diff --git a/.eslintrc.js b/.eslintrc.js index daf49d9d08281..5b7dd6d6d0379 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -64,12 +64,6 @@ module.exports = { 'jsx-a11y/no-onchange': 'off', }, }, - { - files: ['src/core/public/application/**/*.{js,ts,tsx}'], - rules: { - 'react/no-danger': 'off', - }, - }, { files: ['src/legacy/core_plugins/console/**/*.{js,ts,tsx}'], rules: { diff --git a/Jenkinsfile b/Jenkinsfile index c002832d4d51a..6030f2b4a021d 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -4,7 +4,7 @@ library 'kibana-pipeline-library' kibanaLibrary.load() stage("Kibana Pipeline") { // This stage is just here to help the BlueOcean UI a little bit - timeout(time: 180, unit: 'MINUTES') { + timeout(time: 120, unit: 'MINUTES') { timestamps { ansiColor('xterm') { catchError { diff --git a/docs/apm/advanced-queries.asciidoc b/docs/apm/advanced-queries.asciidoc index 815e731760785..1f064c1cad3fd 100644 --- a/docs/apm/advanced-queries.asciidoc +++ b/docs/apm/advanced-queries.asciidoc @@ -10,7 +10,7 @@ so it's easy to share a specific query or view with others. In the screenshot below, you can begin to see some of the transaction fields available for filtering on: [role="screenshot"] -image::apm/images/apm-query-bar.png[Example of the Kibana Query bar in APM UI in Kibana] +image::apm/images/apm-query-bar.png[Example of the Kibana Query bar in APM app in Kibana] [float] ==== Example queries diff --git a/docs/apm/agent-configuration.asciidoc b/docs/apm/agent-configuration.asciidoc index 4d2ae5d01688c..6f147d0e3223a 100644 --- a/docs/apm/agent-configuration.asciidoc +++ b/docs/apm/agent-configuration.asciidoc @@ -2,18 +2,15 @@ [[agent-configuration]] === APM Agent configuration -beta[] APM Agent configuration allows you to fine-tune your agent configuration directly in Kibana. +APM Agent configuration allows you to fine-tune your agent configuration directly in Kibana. Best of all, changes are automatically propagated to your APM agents so there's no need to redeploy. -To get started, simply choose the service and environment you wish to configure. +To get started, simply choose the services and environments you wish to configure. +The APM app will let you know when your configurations have been applied by your agents. [role="screenshot"] image::apm/images/apm-agent-configuration.png[APM Agent configuration in Kibana] -IMPORTANT: As this feature is in Beta, a limited number of configuration settings are supported. -We recommend you watch your agent logs to confirm that configuration has been applied. -If you have feedback, please reach out in our https://discuss.elastic.co/c/apm[Discuss forum]. - [float] ==== Precedence @@ -34,6 +31,26 @@ Kibana communicates any changed settings to APM Server so that your agents only [float] ==== Supported configurations +[float] +===== `CAPTURE_BODY` + +added[7.5.0] Can be `"off"`, `"errors"`, `"transactions"`, or `"all"`. Defaults to `"off"`. + +For transactions that are HTTP requests, the Agent can optionally capture the request body, e.g., POST variables. +Remember, request bodies often contain sensitive values like passwords, credit card numbers, etc. +If your service handles sensitive data, enable this feature with care. +Turning on body capturing can also significantly increase the overhead the overhead of the Agent, +and the Elasticsearch index size. + +[float] +===== `TRANSACTION_MAX_SPANS` + +added[7.5.0] A number between `0` and `32000`. Defaults to `500`. + +Limit the number of spans that are recorded per transaction. +This is helpful in cases where a transaction creates a very high amount of spans, e.g., thousands of SQL queries. +Setting an upper limit will help prevent the Agent and the APM Server from being overloaded. + [float] ===== `TRANSACTION_SAMPLE_RATE` diff --git a/docs/apm/errors.asciidoc b/docs/apm/errors.asciidoc index e80438975cba0..689fa1fffa89e 100644 --- a/docs/apm/errors.asciidoc +++ b/docs/apm/errors.asciidoc @@ -10,12 +10,12 @@ This makes it very easy to quickly see which errors are affecting your services, and to take actions to rectify them. [role="screenshot"] -image::apm/images/apm-errors-overview.png[Example view of the errors overview in the APM UI in Kibana] +image::apm/images/apm-errors-overview.png[Example view of the errors overview in the APM app in Kibana] Selecting an error group ID or error message brings you to the *Error group*. [role="screenshot"] -image::apm/images/apm-error-group.png[Example view of the error group page in the APM UI in Kibana] +image::apm/images/apm-error-group.png[Example view of the error group page in the APM app in Kibana] Here, you'll see the error message, culprit, and the number of occurrences over time. @@ -43,4 +43,4 @@ With Watcher, your team can set up reports within minutes. Watches are managed separately in the dedicated Watcher UI available in Advanced Settings. [role="screenshot"] -image::apm/images/apm-errors-watcher-assistant.png[Example view of the Watcher assistant for errors in APM UI in Kibana] \ No newline at end of file +image::apm/images/apm-errors-watcher-assistant.png[Example view of the Watcher assistant for errors in APM app in Kibana] \ No newline at end of file diff --git a/docs/apm/getting-started.asciidoc b/docs/apm/getting-started.asciidoc index 8f1265b73a8f4..4a391f1a49672 100644 --- a/docs/apm/getting-started.asciidoc +++ b/docs/apm/getting-started.asciidoc @@ -10,7 +10,7 @@ image::apm/images/apm-setup.png[Installation instructions on the APM page in Kib Index patterns tell Kibana which Elasticsearch indices you want to explore. -An APM index pattern is necessary for certain features in the APM UI, like the query bar. +An APM index pattern is necessary for certain features in the APM app, like the query bar. To set up the correct index pattern, simply click *Load Kibana objects* at the bottom of the Setup Instructions. diff --git a/docs/apm/images/apm-metrics.png b/docs/apm/images/apm-metrics.png index a75702ad570d0..6a9789b5a6ecd 100644 Binary files a/docs/apm/images/apm-metrics.png and b/docs/apm/images/apm-metrics.png differ diff --git a/docs/apm/images/jvm-metrics.png b/docs/apm/images/jvm-metrics.png new file mode 100644 index 0000000000000..ffeab27e10246 Binary files /dev/null and b/docs/apm/images/jvm-metrics.png differ diff --git a/docs/apm/metrics.asciidoc b/docs/apm/metrics.asciidoc index 3fc63d6a1344a..ab394b785ef84 100644 --- a/docs/apm/metrics.asciidoc +++ b/docs/apm/metrics.asciidoc @@ -2,13 +2,21 @@ === Metrics overview The *Metrics* overview provides agent-specific metrics, -which lets you perform more in-depth root cause analysis investigations within the APM UI. +which lets you perform more in-depth root cause analysis investigations within the APM app. If you're experiencing a problem with your service, you can use this page to attempt to find the underlying cause. For example, you might be able to correlate a high number of errors with a long transaction duration, high CPU usage, or a memory leak. [role="screenshot"] -image::apm/images/apm-metrics.png[Example view of the Metrics overview in APM UI in Kibana] +image::apm/images/apm-metrics.png[Example view of the Metrics overview in APM app in Kibana] + +If you're using the Java Agent, the metrics view focuses on JVMs. +A detailed view of metrics per JVM makes it much easier to analyze the provided metrics: +CPU usage, memory usage, heap or non-heap memory, +thread count, garbage collection rate, and garbage collection time spent per minute. + +[role="screenshot"] +image::apm/images/jvm-metrics.png[Example view of the Metrics overview for the Java Agent] [[machine-learning-integration]] === Machine Learning integration @@ -17,7 +25,7 @@ The Machine Learning integration will initiate a new job predefined to calculate The response time graph will show the expected bounds and annotate the graph when the anomaly score is 75 or above. [role="screenshot"] -image::apm/images/apm-ml-integration.png[Example view of anomaly scores on response times in APM UI in Kibana] +image::apm/images/apm-ml-integration.png[Example view of anomaly scores on response times in APM app in Kibana] Jobs can be created per transaction type and based on the average response time. You can manage jobs in the *Machine Learning jobs management*. diff --git a/docs/apm/services.asciidoc b/docs/apm/services.asciidoc index a6620b5cea7b7..9af3e74562dab 100644 --- a/docs/apm/services.asciidoc +++ b/docs/apm/services.asciidoc @@ -6,4 +6,4 @@ The *Services* overview gives you quick insights into the health and general per You can add services by setting the `service.name` configuration in each of the {apm-agents-ref}[APM agents] you’re instrumenting. [role="screenshot"] -image::apm/images/apm-services-overview.png[Example view of services table the APM UI in Kibana] \ No newline at end of file +image::apm/images/apm-services-overview.png[Example view of services table the APM app in Kibana] \ No newline at end of file diff --git a/docs/apm/spans.asciidoc b/docs/apm/spans.asciidoc index d23c4f5f4caea..75eae61b4cf12 100644 --- a/docs/apm/spans.asciidoc +++ b/docs/apm/spans.asciidoc @@ -9,7 +9,7 @@ The span timeline visualization is a bird's-eye view of what your application wa This makes it useful for visualizing where the selected transaction spent most of its time. [role="screenshot"] -image::apm/images/apm-distributed-tracing.png[Example view of the distributed tracing in APM UI in Kibana] +image::apm/images/apm-distributed-tracing.png[Example view of the distributed tracing in APM app in Kibana] View a span in detail by clicking on it in the timeline waterfall. For example, in the below screenshot we've clicked on an SQL Select database query. @@ -20,13 +20,13 @@ Finally, APM knows which files are your code and which are just modules or libra These library frames will be minimized by default in order to show you the most relevant stack trace. [role="screenshot"] -image::apm/images/apm-span-detail.png[Example view of a span detail in the APM UI in Kibana] +image::apm/images/apm-span-detail.png[Example view of a span detail in the APM app in Kibana] If your span timeline is colorful, it's indicative of a <>. Services in a distributed trace are separated by color and listed in the order they occur. [role="screenshot"] -image::apm/images/apm-services-trace.png[Example of distributed trace colors in the APM UI in Kibana] +image::apm/images/apm-services-trace.png[Example of distributed trace colors in the APM app in Kibana] Don't forget, a distributed trace includes more than one transaction. When viewing these distributed traces in the timeline waterfall, you'll see this image:apm/images/transaction-icon.png[APM icon] icon, @@ -37,4 +37,4 @@ After exploring these traces, you can return to the full trace by clicking *View full trace* in the upper right hand corner of the page. [role="screenshot"] -image::apm/images/apm-transaction-sample.png[Example of distributed trace colors in the APM UI in Kibana] +image::apm/images/apm-transaction-sample.png[Example of distributed trace colors in the APM app in Kibana] diff --git a/docs/apm/traces.asciidoc b/docs/apm/traces.asciidoc index 214b997818503..09d8f52b92840 100644 --- a/docs/apm/traces.asciidoc +++ b/docs/apm/traces.asciidoc @@ -11,7 +11,7 @@ it's the collective amount of pain a specific endpoint is causing your users. If there's a particular endpoint you're worried about, you can click on it to view the <>. [role="screenshot"] -image::apm/images/apm-traces.png[Example view of the Traces overview in APM UI in Kibana] +image::apm/images/apm-traces.png[Example view of the Traces overview in APM app in Kibana] [float] [[distributed-tracing]] @@ -22,7 +22,7 @@ Distributed tracing is a key feature of modern application performance monitorin service-based architectures. Distributed tracing allows APM users to automatically trace requests all the way through the service architecture, -and visualize those traces in one single view in the APM UI. +and visualize those traces in one single view in the APM app. This is accomplished by tracing all of the requests, from the initial web request to your front-end service, to queries made to your back-end services. This makes finding possible bottlenecks throughout your application much easier and faster. @@ -31,6 +31,6 @@ By definition, a distributed trace includes more than one transaction. You can use the <> to view a waterfall display of all of the transactions from individual services that are connected in a trace. [role="screenshot"] -image::apm/images/apm-distributed-tracing.png[Example view of the distributed tracing in APM UI in Kibana] +image::apm/images/apm-distributed-tracing.png[Example view of the distributed tracing in APM app in Kibana] TIP: Distributed tracing is supported by all APM agents and there’s no additional configuration needed. \ No newline at end of file diff --git a/docs/apm/transactions.asciidoc b/docs/apm/transactions.asciidoc index e70587baa65ea..33f61adc8be63 100644 --- a/docs/apm/transactions.asciidoc +++ b/docs/apm/transactions.asciidoc @@ -10,9 +10,9 @@ The *Transactions* table, however, provides only a list of _transaction groups_ In other words, this view groups all transactions of the same name together, and only displays one transaction for each group. [role="screenshot"] -image::apm/images/apm-transactions-overview.png[Example view of transactions table in the APM UI in Kibana] +image::apm/images/apm-transactions-overview.png[Example view of transactions table in the APM app in Kibana] -*Time spent by span type* -- beta[] Certain agents support breakdown graphs in the APM UI. +*Time spent by span type* -- Most agents support breakdown graphs in the APM app. This graph is an easy way to visualize where your application is spending most of its time. For example, is your app spending time in external calls, database processing, or application code execution? @@ -22,8 +22,6 @@ This could be a sign that the agent does not have auto-instrumentation for whate It's important to note that if you have asynchronous spans, the sum of all span times may exceed the duration of the transaction. -TIP: If the *Time spent by span type* chart is missing in the APM UI, it means your agent does not support this feature yet. - *Transaction duration* shows the response times for this service and is broken down into average, 95th, and 99th percentile. If there's a weird spike that you'd like to investigate, you can simply zoom in on the graph - this will adjust the specific time range, diff --git a/docs/developer/add-data-guide.asciidoc b/docs/developer/add-data-guide.asciidoc index 9c44ae9c9ded3..aec44a9537ee8 100644 --- a/docs/developer/add-data-guide.asciidoc +++ b/docs/developer/add-data-guide.asciidoc @@ -11,10 +11,13 @@ Each tutorial contains three sets of instructions: [float] === Creating a new tutorial +// TODO: update path to where the directory must be created on the new platform 1. Create a new directory in the link:https://github.com/elastic/kibana/tree/master/src/legacy/core_plugins/kibana/server/tutorials[tutorials directory]. 2. In the new directory, create a file called `index.js` that exports a function. -The function must return a JavaScript object that conforms to the link:https://github.com/elastic/kibana/blob/master/src/legacy/core_plugins/kibana/common/tutorials/tutorial_schema.js[tutorial schema]. -3. Register the tutorial in link:https://github.com/elastic/kibana/blob/master/src/legacy/core_plugins/kibana/server/tutorials/register.js[register.js] by calling `server.registerTutorial(myFuncImportedFromIndexJs)`. +The function must return a JavaScript object that conforms to the link:https://github.com/elastic/kibana/blob/master/src/plugins/home/server/services/tutorials/lib/tutorial_schema.ts[tutorial schema]. +// TODO: update path to where the tutorial must be registered on the new platform +3. Register the tutorial in link:https://github.com/elastic/kibana/blob/master/src/legacy/core_plugins/kibana/server/tutorials/register.js[register.js] by calling `server.newPlatform.setup.plugins.home.tutorials.registerTutorial(myFuncImportedFromIndexJs)`. +// TODO: update path to where the image assets must be added on the new platform 4. Add image assets to the link:https://github.com/elastic/kibana/tree/master/src/legacy/core_plugins/kibana/public/home/tutorial_resources[tutorial_resources directory]. 5. Run Kibana locally to preview the tutorial. 6. Create a PR and go through the review process to get the changes approved. diff --git a/docs/developer/plugin/development-uiexports.asciidoc b/docs/developer/plugin/development-uiexports.asciidoc index de713416ae2cd..6368446f7fb43 100644 --- a/docs/developer/plugin/development-uiexports.asciidoc +++ b/docs/developer/plugin/development-uiexports.asciidoc @@ -8,7 +8,6 @@ An aggregate list of available UiExport types: | Type | Purpose | hacks | Any module that should be included in every application | visTypes | Modules that register providers with the `ui/registry/vis_types` registry. -| fieldFormats | Modules that register providers with the `ui/registry/field_formats` registry. | inspectorViews | Modules that register custom inspector views via the `viewRegistry` in `ui/inspector`. | chromeNavControls | Modules that register providers with the `ui/registry/chrome_nav_controls` registry. | navbarExtensions | Modules that register providers with the `ui/registry/navbar_extensions` registry. diff --git a/docs/development/core/public/kibana-plugin-public.chromehelpextension.appname.md b/docs/development/core/public/kibana-plugin-public.chromehelpextension.appname.md new file mode 100644 index 0000000000000..d817238c9287d --- /dev/null +++ b/docs/development/core/public/kibana-plugin-public.chromehelpextension.appname.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [ChromeHelpExtension](./kibana-plugin-public.chromehelpextension.md) > [appName](./kibana-plugin-public.chromehelpextension.appname.md) + +## ChromeHelpExtension.appName property + +Provide your plugin's name to create a header for separation + +Signature: + +```typescript +appName: string; +``` diff --git a/docs/development/core/public/kibana-plugin-public.chromehelpextension.content.md b/docs/development/core/public/kibana-plugin-public.chromehelpextension.content.md new file mode 100644 index 0000000000000..b51d4928e991d --- /dev/null +++ b/docs/development/core/public/kibana-plugin-public.chromehelpextension.content.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [ChromeHelpExtension](./kibana-plugin-public.chromehelpextension.md) > [content](./kibana-plugin-public.chromehelpextension.content.md) + +## ChromeHelpExtension.content property + +Custom content to occur below the list of links + +Signature: + +```typescript +content?: (element: HTMLDivElement) => () => void; +``` diff --git a/docs/development/core/public/kibana-plugin-public.chromehelpextension.links.md b/docs/development/core/public/kibana-plugin-public.chromehelpextension.links.md new file mode 100644 index 0000000000000..de17ca8d86e37 --- /dev/null +++ b/docs/development/core/public/kibana-plugin-public.chromehelpextension.links.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [ChromeHelpExtension](./kibana-plugin-public.chromehelpextension.md) > [links](./kibana-plugin-public.chromehelpextension.links.md) + +## ChromeHelpExtension.links property + +Creates unified links for sending users to documentation, GitHub, Discuss, or a custom link/button + +Signature: + +```typescript +links?: ChromeHelpExtensionMenuLink[]; +``` diff --git a/docs/development/core/public/kibana-plugin-public.chromehelpextension.md b/docs/development/core/public/kibana-plugin-public.chromehelpextension.md index 82e7ba9bec4a3..6f0007335c555 100644 --- a/docs/development/core/public/kibana-plugin-public.chromehelpextension.md +++ b/docs/development/core/public/kibana-plugin-public.chromehelpextension.md @@ -2,11 +2,20 @@ [Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [ChromeHelpExtension](./kibana-plugin-public.chromehelpextension.md) -## ChromeHelpExtension type +## ChromeHelpExtension interface Signature: ```typescript -export declare type ChromeHelpExtension = (element: HTMLDivElement) => () => void; +export interface ChromeHelpExtension ``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [appName](./kibana-plugin-public.chromehelpextension.appname.md) | string | Provide your plugin's name to create a header for separation | +| [content](./kibana-plugin-public.chromehelpextension.content.md) | (element: HTMLDivElement) => () => void | Custom content to occur below the list of links | +| [links](./kibana-plugin-public.chromehelpextension.links.md) | ChromeHelpExtensionMenuLink[] | Creates unified links for sending users to documentation, GitHub, Discuss, or a custom link/button | + diff --git a/docs/development/core/public/kibana-plugin-public.chromehelpextensionmenucustomlink.md b/docs/development/core/public/kibana-plugin-public.chromehelpextensionmenucustomlink.md new file mode 100644 index 0000000000000..daca70f3b79c1 --- /dev/null +++ b/docs/development/core/public/kibana-plugin-public.chromehelpextensionmenucustomlink.md @@ -0,0 +1,15 @@ + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [ChromeHelpExtensionMenuCustomLink](./kibana-plugin-public.chromehelpextensionmenucustomlink.md) + +## ChromeHelpExtensionMenuCustomLink type + + +Signature: + +```typescript +export declare type ChromeHelpExtensionMenuCustomLink = EuiButtonEmptyProps & { + linkType: 'custom'; + content: React.ReactNode; +}; +``` diff --git a/docs/development/core/public/kibana-plugin-public.chromehelpextensionmenudiscusslink.md b/docs/development/core/public/kibana-plugin-public.chromehelpextensionmenudiscusslink.md new file mode 100644 index 0000000000000..8dd1c796bebf1 --- /dev/null +++ b/docs/development/core/public/kibana-plugin-public.chromehelpextensionmenudiscusslink.md @@ -0,0 +1,15 @@ + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [ChromeHelpExtensionMenuDiscussLink](./kibana-plugin-public.chromehelpextensionmenudiscusslink.md) + +## ChromeHelpExtensionMenuDiscussLink type + + +Signature: + +```typescript +export declare type ChromeHelpExtensionMenuDiscussLink = EuiButtonEmptyProps & { + linkType: 'discuss'; + href: string; +}; +``` diff --git a/docs/development/core/public/kibana-plugin-public.chromehelpextensionmenudocumentationlink.md b/docs/development/core/public/kibana-plugin-public.chromehelpextensionmenudocumentationlink.md new file mode 100644 index 0000000000000..0114cc245a874 --- /dev/null +++ b/docs/development/core/public/kibana-plugin-public.chromehelpextensionmenudocumentationlink.md @@ -0,0 +1,15 @@ + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [ChromeHelpExtensionMenuDocumentationLink](./kibana-plugin-public.chromehelpextensionmenudocumentationlink.md) + +## ChromeHelpExtensionMenuDocumentationLink type + + +Signature: + +```typescript +export declare type ChromeHelpExtensionMenuDocumentationLink = EuiButtonEmptyProps & { + linkType: 'documentation'; + href: string; +}; +``` diff --git a/docs/development/core/public/kibana-plugin-public.chromehelpextensionmenugithublink.md b/docs/development/core/public/kibana-plugin-public.chromehelpextensionmenugithublink.md new file mode 100644 index 0000000000000..5dd33f1a05a7f --- /dev/null +++ b/docs/development/core/public/kibana-plugin-public.chromehelpextensionmenugithublink.md @@ -0,0 +1,16 @@ + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [ChromeHelpExtensionMenuGitHubLink](./kibana-plugin-public.chromehelpextensionmenugithublink.md) + +## ChromeHelpExtensionMenuGitHubLink type + + +Signature: + +```typescript +export declare type ChromeHelpExtensionMenuGitHubLink = EuiButtonEmptyProps & { + linkType: 'github'; + labels: string[]; + title?: string; +}; +``` diff --git a/docs/development/core/public/kibana-plugin-public.chromehelpextensionmenulink.md b/docs/development/core/public/kibana-plugin-public.chromehelpextensionmenulink.md new file mode 100644 index 0000000000000..072ce165e23c5 --- /dev/null +++ b/docs/development/core/public/kibana-plugin-public.chromehelpextensionmenulink.md @@ -0,0 +1,12 @@ + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [ChromeHelpExtensionMenuLink](./kibana-plugin-public.chromehelpextensionmenulink.md) + +## ChromeHelpExtensionMenuLink type + + +Signature: + +```typescript +export declare type ChromeHelpExtensionMenuLink = ExclusiveUnion>>; +``` diff --git a/docs/development/core/public/kibana-plugin-public.md b/docs/development/core/public/kibana-plugin-public.md index cec307032094e..22794ca945540 100644 --- a/docs/development/core/public/kibana-plugin-public.md +++ b/docs/development/core/public/kibana-plugin-public.md @@ -33,6 +33,7 @@ The plugin integrates with the core system via lifecycle events: `setup` | [ChromeBadge](./kibana-plugin-public.chromebadge.md) | | | [ChromeBrand](./kibana-plugin-public.chromebrand.md) | | | [ChromeDocTitle](./kibana-plugin-public.chromedoctitle.md) | APIs for accessing and updating the document title. | +| [ChromeHelpExtension](./kibana-plugin-public.chromehelpextension.md) | | | [ChromeNavControl](./kibana-plugin-public.chromenavcontrol.md) | | | [ChromeNavControls](./kibana-plugin-public.chromenavcontrols.md) | [APIs](./kibana-plugin-public.chromenavcontrols.md) for registering new controls to be displayed in the navigation bar. | | [ChromeNavLink](./kibana-plugin-public.chromenavlink.md) | | @@ -98,7 +99,11 @@ The plugin integrates with the core system via lifecycle events: `setup` | --- | --- | | [AppUnmount](./kibana-plugin-public.appunmount.md) | A function called when an application should be unmounted from the page. This function should be synchronous. | | [ChromeBreadcrumb](./kibana-plugin-public.chromebreadcrumb.md) | | -| [ChromeHelpExtension](./kibana-plugin-public.chromehelpextension.md) | | +| [ChromeHelpExtensionMenuCustomLink](./kibana-plugin-public.chromehelpextensionmenucustomlink.md) | | +| [ChromeHelpExtensionMenuDiscussLink](./kibana-plugin-public.chromehelpextensionmenudiscusslink.md) | | +| [ChromeHelpExtensionMenuDocumentationLink](./kibana-plugin-public.chromehelpextensionmenudocumentationlink.md) | | +| [ChromeHelpExtensionMenuGitHubLink](./kibana-plugin-public.chromehelpextensionmenugithublink.md) | | +| [ChromeHelpExtensionMenuLink](./kibana-plugin-public.chromehelpextensionmenulink.md) | | | [ChromeNavLinkUpdateableFields](./kibana-plugin-public.chromenavlinkupdateablefields.md) | | | [HandlerContextType](./kibana-plugin-public.handlercontexttype.md) | Extracts the type of the first argument of a [HandlerFunction](./kibana-plugin-public.handlerfunction.md) to represent the type of the context. | | [HandlerFunction](./kibana-plugin-public.handlerfunction.md) | A function that accepts a context object and an optional number of additional arguments. Used for the generic types in [IContextContainer](./kibana-plugin-public.icontextcontainer.md) | diff --git a/docs/development/core/public/kibana-plugin-public.plugininitializercontext.config.md b/docs/development/core/public/kibana-plugin-public.plugininitializercontext.config.md new file mode 100644 index 0000000000000..28141c9e13749 --- /dev/null +++ b/docs/development/core/public/kibana-plugin-public.plugininitializercontext.config.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [PluginInitializerContext](./kibana-plugin-public.plugininitializercontext.md) > [config](./kibana-plugin-public.plugininitializercontext.config.md) + +## PluginInitializerContext.config property + +Signature: + +```typescript +readonly config: { + get: () => T; + }; +``` diff --git a/docs/development/core/public/kibana-plugin-public.plugininitializercontext.md b/docs/development/core/public/kibana-plugin-public.plugininitializercontext.md index 87c39a502040d..64eaabb28646d 100644 --- a/docs/development/core/public/kibana-plugin-public.plugininitializercontext.md +++ b/docs/development/core/public/kibana-plugin-public.plugininitializercontext.md @@ -9,13 +9,14 @@ The available core services passed to a `PluginInitializer` Signature: ```typescript -export interface PluginInitializerContext +export interface PluginInitializerContext ``` ## Properties | Property | Type | Description | | --- | --- | --- | +| [config](./kibana-plugin-public.plugininitializercontext.config.md) | {
get: <T extends object = ConfigSchema>() => T;
} | | | [env](./kibana-plugin-public.plugininitializercontext.env.md) | {
mode: Readonly<EnvironmentMode>;
packageInfo: Readonly<PackageInfo>;
} | | | [opaqueId](./kibana-plugin-public.plugininitializercontext.opaqueid.md) | PluginOpaqueId | A symbol used to identify this plugin in the system. Needed when registering handlers or context providers. | diff --git a/docs/development/core/server/kibana-plugin-server.md b/docs/development/core/server/kibana-plugin-server.md index 9907750b8742f..c6ab8502acbd2 100644 --- a/docs/development/core/server/kibana-plugin-server.md +++ b/docs/development/core/server/kibana-plugin-server.md @@ -75,6 +75,7 @@ The plugin integrates with the core system via lifecycle events: `setup` | [OnPreAuthToolkit](./kibana-plugin-server.onpreauthtoolkit.md) | A tool set defining an outcome of OnPreAuth interceptor for incoming request. | | [PackageInfo](./kibana-plugin-server.packageinfo.md) | | | [Plugin](./kibana-plugin-server.plugin.md) | The interface that should be returned by a PluginInitializer. | +| [PluginConfigDescriptor](./kibana-plugin-server.pluginconfigdescriptor.md) | Describes a plugin configuration schema and capabilities. | | [PluginInitializerContext](./kibana-plugin-server.plugininitializercontext.md) | Context that's available to plugins during initialization stage. | | [PluginManifest](./kibana-plugin-server.pluginmanifest.md) | Describes the set of required and optional properties plugin can define in its mandatory JSON manifest file. | | [PluginsServiceSetup](./kibana-plugin-server.pluginsservicesetup.md) | | @@ -156,6 +157,7 @@ The plugin integrates with the core system via lifecycle events: `setup` | [MutatingOperationRefreshSetting](./kibana-plugin-server.mutatingoperationrefreshsetting.md) | Elasticsearch Refresh setting for mutating operation | | [OnPostAuthHandler](./kibana-plugin-server.onpostauthhandler.md) | See [OnPostAuthToolkit](./kibana-plugin-server.onpostauthtoolkit.md). | | [OnPreAuthHandler](./kibana-plugin-server.onpreauthhandler.md) | See [OnPreAuthToolkit](./kibana-plugin-server.onpreauthtoolkit.md). | +| [PluginConfigSchema](./kibana-plugin-server.pluginconfigschema.md) | Dedicated type for plugin configuration schema. | | [PluginInitializer](./kibana-plugin-server.plugininitializer.md) | The plugin export at the root of a plugin's server directory should conform to this interface. | | [PluginName](./kibana-plugin-server.pluginname.md) | Dedicated type for plugin name/id that is supposed to make Map/Set/Arrays that use it as a key or value more obvious. | | [PluginOpaqueId](./kibana-plugin-server.pluginopaqueid.md) | | diff --git a/docs/development/core/server/kibana-plugin-server.pluginconfigdescriptor.exposetobrowser.md b/docs/development/core/server/kibana-plugin-server.pluginconfigdescriptor.exposetobrowser.md new file mode 100644 index 0000000000000..d62b2457e9d9a --- /dev/null +++ b/docs/development/core/server/kibana-plugin-server.pluginconfigdescriptor.exposetobrowser.md @@ -0,0 +1,15 @@ + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [PluginConfigDescriptor](./kibana-plugin-server.pluginconfigdescriptor.md) > [exposeToBrowser](./kibana-plugin-server.pluginconfigdescriptor.exposetobrowser.md) + +## PluginConfigDescriptor.exposeToBrowser property + +List of configuration properties that will be available on the client-side plugin. + +Signature: + +```typescript +exposeToBrowser?: { + [P in keyof T]?: boolean; + }; +``` diff --git a/docs/development/core/server/kibana-plugin-server.pluginconfigdescriptor.md b/docs/development/core/server/kibana-plugin-server.pluginconfigdescriptor.md new file mode 100644 index 0000000000000..41fdcfe5df45d --- /dev/null +++ b/docs/development/core/server/kibana-plugin-server.pluginconfigdescriptor.md @@ -0,0 +1,45 @@ + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [PluginConfigDescriptor](./kibana-plugin-server.pluginconfigdescriptor.md) + +## PluginConfigDescriptor interface + +Describes a plugin configuration schema and capabilities. + +Signature: + +```typescript +export interface PluginConfigDescriptor +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [exposeToBrowser](./kibana-plugin-server.pluginconfigdescriptor.exposetobrowser.md) | {
[P in keyof T]?: boolean;
} | List of configuration properties that will be available on the client-side plugin. | +| [schema](./kibana-plugin-server.pluginconfigdescriptor.schema.md) | PluginConfigSchema<T> | Schema to use to validate the plugin configuration.[PluginConfigSchema](./kibana-plugin-server.pluginconfigschema.md) | + +## Example + + +```typescript +// my_plugin/server/index.ts +import { schema, TypeOf } from '@kbn/config-schema'; +import { PluginConfigDescriptor } from 'kibana/server'; + +const configSchema = schema.object({ + secret: schema.string({ defaultValue: 'Only on server' }), + uiProp: schema.string({ defaultValue: 'Accessible from client' }), +}); + +type ConfigType = TypeOf; + +export const config: PluginConfigDescriptor = { + exposeToBrowser: { + uiProp: true, + }, + schema: configSchema, +}; + +``` + diff --git a/docs/development/core/server/kibana-plugin-server.pluginconfigdescriptor.schema.md b/docs/development/core/server/kibana-plugin-server.pluginconfigdescriptor.schema.md new file mode 100644 index 0000000000000..c4845d52ff212 --- /dev/null +++ b/docs/development/core/server/kibana-plugin-server.pluginconfigdescriptor.schema.md @@ -0,0 +1,15 @@ + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [PluginConfigDescriptor](./kibana-plugin-server.pluginconfigdescriptor.md) > [schema](./kibana-plugin-server.pluginconfigdescriptor.schema.md) + +## PluginConfigDescriptor.schema property + +Schema to use to validate the plugin configuration. + +[PluginConfigSchema](./kibana-plugin-server.pluginconfigschema.md) + +Signature: + +```typescript +schema: PluginConfigSchema; +``` diff --git a/docs/development/core/server/kibana-plugin-server.pluginconfigschema.md b/docs/development/core/server/kibana-plugin-server.pluginconfigschema.md new file mode 100644 index 0000000000000..6528798ec8e01 --- /dev/null +++ b/docs/development/core/server/kibana-plugin-server.pluginconfigschema.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [PluginConfigSchema](./kibana-plugin-server.pluginconfigschema.md) + +## PluginConfigSchema type + +Dedicated type for plugin configuration schema. + +Signature: + +```typescript +export declare type PluginConfigSchema = Type; +``` diff --git a/docs/development/core/server/kibana-plugin-server.pluginsservicesetup.md b/docs/development/core/server/kibana-plugin-server.pluginsservicesetup.md index 2b3ff9a2cd419..36d803ddea618 100644 --- a/docs/development/core/server/kibana-plugin-server.pluginsservicesetup.md +++ b/docs/development/core/server/kibana-plugin-server.pluginsservicesetup.md @@ -16,5 +16,6 @@ export interface PluginsServiceSetup | Property | Type | Description | | --- | --- | --- | | [contracts](./kibana-plugin-server.pluginsservicesetup.contracts.md) | Map<PluginName, unknown> | | +| [uiPluginConfigs](./kibana-plugin-server.pluginsservicesetup.uipluginconfigs.md) | Map<PluginName, Observable<unknown>> | | | [uiPlugins](./kibana-plugin-server.pluginsservicesetup.uiplugins.md) | {
public: Map<PluginName, DiscoveredPlugin>;
internal: Map<PluginName, DiscoveredPluginInternal>;
} | | diff --git a/docs/development/core/server/kibana-plugin-server.pluginsservicesetup.uipluginconfigs.md b/docs/development/core/server/kibana-plugin-server.pluginsservicesetup.uipluginconfigs.md new file mode 100644 index 0000000000000..4bd57b873043e --- /dev/null +++ b/docs/development/core/server/kibana-plugin-server.pluginsservicesetup.uipluginconfigs.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [PluginsServiceSetup](./kibana-plugin-server.pluginsservicesetup.md) > [uiPluginConfigs](./kibana-plugin-server.pluginsservicesetup.uipluginconfigs.md) + +## PluginsServiceSetup.uiPluginConfigs property + +Signature: + +```typescript +uiPluginConfigs: Map>; +``` diff --git a/docs/management/advanced-options.asciidoc b/docs/management/advanced-options.asciidoc index 38fceeb47d6fd..977a65f62202d 100644 --- a/docs/management/advanced-options.asciidoc +++ b/docs/management/advanced-options.asciidoc @@ -46,6 +46,7 @@ adapt to the interval between measurements. Keys are http://en.wikipedia.org/wik `dateFormat:tz`:: The timezone that Kibana uses. The default value of `Browser` uses the timezone detected by the browser. `dateNanosFormat`:: The format to use for displaying https://momentjs.com/docs/#/displaying/format/[pretty formatted dates] of {ref}/date_nanos.html[Elasticsearch date_nanos type]. `defaultIndex`:: The index to access if no index is set. The default is `null`. +`defaultRoute`:: The default route when opening Kibana. Use this setting to route users to a specific dashboard, application, or saved object as they enter each space. `fields:popularLimit`:: The top N most popular fields to show. `filterEditor:suggestValues`:: Set this property to `false` to prevent the filter editor from suggesting values for fields. `filters:pinnedByDefault`:: Set this property to `true` to make filters have a global state (be pinned) by default. diff --git a/docs/management/managing-fields.asciidoc b/docs/management/managing-fields.asciidoc index 6bfd36bc1c067..308e61abf70e5 100644 --- a/docs/management/managing-fields.asciidoc +++ b/docs/management/managing-fields.asciidoc @@ -29,7 +29,7 @@ include::field-formatters/url-formatter.asciidoc[] Date fields support the `Date`, `Url`, and `String` formatters. -The `Date` formatter enables you to choose the display format of date stamps using the http://moment.js[moment.js] +The `Date` formatter enables you to choose the display format of date stamps using the https://momentjs.com/[moment.js] standard format definitions. include::field-formatters/string-formatter.asciidoc[] @@ -65,7 +65,7 @@ the https://adamwdraper.github.io/Numeral-js/[numeral.js] standard format defini Scripted fields compute data on the fly from the data in your Elasticsearch indices. Scripted field data is shown on the Discover tab as part of the document data, and you can use scripted fields in your visualizations. Scripted field values are computed at query time so they aren't indexed and cannot be searched using Kibana's default -query language. However they can be queried using Kibana's new <>. Scripted +query language. However they can be queried using Kibana's new <>. Scripted fields are also supported in the filter bar. WARNING: Computing data on the fly with scripted fields can be very resource intensive and can have a direct impact on diff --git a/docs/settings/monitoring-settings.asciidoc b/docs/settings/monitoring-settings.asciidoc index 68dd9a8b3cefb..2fc74d2ffee32 100644 --- a/docs/settings/monitoring-settings.asciidoc +++ b/docs/settings/monitoring-settings.asciidoc @@ -45,14 +45,26 @@ production cluster as well as monitor data sent to a dedicated monitoring cluster. `xpack.monitoring.elasticsearch.username`:: -Specifies the user ID that {kib} uses for authentication when it retrieves data -from the monitoring cluster. If not set, {kib} uses the value of the -`elasticsearch.username` setting. +Specifies the username used by {kib} monitoring to establish a persistent connection +in {kib} to the {es} monitoring cluster and to verify licensing status on the {es} +monitoring cluster. + +Every other request performed by the Stack Monitoring UI to the monitoring {es} +cluster uses the authenticated user's credentials, which must be the same on +both the {es} monitoring cluster and the {es} production cluster. + +If not set, {kib} uses the value of the `elasticsearch.username` setting. `xpack.monitoring.elasticsearch.password`:: -Specifies the password that {kib} uses for authentication when it retrieves data -from the monitoring cluster. If not set, {kib} uses the value of the -`elasticsearch.password` setting. +Specifies the password used by {kib} monitoring to establish a persistent connection +in {kib} to the {es} monitoring cluster and to verify licensing status on the {es} +monitoring cluster. + +Every other request performed by the Stack Monitoring UI to the monitoring {es} +cluster uses the authenticated user's credentials, which must be the same on +both the {es} monitoring cluster and the {es} production cluster. + +If not set, {kib} uses the value of the `elasticsearch.password` setting. `telemetry.enabled`:: Set to `true` (default) to send cluster statistics to Elastic. Reporting your diff --git a/docs/setup/install/brew.asciidoc b/docs/setup/install/brew.asciidoc index ad531a83d3690..3fe104bd04794 100644 --- a/docs/setup/install/brew.asciidoc +++ b/docs/setup/install/brew.asciidoc @@ -32,13 +32,13 @@ and data directory are stored in the following locations. | Type | Description | Default Location | Setting | home | Kibana home directory or `$KIBANA_HOME` - | /usr/local/var/homebrew/linked/kibana + | /usr/local/var/homebrew/linked/kibana-full d| | bin | Binary scripts including `kibana` to start a node and `kibana-plugin` to install plugins - | /usr/local/var/homebrew/linked/kibana/bin + | /usr/local/var/homebrew/linked/kibana-full/bin d| | conf @@ -59,7 +59,7 @@ and data directory are stored in the following locations. | plugins | Plugin files location. Each plugin will be contained in a subdirectory. - | /usr/local/var/homebrew/linked/kibana/plugins + | /usr/local/var/homebrew/linked/kibana-full/plugins d| |======================================================================= diff --git a/docs/spaces/index.asciidoc b/docs/spaces/index.asciidoc index fc858eb6d86ef..69655aac521e7 100644 --- a/docs/spaces/index.asciidoc +++ b/docs/spaces/index.asciidoc @@ -22,6 +22,7 @@ Kibana supports spaces in several ways. You can: * <> * <> * <> +* <> * <> [float] @@ -108,6 +109,13 @@ interface. {kib} also has beta <> and <> APIs if you want to automate this process. +[float] +[[spaces-default-route]] +=== Configure a Space-level landing page + +You can create a custom experience for users by configuring the {kib} landing page on a per-space basis. +The landing page can route users to a specific dashboard, application, or saved object as they enter each space. +To configure the landing page, use the `defaultRoute` setting in < Advanced settings>>. [float] [[spaces-delete-started]] diff --git a/package.json b/package.json index f34b283076edd..1b62446e17086 100644 --- a/package.json +++ b/package.json @@ -109,7 +109,7 @@ "@elastic/charts": "^14.0.0", "@elastic/datemath": "5.0.2", "@elastic/ems-client": "1.0.5", - "@elastic/eui": "14.9.0", + "@elastic/eui": "16.0.0", "@elastic/filesaver": "1.1.2", "@elastic/good": "8.1.1-kibana2", "@elastic/numeral": "2.3.3", @@ -132,7 +132,7 @@ "@types/recompose": "^0.30.5", "JSONStream": "1.3.5", "abortcontroller-polyfill": "^1.3.0", - "angular": "^1.7.8", + "angular": "^1.7.9", "angular-aria": "^1.7.8", "angular-elastic": "^2.5.1", "angular-recursion": "^1.0.5", @@ -340,7 +340,7 @@ "@types/semver": "^5.5.0", "@types/sinon": "^7.0.13", "@types/strip-ansi": "^3.0.0", - "@types/styled-components": "^3.0.2", + "@types/styled-components": "^4.4.0", "@types/supertest": "^2.0.5", "@types/supertest-as-promised": "^2.0.38", "@types/type-detect": "^4.0.1", @@ -366,9 +366,9 @@ "dedent": "^0.7.0", "delete-empty": "^2.0.0", "enzyme": "^3.10.0", - "enzyme-adapter-react-16": "^1.14.0", - "enzyme-adapter-utils": "^1.12.0", - "enzyme-to-json": "^3.3.4", + "enzyme-adapter-react-16": "^1.15.1", + "enzyme-adapter-utils": "^1.12.1", + "enzyme-to-json": "^3.4.3", "eslint": "^6.5.1", "eslint-config-prettier": "^6.4.0", "eslint-plugin-babel": "^5.3.0", @@ -421,7 +421,7 @@ "license-checker": "^16.0.0", "listr": "^0.14.1", "load-grunt-config": "^3.0.1", - "mocha": "6.2.1", + "mocha": "^6.2.2", "multistream": "^2.1.1", "murmurhash3js": "3.0.1", "mutation-observer": "^1.0.3", diff --git a/packages/kbn-es/README.md b/packages/kbn-es/README.md index 0d9af2442ebf4..4d4c2aa94db07 100644 --- a/packages/kbn-es/README.md +++ b/packages/kbn-es/README.md @@ -59,4 +59,62 @@ Cloned location of elasticsearch repository, used when running from source Type: `String` -Location where snapshots are cached \ No newline at end of file +Location where snapshots are cached + +## Snapshot Pinning + +Sometimes we need to pin snapshots for a specific version. We'd really like to get this automated, but until that is completed here are the steps to take to build, upload, and switch to pinned snapshots for a branch. + +To use these steps you'll need to setup the google-cloud-sdk, which can be installed on macOS with `brew cask install google-cloud-sdk`. Login with the CLI and you'll have access to the `gsutil` to do efficient/parallel uploads to GCS from the command line. + + 1. Clone the elasticsearch repo somewhere + 2. Checkout the branch you want to build + 3. Run the following to delete old distributables + + ``` + find distribution/archives -type f \( -name 'elasticsearch-*-*.tar.gz' -o -name 'elasticsearch-*-*.zip' \) -not -path *no-jdk* -exec rm {} \; + ``` + + 4. Build the new artifacts + + ``` + ./gradlew -p distribution/archives assemble --parallel + ``` + + 4. Copy new artifacts to your `~/Downloads/tmp-artifacts` + + ``` + rm -rf ~/Downloads/tmp-artifacts + mkdir ~/Downloads/tmp-artifacts + find distribution/archives -type f \( -name 'elasticsearch-*-*.tar.gz' -o -name 'elasticsearch-*-*.zip' \) -not -path *no-jdk* -exec cp {} ~/Downloads/tmp-artifacts \; + ``` + + 5. Calculate shasums of the uploads + + ``` + cd ~/Downloads/tmp-artifacts + find * -exec bash -c "shasum -a 512 {} > {}.sha512" \; + ``` + + 6. Check that the files in `~/Downloads/tmp-artifacts` look reasonable + 7. Upload the files to GCS + + ``` + gsutil -m rsync . gs://kibana-ci-tmp-artifacts/ + ``` + + 8. Once the artifacts are uploaded, modify `packages/kbn-es/src/custom_snapshots.js` in a PR to use a URL formatted like: + + ``` + // force use of manually created snapshots until ReindexPutMappings fix + if (!process.env.KBN_ES_SNAPSHOT_URL && !process.argv.some(isVersionFlag)) { + // return undefined; + return 'https://storage.googleapis.com/kibana-ci-tmp-artifacts/{name}-{version}-{os}-x86_64.{ext}'; + } + ``` + + For 6.8, the format of the url should look like: + + ``` + 'https://storage.googleapis.com/kibana-ci-tmp-artifacts/{name}-{version}.{ext}'; + ``` \ No newline at end of file diff --git a/src/core/MIGRATION.md b/src/core/MIGRATION.md index 0dcc8d55d31a4..f3532cd717ac8 100644 --- a/src/core/MIGRATION.md +++ b/src/core/MIGRATION.md @@ -9,6 +9,7 @@ - [Challenges on the server](#challenges-on-the-server) - [Challenges in the browser](#challenges-in-the-browser) - [Plan of action](#plan-of-action) + - [Shared application plugins](#shared-application-plugins) - [Server-side plan of action](#server-side-plan-of-action) - [De-couple from hapi.js server and request objects](#de-couple-from-hapijs-server-and-request-objects) - [Introduce new plugin definition shim](#introduce-new-plugin-definition-shim) @@ -314,6 +315,43 @@ First, decouple your plugin's business logic from the dependencies that are not Once those things are finished for any given plugin, it can officially be switched to the new plugin system. +### Shared application plugins + +Some services have been already moved to the new platform. + +Below you can find their new locations: + +| Service | Old place | New place in the NP | +| --------------- | ----------------------------------------- | --------------------------------------------------- | +| *FieldFormats* | ui/registry/field_formats | plugins/data/public | + +The `FieldFormats` service has been moved to the `data` plugin in the New Platform. If your plugin has any imports from `ui/registry/field_formats`, you'll need to update your imports as follows: + +Use it in your New Platform plugin: + +```ts +class MyPlugin { + setup (core, { data }) { + data.fieldFormats.register(myFieldFormat); + // ... + } + start (core, { data }) { + data.fieldFormats.getType(myFieldFormatId); + // ... + } +} +``` + +Or, in your legacy platform plugin, consume it through the `ui/new_platform` module: + +```ts +import { npSetup, npStart } from 'ui/new_platform'; + +npSetup.plugins.data.fieldFormats.register(myFieldFormat); +npStart.plugins.data.fieldFormats.getType(myFieldFormatId); +// ... +``` + ## Server-side plan of action Legacy server-side plugins access functionality from core and other plugins at runtime via function arguments, which is similar to how they must be architected to use the new plugin system. This greatly simplifies the plan of action for migrating server-side plugins. @@ -1112,6 +1150,7 @@ import { npStart: { core } } from 'ui/new_platform'; | `ui/routes` | -- | There is no global routing mechanism. Each app [configures its own routing](/rfcs/text/0004_application_service_mounting.md#complete-example). | | `ui/saved_objects` | [`core.savedObjects`](/docs/development/core/public/kibana-plugin-public.savedobjectsstart.md) | Client API is the same | | `ui/doc_title` | [`core.chrome.docTitle`](/docs/development/core/public/kibana-plugin-public.chromedoctitle.md) | | +| `uiExports/injectedVars` | [Configure plugin](#configure-plugin) and [`PluginConfigDescriptor.exposeToBrowser`](/docs/development/core/server/kibana-plugin-server.pluginconfigdescriptor.exposetobrowser.md) | Can only be used to expose configuration properties | _See also: [Public's CoreStart API Docs](/docs/development/core/public/kibana-plugin-public.corestart.md)_ @@ -1244,6 +1283,43 @@ class MyPlugin { } ``` +If your plugin also have a client-side part, you can also expose configuration properties to it using a whitelisting mechanism with the configuration `exposeToBrowser` property. +```typescript +// my_plugin/server/index.ts +import { schema, TypeOf } from '@kbn/config-schema'; +import { PluginConfigDescriptor } from 'kibana/server'; + +const configSchema = schema.object({ + secret: schema.string({ defaultValue: 'Only on server' }), + uiProp: schema.string({ defaultValue: 'Accessible from client' }), +}); + +type ConfigType = TypeOf; + +export const config: PluginConfigDescriptor = { + exposeToBrowser: { + uiProp: true, + }, + schema: configSchema, +}; +``` + +Configuration containing only the exposed properties will be then available on the client-side using the plugin's `initializerContext`: +```typescript +// my_plugin/public/index.ts +interface ClientConfigType { + uiProp: string; +} + +export class Plugin implements Plugin { + constructor(private readonly initializerContext: PluginInitializerContext) {} + + public async setup(core: CoreSetup, deps: {}) { + const config = this.initializerContext.config.get(); + // ... + } +``` + ### Mock new platform services in tests #### Writing mocks for your plugin diff --git a/src/core/public/application/integration_tests/router.test.tsx b/src/core/public/application/integration_tests/router.test.tsx index e6a1070e1a684..593858851d387 100644 --- a/src/core/public/application/integration_tests/router.test.tsx +++ b/src/core/public/application/integration_tests/router.test.tsx @@ -18,7 +18,6 @@ */ import React from 'react'; -import ReactDOM from 'react-dom'; import { mount, ReactWrapper } from 'enzyme'; import { createMemoryHistory, History } from 'history'; import { BehaviorSubject } from 'rxjs'; @@ -31,13 +30,8 @@ import { AppRouter, AppNotFound } from '../ui'; const createMountHandler = (htmlString: string) => jest.fn(async ({ appBasePath: basename, element: el }: AppMountParameters) => { - ReactDOM.render( -
, - el - ); - return jest.fn(() => ReactDOM.unmountComponentAtNode(el)); + el.innerHTML = `
\nbasename: ${basename}\nhtml: ${htmlString}\n
`; + return jest.fn(() => (el.innerHTML = '')); }); describe('AppContainer', () => { diff --git a/src/core/public/chrome/chrome_service.test.ts b/src/core/public/chrome/chrome_service.test.ts index 3390480e56bdd..9656739421686 100644 --- a/src/core/public/chrome/chrome_service.test.ts +++ b/src/core/public/chrome/chrome_service.test.ts @@ -418,17 +418,20 @@ describe('start', () => { .pipe(toArray()) .toPromise(); - chrome.setHelpExtension(() => () => undefined); + chrome.setHelpExtension({ appName: 'App name', content: () => () => undefined }); chrome.setHelpExtension(undefined); service.stop(); await expect(promise).resolves.toMatchInlineSnapshot(` - Array [ - undefined, - [Function], - undefined, - ] - `); + Array [ + undefined, + Object { + "appName": "App name", + "content": [Function], + }, + undefined, + ] + `); }); }); }); diff --git a/src/core/public/chrome/chrome_service.tsx b/src/core/public/chrome/chrome_service.tsx index e686f03413dd5..cc23b79e1c621 100644 --- a/src/core/public/chrome/chrome_service.tsx +++ b/src/core/public/chrome/chrome_service.tsx @@ -36,6 +36,7 @@ import { NavControlsService, ChromeNavControls } from './nav_controls'; import { DocTitleService, ChromeDocTitle } from './doc_title'; import { LoadingIndicator, HeaderWrapper as Header } from './ui'; import { DocLinksStart } from '../doc_links'; +import { ChromeHelpExtensionMenuLink } from './ui/header/header_help_menu'; export { ChromeNavControls, ChromeRecentlyAccessed, ChromeDocTitle }; @@ -58,7 +59,20 @@ export interface ChromeBrand { export type ChromeBreadcrumb = EuiBreadcrumb; /** @public */ -export type ChromeHelpExtension = (element: HTMLDivElement) => () => void; +export interface ChromeHelpExtension { + /** + * Provide your plugin's name to create a header for separation + */ + appName: string; + /** + * Creates unified links for sending users to documentation, GitHub, Discuss, or a custom link/button + */ + links?: ChromeHelpExtensionMenuLink[]; + /** + * Custom content to occur below the list of links + */ + content?: (element: HTMLDivElement) => () => void; +} interface ConstructorParams { browserSupportsCsp: boolean; diff --git a/src/core/public/chrome/index.ts b/src/core/public/chrome/index.ts index b220a81f775f8..4a500836990a7 100644 --- a/src/core/public/chrome/index.ts +++ b/src/core/public/chrome/index.ts @@ -26,6 +26,13 @@ export { ChromeBrand, ChromeHelpExtension, } from './chrome_service'; +export { + ChromeHelpExtensionMenuLink, + ChromeHelpExtensionMenuCustomLink, + ChromeHelpExtensionMenuDiscussLink, + ChromeHelpExtensionMenuDocumentationLink, + ChromeHelpExtensionMenuGitHubLink, +} from './ui/header/header_help_menu'; export { ChromeNavLink, ChromeNavLinks, ChromeNavLinkUpdateableFields } from './nav_links'; export { ChromeRecentlyAccessed, ChromeRecentlyAccessedHistoryItem } from './recently_accessed'; export { ChromeNavControl, ChromeNavControls } from './nav_controls'; diff --git a/src/core/public/chrome/ui/header/header.tsx b/src/core/public/chrome/ui/header/header.tsx index 1e97899be5854..904618651201f 100644 --- a/src/core/public/chrome/ui/header/header.tsx +++ b/src/core/public/chrome/ui/header/header.tsx @@ -24,21 +24,13 @@ import * as Rx from 'rxjs'; import { // TODO: add type annotations - // @ts-ignore EuiHeader, - // @ts-ignore EuiHeaderLogo, - // @ts-ignore EuiHeaderSection, - // @ts-ignore EuiHeaderSectionItem, - // @ts-ignore EuiHeaderSectionItemButton, - // @ts-ignore - EuiHideFor, EuiHorizontalRule, EuiIcon, - // @ts-ignore EuiImage, // @ts-ignore EuiNavDrawer, diff --git a/src/core/public/chrome/ui/header/header_help_menu.tsx b/src/core/public/chrome/ui/header/header_help_menu.tsx index c04fbaa07ba71..50659a777eccb 100644 --- a/src/core/public/chrome/ui/header/header_help_menu.tsx +++ b/src/core/public/chrome/ui/header/header_help_menu.tsx @@ -18,11 +18,12 @@ */ import * as Rx from 'rxjs'; -import { FormattedMessage } from '@kbn/i18n/react'; import React, { Component, Fragment } from 'react'; -import { InjectedIntl, injectI18n } from '@kbn/i18n/react'; +import { i18n } from '@kbn/i18n'; +import { InjectedIntl, injectI18n, FormattedMessage } from '@kbn/i18n/react'; import { EuiButtonEmpty, + EuiButtonEmptyProps, EuiFlexGroup, EuiFlexItem, EuiHeaderSectionItemButton, @@ -30,8 +31,11 @@ import { EuiPopover, EuiPopoverTitle, EuiSpacer, + EuiTitle, + EuiHorizontalRule, } from '@elastic/eui'; +import { ExclusiveUnion } from '@elastic/eui'; import { HeaderExtension } from './header_extension'; import { ChromeHelpExtension } from '../../chrome_service'; import { @@ -41,6 +45,69 @@ import { KIBANA_FEEDBACK_LINK, } from '../../constants'; +/** @public */ +export type ChromeHelpExtensionMenuGitHubLink = EuiButtonEmptyProps & { + /** + * Creates a link to a new github issue in the Kibana repo + */ + linkType: 'github'; + /** + * Include at least one app-specific label to be applied to the new github issue + */ + labels: string[]; + /** + * Provides initial text for the title of the issue + */ + title?: string; +}; + +/** @public */ +export type ChromeHelpExtensionMenuDiscussLink = EuiButtonEmptyProps & { + /** + * Creates a generic give feedback link with comment icon + */ + linkType: 'discuss'; + /** + * URL to discuss page. + * i.e. `https://discuss.elastic.co/c/${appName}` + */ + href: string; +}; + +/** @public */ +export type ChromeHelpExtensionMenuDocumentationLink = EuiButtonEmptyProps & { + /** + * Creates a deep-link to app-specific documentation + */ + linkType: 'documentation'; + /** + * URL to documentation page. + * i.e. `${ELASTIC_WEBSITE_URL}guide/en/kibana/${DOC_LINK_VERSION}/${appName}.html`, + */ + href: string; +}; + +/** @public */ +export type ChromeHelpExtensionMenuCustomLink = EuiButtonEmptyProps & { + /** + * Extend EuiButtonEmpty to provide extra functionality + */ + linkType: 'custom'; + /** + * Content of the button (in lieu of `children`) + */ + content: React.ReactNode; +}; + +/** @public */ +export type ChromeHelpExtensionMenuLink = ExclusiveUnion< + ChromeHelpExtensionMenuGitHubLink, + ExclusiveUnion< + ChromeHelpExtensionMenuDiscussLink, + ExclusiveUnion + > +>; + interface Props { helpExtension$: Rx.Observable; intl: InjectedIntl; @@ -84,6 +151,36 @@ class HeaderHelpMenuUI extends Component { } } + createGithubUrl = (labels: string[], title?: string) => { + const url = new URL('https://github.com/elastic/kibana/issues/new?'); + + if (labels.length) { + url.searchParams.set('labels', labels.join(',')); + } + + if (title) { + url.searchParams.set('title', title); + } + + return url.toString(); + }; + + createCustomLink = ( + index: number, + text: React.ReactNode, + addSpacer?: boolean, + buttonProps?: EuiButtonEmptyProps + ) => { + return ( + + + {text} + + {addSpacer && } + + ); + }; + public render() { const { intl, kibanaVersion, useDefaultContent, kibanaDocLink } = this.props; const { helpExtension } = this.state; @@ -137,6 +234,74 @@ class HeaderHelpMenuUI extends Component { ) : null; + let customContent; + if (helpExtension) { + const { appName, links, content } = helpExtension; + + const getFeedbackText = () => + i18n.translate('core.ui.chrome.headerGlobalNav.helpMenuGiveFeedbackOnApp', { + defaultMessage: 'Give feedback on {appName}', + values: { appName: helpExtension.appName }, + }); + + const customLinks = + links && + links.map((link, index) => { + const { linkType, title, labels = [], content: text, ...rest } = link; + switch (linkType) { + case 'documentation': + return this.createCustomLink( + index, + , + index < links.length - 1, + { + target: '_blank', + rel: 'noopener', + ...rest, + } + ); + case 'github': + return this.createCustomLink(index, getFeedbackText(), index < links.length - 1, { + iconType: 'logoGithub', + href: this.createGithubUrl(labels, title), + target: '_blank', + rel: 'noopener', + ...rest, + }); + case 'discuss': + return this.createCustomLink(index, getFeedbackText(), index < links.length - 1, { + iconType: 'editorComment', + target: '_blank', + rel: 'noopener', + ...rest, + }); + case 'custom': + return this.createCustomLink(index, text, index < links.length - 1, { ...rest }); + default: + break; + } + }); + + customContent = ( + <> + +

{appName}

+
+ + {customLinks} + {content && ( + <> + {customLinks && } + + + )} + + ); + } + const button = ( { - +

+ +

{
{defaultContent} - {defaultContent && helpExtension && } - {helpExtension && } + {defaultContent && customContent && } + {customContent}
); diff --git a/src/core/public/chrome/ui/header/index.ts b/src/core/public/chrome/ui/header/index.ts index f9c122b864dce..6d59fc6d9433b 100644 --- a/src/core/public/chrome/ui/header/index.ts +++ b/src/core/public/chrome/ui/header/index.ts @@ -19,3 +19,10 @@ export { Header, HeaderProps } from './header'; export { HeaderWrapper } from './header_wrapper'; +export { + ChromeHelpExtensionMenuLink, + ChromeHelpExtensionMenuCustomLink, + ChromeHelpExtensionMenuDiscussLink, + ChromeHelpExtensionMenuDocumentationLink, + ChromeHelpExtensionMenuGitHubLink, +} from './header_help_menu'; diff --git a/src/core/public/chrome/ui/index.ts b/src/core/public/chrome/ui/index.ts index 69582f6f1ed52..81b2fdfb0fcc0 100644 --- a/src/core/public/chrome/ui/index.ts +++ b/src/core/public/chrome/ui/index.ts @@ -18,4 +18,12 @@ */ export { LoadingIndicator } from './loading_indicator'; -export { Header, HeaderWrapper } from './header'; +export { + Header, + HeaderWrapper, + ChromeHelpExtensionMenuLink, + ChromeHelpExtensionMenuCustomLink, + ChromeHelpExtensionMenuDiscussLink, + ChromeHelpExtensionMenuDocumentationLink, + ChromeHelpExtensionMenuGitHubLink, +} from './header'; diff --git a/src/core/public/index.ts b/src/core/public/index.ts index e040b29814900..c723c282a7caa 100644 --- a/src/core/public/index.ts +++ b/src/core/public/index.ts @@ -40,6 +40,11 @@ import { ChromeBrand, ChromeBreadcrumb, ChromeHelpExtension, + ChromeHelpExtensionMenuLink, + ChromeHelpExtensionMenuCustomLink, + ChromeHelpExtensionMenuDiscussLink, + ChromeHelpExtensionMenuDocumentationLink, + ChromeHelpExtensionMenuGitHubLink, ChromeNavControl, ChromeNavControls, ChromeNavLink, @@ -242,6 +247,11 @@ export { ChromeBrand, ChromeBreadcrumb, ChromeHelpExtension, + ChromeHelpExtensionMenuLink, + ChromeHelpExtensionMenuCustomLink, + ChromeHelpExtensionMenuDiscussLink, + ChromeHelpExtensionMenuDocumentationLink, + ChromeHelpExtensionMenuGitHubLink, ChromeNavControl, ChromeNavControls, ChromeNavLink, diff --git a/src/core/public/injected_metadata/index.ts b/src/core/public/injected_metadata/index.ts index dac9d5cea3565..cebd0f017de69 100644 --- a/src/core/public/injected_metadata/index.ts +++ b/src/core/public/injected_metadata/index.ts @@ -22,5 +22,6 @@ export { InjectedMetadataParams, InjectedMetadataSetup, InjectedMetadataStart, + InjectedPluginMetadata, LegacyNavLink, } from './injected_metadata_service'; diff --git a/src/core/public/injected_metadata/injected_metadata_service.test.ts b/src/core/public/injected_metadata/injected_metadata_service.test.ts index 1110097c1c92b..cf4b72114d5ac 100644 --- a/src/core/public/injected_metadata/injected_metadata_service.test.ts +++ b/src/core/public/injected_metadata/injected_metadata_service.test.ts @@ -69,7 +69,7 @@ describe('setup.getPlugins()', () => { const injectedMetadata = new InjectedMetadataService({ injectedMetadata: { uiPlugins: [ - { id: 'plugin-1', plugin: {} }, + { id: 'plugin-1', plugin: {}, config: { clientProp: 'clientValue' } }, { id: 'plugin-2', plugin: {} }, ], }, @@ -77,7 +77,7 @@ describe('setup.getPlugins()', () => { const plugins = injectedMetadata.setup().getPlugins(); expect(plugins).toEqual([ - { id: 'plugin-1', plugin: {} }, + { id: 'plugin-1', plugin: {}, config: { clientProp: 'clientValue' } }, { id: 'plugin-2', plugin: {} }, ]); }); diff --git a/src/core/public/injected_metadata/injected_metadata_service.ts b/src/core/public/injected_metadata/injected_metadata_service.ts index a5342aaa48b72..002f83d9feac4 100644 --- a/src/core/public/injected_metadata/injected_metadata_service.ts +++ b/src/core/public/injected_metadata/injected_metadata_service.ts @@ -38,6 +38,14 @@ export interface LegacyNavLink { euiIconType?: string; } +export interface InjectedPluginMetadata { + id: PluginName; + plugin: DiscoveredPlugin; + config?: { + [key: string]: unknown; + }; +} + /** @internal */ export interface InjectedMetadataParams { injectedMetadata: { @@ -55,10 +63,7 @@ export interface InjectedMetadataParams { mode: Readonly; packageInfo: Readonly; }; - uiPlugins: Array<{ - id: PluginName; - plugin: DiscoveredPlugin; - }>; + uiPlugins: InjectedPluginMetadata[]; capabilities: Capabilities; legacyMode: boolean; legacyMetadata: { @@ -165,10 +170,7 @@ export interface InjectedMetadataSetup { /** * An array of frontend plugins in topological order. */ - getPlugins: () => Array<{ - id: string; - plugin: DiscoveredPlugin; - }>; + getPlugins: () => InjectedPluginMetadata[]; /** Indicates whether or not we are rendering a known legacy app. */ getLegacyMode: () => boolean; getLegacyMetadata: () => { diff --git a/src/core/public/mocks.ts b/src/core/public/mocks.ts index afd0825ec986c..695f0454f8b65 100644 --- a/src/core/public/mocks.ts +++ b/src/core/public/mocks.ts @@ -92,6 +92,9 @@ function pluginInitializerContextMock() { dist: false, }, }, + config: { + get: () => ({} as T), + }, }; return mock; diff --git a/src/core/public/overlays/flyout/__snapshots__/flyout_service.test.tsx.snap b/src/core/public/overlays/flyout/__snapshots__/flyout_service.test.tsx.snap index 94c11f0185427..626c91b6a9668 100644 --- a/src/core/public/overlays/flyout/__snapshots__/flyout_service.test.tsx.snap +++ b/src/core/public/overlays/flyout/__snapshots__/flyout_service.test.tsx.snap @@ -31,7 +31,7 @@ Array [ ] `; -exports[`FlyoutService openFlyout() renders a flyout to the DOM 2`] = `"
Flyout content
"`; +exports[`FlyoutService openFlyout() renders a flyout to the DOM 2`] = `"
Flyout content
"`; exports[`FlyoutService openFlyout() with a currently active flyout replaces the current flyout with a new one 1`] = ` Array [ @@ -74,4 +74,4 @@ Array [ ] `; -exports[`FlyoutService openFlyout() with a currently active flyout replaces the current flyout with a new one 2`] = `"
Flyout content 2
"`; +exports[`FlyoutService openFlyout() with a currently active flyout replaces the current flyout with a new one 2`] = `"
Flyout content 2
"`; diff --git a/src/core/public/plugins/plugin_context.ts b/src/core/public/plugins/plugin_context.ts index eae45654fce18..f77ddd8f2f696 100644 --- a/src/core/public/plugins/plugin_context.ts +++ b/src/core/public/plugins/plugin_context.ts @@ -18,7 +18,6 @@ */ import { omit } from 'lodash'; - import { DiscoveredPlugin } from '../../server'; import { PluginOpaqueId, PackageInfo, EnvironmentMode } from '../../server/types'; import { CoreContext } from '../core_system'; @@ -31,7 +30,7 @@ import { CoreSetup, CoreStart } from '../'; * * @public */ -export interface PluginInitializerContext { +export interface PluginInitializerContext { /** * A symbol used to identify this plugin in the system. Needed when registering handlers or context providers. */ @@ -40,6 +39,9 @@ export interface PluginInitializerContext { mode: Readonly; packageInfo: Readonly; }; + readonly config: { + get: () => T; + }; } /** @@ -47,17 +49,27 @@ export interface PluginInitializerContext { * empty but should provide static services in the future, such as config and logging. * * @param coreContext - * @param pluginManinfest + * @param opaqueId + * @param pluginManifest + * @param pluginConfig * @internal */ export function createPluginInitializerContext( coreContext: CoreContext, opaqueId: PluginOpaqueId, - pluginManifest: DiscoveredPlugin + pluginManifest: DiscoveredPlugin, + pluginConfig: { + [key: string]: unknown; + } ): PluginInitializerContext { return { opaqueId, env: coreContext.env, + config: { + get() { + return (pluginConfig as unknown) as T; + }, + }, }; } diff --git a/src/core/public/plugins/plugins_service.test.ts b/src/core/public/plugins/plugins_service.test.ts index 0d8887774e900..2983d7583cb49 100644 --- a/src/core/public/plugins/plugins_service.test.ts +++ b/src/core/public/plugins/plugins_service.test.ts @@ -25,13 +25,14 @@ import { mockPluginInitializerProvider, } from './plugins_service.test.mocks'; -import { PluginName, DiscoveredPlugin } from 'src/core/server'; +import { PluginName } from 'src/core/server'; import { coreMock } from '../mocks'; import { PluginsService, PluginsServiceStartDeps, PluginsServiceSetupDeps, } from './plugins_service'; +import { InjectedPluginMetadata } from '../injected_metadata'; import { notificationServiceMock } from '../notifications/notifications_service.mock'; import { applicationServiceMock } from '../application/application_service.mock'; import { i18nServiceMock } from '../i18n/i18n_service.mock'; @@ -41,7 +42,7 @@ import { fatalErrorsServiceMock } from '../fatal_errors/fatal_errors_service.moc import { uiSettingsServiceMock } from '../ui_settings/ui_settings_service.mock'; import { injectedMetadataServiceMock } from '../injected_metadata/injected_metadata_service.mock'; import { httpServiceMock } from '../http/http_service.mock'; -import { CoreSetup, CoreStart } from '..'; +import { CoreSetup, CoreStart, PluginInitializerContext } from '..'; import { docLinksServiceMock } from '../doc_links/doc_links_service.mock'; import { savedObjectsMock } from '../saved_objects/saved_objects_service.mock'; import { contextServiceMock } from '../context/context_service.mock'; @@ -52,7 +53,7 @@ mockPluginInitializerProvider.mockImplementation( pluginName => mockPluginInitializers.get(pluginName)! ); -let plugins: Array<{ id: string; plugin: DiscoveredPlugin }>; +let plugins: InjectedPluginMetadata[]; type DeeplyMocked = { [P in keyof T]: jest.Mocked }; @@ -62,83 +63,6 @@ let mockSetupContext: DeeplyMocked; let mockStartDeps: DeeplyMocked; let mockStartContext: DeeplyMocked; -beforeEach(() => { - plugins = [ - { id: 'pluginA', plugin: createManifest('pluginA') }, - { id: 'pluginB', plugin: createManifest('pluginB', { required: ['pluginA'] }) }, - { - id: 'pluginC', - plugin: createManifest('pluginC', { required: ['pluginA'], optional: ['nonexist'] }), - }, - ]; - mockSetupDeps = { - application: applicationServiceMock.createInternalSetupContract(), - context: contextServiceMock.createSetupContract(), - fatalErrors: fatalErrorsServiceMock.createSetupContract(), - http: httpServiceMock.createSetupContract(), - injectedMetadata: pick(injectedMetadataServiceMock.createStartContract(), 'getInjectedVar'), - notifications: notificationServiceMock.createSetupContract(), - uiSettings: uiSettingsServiceMock.createSetupContract(), - }; - mockSetupContext = { - ...mockSetupDeps, - application: expect.any(Object), - }; - mockStartDeps = { - application: applicationServiceMock.createInternalStartContract(), - docLinks: docLinksServiceMock.createStartContract(), - http: httpServiceMock.createStartContract(), - chrome: chromeServiceMock.createStartContract(), - i18n: i18nServiceMock.createStartContract(), - injectedMetadata: pick(injectedMetadataServiceMock.createStartContract(), 'getInjectedVar'), - notifications: notificationServiceMock.createStartContract(), - overlays: overlayServiceMock.createStartContract(), - uiSettings: uiSettingsServiceMock.createStartContract(), - savedObjects: savedObjectsMock.createStartContract(), - }; - mockStartContext = { - ...mockStartDeps, - application: expect.any(Object), - chrome: omit(mockStartDeps.chrome, 'getComponent'), - }; - - // Reset these for each test. - mockPluginInitializers = new Map(([ - [ - 'pluginA', - jest.fn(() => ({ - setup: jest.fn(() => ({ setupValue: 1 })), - start: jest.fn(() => ({ startValue: 2 })), - stop: jest.fn(), - })), - ], - [ - 'pluginB', - jest.fn(() => ({ - setup: jest.fn((core, deps: any) => ({ - pluginAPlusB: deps.pluginA.setupValue + 1, - })), - start: jest.fn((core, deps: any) => ({ - pluginAPlusB: deps.pluginA.startValue + 1, - })), - stop: jest.fn(), - })), - ], - [ - 'pluginC', - jest.fn(() => ({ - setup: jest.fn(), - start: jest.fn(), - stop: jest.fn(), - })), - ], - ] as unknown) as [[PluginName, any]]); -}); - -afterEach(() => { - mockLoadPluginBundle.mockClear(); -}); - function createManifest( id: string, { required = [], optional = [] }: { required?: string[]; optional?: string[]; ui?: boolean } = {} @@ -152,9 +76,88 @@ function createManifest( }; } -test('`PluginsService.getOpaqueIds` returns dependency tree of symbols', () => { - const pluginsService = new PluginsService(mockCoreContext, plugins); - expect(pluginsService.getOpaqueIds()).toMatchInlineSnapshot(` +describe('PluginsService', () => { + beforeEach(() => { + plugins = [ + { id: 'pluginA', plugin: createManifest('pluginA') }, + { id: 'pluginB', plugin: createManifest('pluginB', { required: ['pluginA'] }) }, + { + id: 'pluginC', + plugin: createManifest('pluginC', { required: ['pluginA'], optional: ['nonexist'] }), + }, + ]; + mockSetupDeps = { + application: applicationServiceMock.createInternalSetupContract(), + context: contextServiceMock.createSetupContract(), + fatalErrors: fatalErrorsServiceMock.createSetupContract(), + http: httpServiceMock.createSetupContract(), + injectedMetadata: pick(injectedMetadataServiceMock.createStartContract(), 'getInjectedVar'), + notifications: notificationServiceMock.createSetupContract(), + uiSettings: uiSettingsServiceMock.createSetupContract(), + }; + mockSetupContext = { + ...mockSetupDeps, + application: expect.any(Object), + }; + mockStartDeps = { + application: applicationServiceMock.createInternalStartContract(), + docLinks: docLinksServiceMock.createStartContract(), + http: httpServiceMock.createStartContract(), + chrome: chromeServiceMock.createStartContract(), + i18n: i18nServiceMock.createStartContract(), + injectedMetadata: pick(injectedMetadataServiceMock.createStartContract(), 'getInjectedVar'), + notifications: notificationServiceMock.createStartContract(), + overlays: overlayServiceMock.createStartContract(), + uiSettings: uiSettingsServiceMock.createStartContract(), + savedObjects: savedObjectsMock.createStartContract(), + }; + mockStartContext = { + ...mockStartDeps, + application: expect.any(Object), + chrome: omit(mockStartDeps.chrome, 'getComponent'), + }; + + // Reset these for each test. + mockPluginInitializers = new Map(([ + [ + 'pluginA', + jest.fn(() => ({ + setup: jest.fn(() => ({ setupValue: 1 })), + start: jest.fn(() => ({ startValue: 2 })), + stop: jest.fn(), + })), + ], + [ + 'pluginB', + jest.fn(() => ({ + setup: jest.fn((core, deps: any) => ({ + pluginAPlusB: deps.pluginA.setupValue + 1, + })), + start: jest.fn((core, deps: any) => ({ + pluginAPlusB: deps.pluginA.startValue + 1, + })), + stop: jest.fn(), + })), + ], + [ + 'pluginC', + jest.fn(() => ({ + setup: jest.fn(), + start: jest.fn(), + stop: jest.fn(), + })), + ], + ] as unknown) as [[PluginName, any]]); + }); + + afterEach(() => { + mockLoadPluginBundle.mockClear(); + }); + + describe('#getOpaqueIds()', () => { + it('returns dependency tree of symbols', () => { + const pluginsService = new PluginsService(mockCoreContext, plugins); + expect(pluginsService.getOpaqueIds()).toMatchInlineSnapshot(` Map { Symbol(pluginA) => Array [], Symbol(pluginB) => Array [ @@ -165,152 +168,184 @@ test('`PluginsService.getOpaqueIds` returns dependency tree of symbols', () => { ], } `); -}); - -test('`PluginsService.setup` fails if any bundle cannot be loaded', async () => { - mockLoadPluginBundle.mockRejectedValueOnce(new Error('Could not load bundle')); - - const pluginsService = new PluginsService(mockCoreContext, plugins); - await expect(pluginsService.setup(mockSetupDeps)).rejects.toThrowErrorMatchingInlineSnapshot( - `"Could not load bundle"` - ); -}); - -test('`PluginsService.setup` fails if any plugin instance does not have a setup function', async () => { - mockPluginInitializers.set('pluginA', (() => ({})) as any); - const pluginsService = new PluginsService(mockCoreContext, plugins); - await expect(pluginsService.setup(mockSetupDeps)).rejects.toThrowErrorMatchingInlineSnapshot( - `"Instance of plugin \\"pluginA\\" does not define \\"setup\\" function."` - ); -}); - -test('`PluginsService.setup` calls loadPluginBundles with http and plugins', async () => { - const pluginsService = new PluginsService(mockCoreContext, plugins); - await pluginsService.setup(mockSetupDeps); - - expect(mockLoadPluginBundle).toHaveBeenCalledTimes(3); - expect(mockLoadPluginBundle).toHaveBeenCalledWith(mockSetupDeps.http.basePath.prepend, 'pluginA'); - expect(mockLoadPluginBundle).toHaveBeenCalledWith(mockSetupDeps.http.basePath.prepend, 'pluginB'); - expect(mockLoadPluginBundle).toHaveBeenCalledWith(mockSetupDeps.http.basePath.prepend, 'pluginC'); -}); - -test('`PluginsService.setup` initalizes plugins with PluginIntitializerContext', async () => { - const pluginsService = new PluginsService(mockCoreContext, plugins); - await pluginsService.setup(mockSetupDeps); - - expect(mockPluginInitializers.get('pluginA')).toHaveBeenCalledWith(expect.any(Object)); - expect(mockPluginInitializers.get('pluginB')).toHaveBeenCalledWith(expect.any(Object)); - expect(mockPluginInitializers.get('pluginC')).toHaveBeenCalledWith(expect.any(Object)); -}); - -test('`PluginsService.setup` exposes dependent setup contracts to plugins', async () => { - const pluginsService = new PluginsService(mockCoreContext, plugins); - await pluginsService.setup(mockSetupDeps); - - const pluginAInstance = mockPluginInitializers.get('pluginA')!.mock.results[0].value; - const pluginBInstance = mockPluginInitializers.get('pluginB')!.mock.results[0].value; - const pluginCInstance = mockPluginInitializers.get('pluginC')!.mock.results[0].value; - - expect(pluginAInstance.setup).toHaveBeenCalledWith(mockSetupContext, {}); - expect(pluginBInstance.setup).toHaveBeenCalledWith(mockSetupContext, { - pluginA: { setupValue: 1 }, - }); - // Does not supply value for `nonexist` optional dep - expect(pluginCInstance.setup).toHaveBeenCalledWith(mockSetupContext, { - pluginA: { setupValue: 1 }, + }); }); -}); - -test('`PluginsService.setup` does not set missing dependent setup contracts', async () => { - plugins = [{ id: 'pluginD', plugin: createManifest('pluginD', { optional: ['missing'] }) }]; - mockPluginInitializers.set( - 'pluginD', - jest.fn(() => ({ - setup: jest.fn(), - start: jest.fn(), - })) as any - ); - - const pluginsService = new PluginsService(mockCoreContext, plugins); - await pluginsService.setup(mockSetupDeps); - - // If a dependency is missing it should not be in the deps at all, not even as undefined. - const pluginDInstance = mockPluginInitializers.get('pluginD')!.mock.results[0].value; - expect(pluginDInstance.setup).toHaveBeenCalledWith(mockSetupContext, {}); - const pluginDDeps = pluginDInstance.setup.mock.calls[0][1]; - expect(pluginDDeps).not.toHaveProperty('missing'); -}); -test('`PluginsService.setup` returns plugin setup contracts', async () => { - const pluginsService = new PluginsService(mockCoreContext, plugins); - const { contracts } = await pluginsService.setup(mockSetupDeps); - - // Verify that plugin contracts were available - expect((contracts.get('pluginA')! as any).setupValue).toEqual(1); - expect((contracts.get('pluginB')! as any).pluginAPlusB).toEqual(2); -}); - -test('`PluginsService.start` exposes dependent start contracts to plugins', async () => { - const pluginsService = new PluginsService(mockCoreContext, plugins); - await pluginsService.setup(mockSetupDeps); - await pluginsService.start(mockStartDeps); - - const pluginAInstance = mockPluginInitializers.get('pluginA')!.mock.results[0].value; - const pluginBInstance = mockPluginInitializers.get('pluginB')!.mock.results[0].value; - const pluginCInstance = mockPluginInitializers.get('pluginC')!.mock.results[0].value; - - expect(pluginAInstance.start).toHaveBeenCalledWith(mockStartContext, {}); - expect(pluginBInstance.start).toHaveBeenCalledWith(mockStartContext, { - pluginA: { startValue: 2 }, - }); - // Does not supply value for `nonexist` optional dep - expect(pluginCInstance.start).toHaveBeenCalledWith(mockStartContext, { - pluginA: { startValue: 2 }, + describe('#setup()', () => { + it('fails if any bundle cannot be loaded', async () => { + mockLoadPluginBundle.mockRejectedValueOnce(new Error('Could not load bundle')); + + const pluginsService = new PluginsService(mockCoreContext, plugins); + await expect(pluginsService.setup(mockSetupDeps)).rejects.toThrowErrorMatchingInlineSnapshot( + `"Could not load bundle"` + ); + }); + + it('fails if any plugin instance does not have a setup function', async () => { + mockPluginInitializers.set('pluginA', (() => ({})) as any); + const pluginsService = new PluginsService(mockCoreContext, plugins); + await expect(pluginsService.setup(mockSetupDeps)).rejects.toThrowErrorMatchingInlineSnapshot( + `"Instance of plugin \\"pluginA\\" does not define \\"setup\\" function."` + ); + }); + + it('calls loadPluginBundles with http and plugins', async () => { + const pluginsService = new PluginsService(mockCoreContext, plugins); + await pluginsService.setup(mockSetupDeps); + + expect(mockLoadPluginBundle).toHaveBeenCalledTimes(3); + expect(mockLoadPluginBundle).toHaveBeenCalledWith( + mockSetupDeps.http.basePath.prepend, + 'pluginA' + ); + expect(mockLoadPluginBundle).toHaveBeenCalledWith( + mockSetupDeps.http.basePath.prepend, + 'pluginB' + ); + expect(mockLoadPluginBundle).toHaveBeenCalledWith( + mockSetupDeps.http.basePath.prepend, + 'pluginC' + ); + }); + + it('initializes plugins with PluginInitializerContext', async () => { + const pluginsService = new PluginsService(mockCoreContext, plugins); + await pluginsService.setup(mockSetupDeps); + + expect(mockPluginInitializers.get('pluginA')).toHaveBeenCalledWith(expect.any(Object)); + expect(mockPluginInitializers.get('pluginB')).toHaveBeenCalledWith(expect.any(Object)); + expect(mockPluginInitializers.get('pluginC')).toHaveBeenCalledWith(expect.any(Object)); + }); + + it('initializes plugins with associated client configuration', async () => { + const pluginConfig = { + clientProperty: 'some value', + }; + plugins[0].config = pluginConfig; + + const pluginsService = new PluginsService(mockCoreContext, plugins); + await pluginsService.setup(mockSetupDeps); + + const initializerContext = mockPluginInitializers.get('pluginA')!.mock + .calls[0][0] as PluginInitializerContext; + const config = initializerContext.config.get(); + expect(config).toMatchObject(pluginConfig); + }); + + it('exposes dependent setup contracts to plugins', async () => { + const pluginsService = new PluginsService(mockCoreContext, plugins); + await pluginsService.setup(mockSetupDeps); + + const pluginAInstance = mockPluginInitializers.get('pluginA')!.mock.results[0].value; + const pluginBInstance = mockPluginInitializers.get('pluginB')!.mock.results[0].value; + const pluginCInstance = mockPluginInitializers.get('pluginC')!.mock.results[0].value; + + expect(pluginAInstance.setup).toHaveBeenCalledWith(mockSetupContext, {}); + expect(pluginBInstance.setup).toHaveBeenCalledWith(mockSetupContext, { + pluginA: { setupValue: 1 }, + }); + // Does not supply value for `nonexist` optional dep + expect(pluginCInstance.setup).toHaveBeenCalledWith(mockSetupContext, { + pluginA: { setupValue: 1 }, + }); + }); + + it('does not set missing dependent setup contracts', async () => { + plugins = [{ id: 'pluginD', plugin: createManifest('pluginD', { optional: ['missing'] }) }]; + mockPluginInitializers.set( + 'pluginD', + jest.fn(() => ({ + setup: jest.fn(), + start: jest.fn(), + })) as any + ); + + const pluginsService = new PluginsService(mockCoreContext, plugins); + await pluginsService.setup(mockSetupDeps); + + // If a dependency is missing it should not be in the deps at all, not even as undefined. + const pluginDInstance = mockPluginInitializers.get('pluginD')!.mock.results[0].value; + expect(pluginDInstance.setup).toHaveBeenCalledWith(mockSetupContext, {}); + const pluginDDeps = pluginDInstance.setup.mock.calls[0][1]; + expect(pluginDDeps).not.toHaveProperty('missing'); + }); + + it('returns plugin setup contracts', async () => { + const pluginsService = new PluginsService(mockCoreContext, plugins); + const { contracts } = await pluginsService.setup(mockSetupDeps); + + // Verify that plugin contracts were available + expect((contracts.get('pluginA')! as any).setupValue).toEqual(1); + expect((contracts.get('pluginB')! as any).pluginAPlusB).toEqual(2); + }); }); -}); -test('`PluginsService.start` does not set missing dependent start contracts', async () => { - plugins = [{ id: 'pluginD', plugin: createManifest('pluginD', { optional: ['missing'] }) }]; - mockPluginInitializers.set( - 'pluginD', - jest.fn(() => ({ - setup: jest.fn(), - start: jest.fn(), - })) as any - ); - - const pluginsService = new PluginsService(mockCoreContext, plugins); - await pluginsService.setup(mockSetupDeps); - await pluginsService.start(mockStartDeps); - - // If a dependency is missing it should not be in the deps at all, not even as undefined. - const pluginDInstance = mockPluginInitializers.get('pluginD')!.mock.results[0].value; - expect(pluginDInstance.start).toHaveBeenCalledWith(mockStartContext, {}); - const pluginDDeps = pluginDInstance.start.mock.calls[0][1]; - expect(pluginDDeps).not.toHaveProperty('missing'); -}); - -test('`PluginsService.start` returns plugin start contracts', async () => { - const pluginsService = new PluginsService(mockCoreContext, plugins); - await pluginsService.setup(mockSetupDeps); - const { contracts } = await pluginsService.start(mockStartDeps); - - // Verify that plugin contracts were available - expect((contracts.get('pluginA')! as any).startValue).toEqual(2); - expect((contracts.get('pluginB')! as any).pluginAPlusB).toEqual(3); -}); + describe('#start()', () => { + it('exposes dependent start contracts to plugins', async () => { + const pluginsService = new PluginsService(mockCoreContext, plugins); + await pluginsService.setup(mockSetupDeps); + await pluginsService.start(mockStartDeps); + + const pluginAInstance = mockPluginInitializers.get('pluginA')!.mock.results[0].value; + const pluginBInstance = mockPluginInitializers.get('pluginB')!.mock.results[0].value; + const pluginCInstance = mockPluginInitializers.get('pluginC')!.mock.results[0].value; + + expect(pluginAInstance.start).toHaveBeenCalledWith(mockStartContext, {}); + expect(pluginBInstance.start).toHaveBeenCalledWith(mockStartContext, { + pluginA: { startValue: 2 }, + }); + // Does not supply value for `nonexist` optional dep + expect(pluginCInstance.start).toHaveBeenCalledWith(mockStartContext, { + pluginA: { startValue: 2 }, + }); + }); + + it('does not set missing dependent start contracts', async () => { + plugins = [{ id: 'pluginD', plugin: createManifest('pluginD', { optional: ['missing'] }) }]; + mockPluginInitializers.set( + 'pluginD', + jest.fn(() => ({ + setup: jest.fn(), + start: jest.fn(), + })) as any + ); + + const pluginsService = new PluginsService(mockCoreContext, plugins); + await pluginsService.setup(mockSetupDeps); + await pluginsService.start(mockStartDeps); + + // If a dependency is missing it should not be in the deps at all, not even as undefined. + const pluginDInstance = mockPluginInitializers.get('pluginD')!.mock.results[0].value; + expect(pluginDInstance.start).toHaveBeenCalledWith(mockStartContext, {}); + const pluginDDeps = pluginDInstance.start.mock.calls[0][1]; + expect(pluginDDeps).not.toHaveProperty('missing'); + }); + + it('returns plugin start contracts', async () => { + const pluginsService = new PluginsService(mockCoreContext, plugins); + await pluginsService.setup(mockSetupDeps); + const { contracts } = await pluginsService.start(mockStartDeps); + + // Verify that plugin contracts were available + expect((contracts.get('pluginA')! as any).startValue).toEqual(2); + expect((contracts.get('pluginB')! as any).pluginAPlusB).toEqual(3); + }); + }); -test('`PluginService.stop` calls the stop function on each plugin', async () => { - const pluginsService = new PluginsService(mockCoreContext, plugins); - await pluginsService.setup(mockSetupDeps); + describe('#stop()', () => { + it('calls the stop function on each plugin', async () => { + const pluginsService = new PluginsService(mockCoreContext, plugins); + await pluginsService.setup(mockSetupDeps); - const pluginAInstance = mockPluginInitializers.get('pluginA')!.mock.results[0].value; - const pluginBInstance = mockPluginInitializers.get('pluginB')!.mock.results[0].value; - const pluginCInstance = mockPluginInitializers.get('pluginC')!.mock.results[0].value; + const pluginAInstance = mockPluginInitializers.get('pluginA')!.mock.results[0].value; + const pluginBInstance = mockPluginInitializers.get('pluginB')!.mock.results[0].value; + const pluginCInstance = mockPluginInitializers.get('pluginC')!.mock.results[0].value; - await pluginsService.stop(); + await pluginsService.stop(); - expect(pluginAInstance.stop).toHaveBeenCalled(); - expect(pluginBInstance.stop).toHaveBeenCalled(); - expect(pluginCInstance.stop).toHaveBeenCalled(); + expect(pluginAInstance.stop).toHaveBeenCalled(); + expect(pluginBInstance.stop).toHaveBeenCalled(); + expect(pluginCInstance.stop).toHaveBeenCalled(); + }); + }); }); diff --git a/src/core/public/plugins/plugins_service.ts b/src/core/public/plugins/plugins_service.ts index 1ab9d7f2fa9b2..c1939a3397647 100644 --- a/src/core/public/plugins/plugins_service.ts +++ b/src/core/public/plugins/plugins_service.ts @@ -17,7 +17,7 @@ * under the License. */ -import { DiscoveredPlugin, PluginName, PluginOpaqueId } from '../../server'; +import { PluginName, PluginOpaqueId } from '../../server'; import { CoreService } from '../../types'; import { CoreContext } from '../core_system'; import { PluginWrapper } from './plugin'; @@ -27,6 +27,7 @@ import { createPluginStartContext, } from './plugin_context'; import { InternalCoreSetup, InternalCoreStart } from '../core_system'; +import { InjectedPluginMetadata } from '../injected_metadata'; /** @internal */ export type PluginsServiceSetupDeps = InternalCoreSetup; @@ -55,15 +56,12 @@ export class PluginsService implements CoreService - ) { + constructor(private readonly coreContext: CoreContext, plugins: InjectedPluginMetadata[]) { // Generate opaque ids const opaqueIds = new Map(plugins.map(p => [p.id, Symbol(p.id)])); // Setup dependency map and plugin wrappers - plugins.forEach(({ id, plugin }) => { + plugins.forEach(({ id, plugin, config = {} }) => { // Setup map of dependencies this.pluginDependencies.set(id, [ ...plugin.requiredPlugins, @@ -76,7 +74,7 @@ export class PluginsService implements CoreService () => void; +export interface ChromeHelpExtension { + appName: string; + content?: (element: HTMLDivElement) => () => void; + links?: ChromeHelpExtensionMenuLink[]; +} + +// @public (undocumented) +export type ChromeHelpExtensionMenuCustomLink = EuiButtonEmptyProps & { + linkType: 'custom'; + content: React.ReactNode; +}; + +// @public (undocumented) +export type ChromeHelpExtensionMenuDiscussLink = EuiButtonEmptyProps & { + linkType: 'discuss'; + href: string; +}; + +// @public (undocumented) +export type ChromeHelpExtensionMenuDocumentationLink = EuiButtonEmptyProps & { + linkType: 'documentation'; + href: string; +}; + +// @public (undocumented) +export type ChromeHelpExtensionMenuGitHubLink = EuiButtonEmptyProps & { + linkType: 'github'; + labels: string[]; + title?: string; +}; + +// @public (undocumented) +export type ChromeHelpExtensionMenuLink = ExclusiveUnion>>; // @public (undocumented) export interface ChromeNavControl { @@ -695,7 +729,11 @@ export interface Plugin = (core: PluginInitializerContext) => Plugin; // @public -export interface PluginInitializerContext { +export interface PluginInitializerContext { + // (undocumented) + readonly config: { + get: () => T; + }; // (undocumented) readonly env: { mode: Readonly; diff --git a/src/core/server/index.ts b/src/core/server/index.ts index 2a5631ad1c380..987e4e64f9d5b 100644 --- a/src/core/server/index.ts +++ b/src/core/server/index.ts @@ -123,6 +123,8 @@ export { Logger, LoggerFactory, LogMeta, LogRecord, LogLevel } from './logging'; export { DiscoveredPlugin, Plugin, + PluginConfigDescriptor, + PluginConfigSchema, PluginInitializer, PluginInitializerContext, PluginManifest, diff --git a/src/core/server/legacy/legacy_service.test.ts b/src/core/server/legacy/legacy_service.test.ts index e2aefd846d978..1240518422e2f 100644 --- a/src/core/server/legacy/legacy_service.test.ts +++ b/src/core/server/legacy/legacy_service.test.ts @@ -86,6 +86,7 @@ beforeEach(() => { public: new Map([['plugin-id', {} as DiscoveredPlugin]]), internal: new Map([['plugin-id', {} as DiscoveredPluginInternal]]), }, + uiPluginConfigs: new Map(), }, }, plugins: { 'plugin-id': 'plugin-value' }, diff --git a/src/core/server/legacy/legacy_service.ts b/src/core/server/legacy/legacy_service.ts index 99963ad9ce3e8..e86e6cde6e927 100644 --- a/src/core/server/legacy/legacy_service.ts +++ b/src/core/server/legacy/legacy_service.ts @@ -278,6 +278,7 @@ export class LegacyService implements CoreService { hapiServer: setupDeps.core.http.server, kibanaMigrator: startDeps.core.savedObjects.migrator, uiPlugins: setupDeps.core.plugins.uiPlugins, + uiPluginConfigs: setupDeps.core.plugins.uiPluginConfigs, elasticsearch: setupDeps.core.elasticsearch, uiSettings: setupDeps.core.uiSettings, savedObjectsClientProvider: startDeps.core.savedObjects.clientProvider, diff --git a/src/core/server/plugins/plugin.test.ts b/src/core/server/plugins/plugin.test.ts index e457f01a1941c..6aab03a01675d 100644 --- a/src/core/server/plugins/plugin.test.ts +++ b/src/core/server/plugins/plugin.test.ts @@ -291,12 +291,13 @@ test('`stop` calls `stop` defined by the plugin instance', async () => { describe('#getConfigSchema()', () => { it('reads config schema from plugin', () => { const pluginSchema = schema.any(); + const configDescriptor = { + schema: pluginSchema, + }; jest.doMock( 'plugin-with-schema/server', () => ({ - config: { - schema: pluginSchema, - }, + config: configDescriptor, }), { virtual: true } ); @@ -309,7 +310,7 @@ describe('#getConfigSchema()', () => { initializerContext: createPluginInitializerContext(coreContext, opaqueId, manifest), }); - expect(plugin.getConfigSchema()).toBe(pluginSchema); + expect(plugin.getConfigDescriptor()).toBe(configDescriptor); }); it('returns null if config definition not specified', () => { @@ -322,7 +323,7 @@ describe('#getConfigSchema()', () => { opaqueId, initializerContext: createPluginInitializerContext(coreContext, opaqueId, manifest), }); - expect(plugin.getConfigSchema()).toBe(null); + expect(plugin.getConfigDescriptor()).toBe(null); }); it('returns null for plugins without a server part', () => { @@ -334,7 +335,7 @@ describe('#getConfigSchema()', () => { opaqueId, initializerContext: createPluginInitializerContext(coreContext, opaqueId, manifest), }); - expect(plugin.getConfigSchema()).toBe(null); + expect(plugin.getConfigDescriptor()).toBe(null); }); it('throws if plugin contains invalid schema', () => { @@ -357,7 +358,7 @@ describe('#getConfigSchema()', () => { opaqueId, initializerContext: createPluginInitializerContext(coreContext, opaqueId, manifest), }); - expect(() => plugin.getConfigSchema()).toThrowErrorMatchingInlineSnapshot( + expect(() => plugin.getConfigDescriptor()).toThrowErrorMatchingInlineSnapshot( `"Configuration schema expected to be an instance of Type"` ); }); diff --git a/src/core/server/plugins/plugin.ts b/src/core/server/plugins/plugin.ts index ff61d8033a484..c0b484515ccce 100644 --- a/src/core/server/plugins/plugin.ts +++ b/src/core/server/plugins/plugin.ts @@ -27,9 +27,9 @@ import { Plugin, PluginInitializerContext, PluginManifest, - PluginConfigSchema, PluginInitializer, PluginOpaqueId, + PluginConfigDescriptor, } from './types'; import { CoreSetup, CoreStart } from '..'; @@ -128,7 +128,7 @@ export class PluginWrapper< this.instance = undefined; } - public getConfigSchema(): PluginConfigSchema { + public getConfigDescriptor(): PluginConfigDescriptor | null { if (!this.manifest.server) { return null; } @@ -141,10 +141,11 @@ export class PluginWrapper< return null; } - if (!(pluginDefinition.config.schema instanceof Type)) { + const configDescriptor = pluginDefinition.config; + if (!(configDescriptor.schema instanceof Type)) { throw new Error('Configuration schema expected to be an instance of Type'); } - return pluginDefinition.config.schema; + return configDescriptor; } private createPluginInstance() { diff --git a/src/core/server/plugins/plugins_service.mock.ts b/src/core/server/plugins/plugins_service.mock.ts index c8b6bed044fd7..e3be8fbb98309 100644 --- a/src/core/server/plugins/plugins_service.mock.ts +++ b/src/core/server/plugins/plugins_service.mock.ts @@ -33,6 +33,7 @@ const createServiceMock = () => { public: new Map(), internal: new Map(), }, + uiPluginConfigs: new Map(), }); mocked.start.mockResolvedValue({ contracts: new Map() }); return mocked; diff --git a/src/core/server/plugins/plugins_service.test.ts b/src/core/server/plugins/plugins_service.test.ts index 0b3bc0759463c..da6d1d5a010e7 100644 --- a/src/core/server/plugins/plugins_service.test.ts +++ b/src/core/server/plugins/plugins_service.test.ts @@ -32,6 +32,8 @@ import { PluginWrapper } from './plugin'; import { PluginsService } from './plugins_service'; import { PluginsSystem } from './plugins_system'; import { config } from './plugins_config'; +import { take } from 'rxjs/operators'; +import { DiscoveredPluginInternal } from './types'; const MockPluginsSystem: jest.Mock = PluginsSystem as any; @@ -90,301 +92,398 @@ const createPlugin = ( }); }; -beforeEach(async () => { - mockPackage.raw = { - branch: 'feature-v1', - version: 'v1', - build: { - distributable: true, - number: 100, - sha: 'feature-v1-build-sha', - }, - }; - - coreId = Symbol('core'); - env = Env.createDefault(getEnvOptions()); - - configService = new ConfigService( - new BehaviorSubject(new ObjectToConfigAdapter({ plugins: { initialize: true } })), - env, - logger - ); - await configService.setSchema(config.path, config.schema); - pluginsService = new PluginsService({ coreId, env, logger, configService }); +describe('PluginsService', () => { + beforeEach(async () => { + mockPackage.raw = { + branch: 'feature-v1', + version: 'v1', + build: { + distributable: true, + number: 100, + sha: 'feature-v1-build-sha', + }, + }; - [mockPluginSystem] = MockPluginsSystem.mock.instances as any; -}); + coreId = Symbol('core'); + env = Env.createDefault(getEnvOptions()); -afterEach(() => { - jest.clearAllMocks(); -}); + configService = new ConfigService( + new BehaviorSubject(new ObjectToConfigAdapter({ plugins: { initialize: true } })), + env, + logger + ); + await configService.setSchema(config.path, config.schema); + pluginsService = new PluginsService({ coreId, env, logger, configService }); -test('`discover` throws if plugin has an invalid manifest', async () => { - mockDiscover.mockReturnValue({ - error$: from([PluginDiscoveryError.invalidManifest('path-1', new Error('Invalid JSON'))]), - plugin$: from([]), + [mockPluginSystem] = MockPluginsSystem.mock.instances as any; }); - await expect(pluginsService.discover()).rejects.toMatchInlineSnapshot(` -[Error: Failed to initialize plugins: - Invalid JSON (invalid-manifest, path-1)] -`); - expect(loggingServiceMock.collect(logger).error).toMatchInlineSnapshot(` -Array [ - Array [ - [Error: Invalid JSON (invalid-manifest, path-1)], - ], -] -`); -}); - -test('`discover` throws if plugin required Kibana version is incompatible with the current version', async () => { - mockDiscover.mockReturnValue({ - error$: from([ - PluginDiscoveryError.incompatibleVersion('path-3', new Error('Incompatible version')), - ]), - plugin$: from([]), + afterEach(() => { + jest.clearAllMocks(); }); - await expect(pluginsService.discover()).rejects.toMatchInlineSnapshot(` -[Error: Failed to initialize plugins: - Incompatible version (incompatible-version, path-3)] -`); - expect(loggingServiceMock.collect(logger).error).toMatchInlineSnapshot(` -Array [ - Array [ - [Error: Incompatible version (incompatible-version, path-3)], - ], -] -`); -}); - -test('`discover` throws if discovered plugins with conflicting names', async () => { - mockDiscover.mockReturnValue({ - error$: from([]), - plugin$: from([ - createPlugin('conflicting-id', { - path: 'path-4', - version: 'some-version', - configPath: 'path', - requiredPlugins: ['some-required-plugin', 'some-required-plugin-2'], - optionalPlugins: ['some-optional-plugin'], - }), - createPlugin('conflicting-id', { - path: 'path-4', - version: 'some-version', - configPath: 'path', - requiredPlugins: ['some-required-plugin', 'some-required-plugin-2'], - optionalPlugins: ['some-optional-plugin'], - }), - ]), - }); - - await expect(pluginsService.discover()).rejects.toMatchInlineSnapshot( - `[Error: Plugin with id "conflicting-id" is already registered!]` - ); + describe('#discover()', () => { + it('throws if plugin has an invalid manifest', async () => { + mockDiscover.mockReturnValue({ + error$: from([PluginDiscoveryError.invalidManifest('path-1', new Error('Invalid JSON'))]), + plugin$: from([]), + }); + + await expect(pluginsService.discover()).rejects.toMatchInlineSnapshot(` + [Error: Failed to initialize plugins: + Invalid JSON (invalid-manifest, path-1)] + `); + expect(loggingServiceMock.collect(logger).error).toMatchInlineSnapshot(` + Array [ + Array [ + [Error: Invalid JSON (invalid-manifest, path-1)], + ], + ] + `); + }); + + it('throws if plugin required Kibana version is incompatible with the current version', async () => { + mockDiscover.mockReturnValue({ + error$: from([ + PluginDiscoveryError.incompatibleVersion('path-3', new Error('Incompatible version')), + ]), + plugin$: from([]), + }); + + await expect(pluginsService.discover()).rejects.toMatchInlineSnapshot(` + [Error: Failed to initialize plugins: + Incompatible version (incompatible-version, path-3)] + `); + expect(loggingServiceMock.collect(logger).error).toMatchInlineSnapshot(` + Array [ + Array [ + [Error: Incompatible version (incompatible-version, path-3)], + ], + ] + `); + }); + + it('throws if discovered plugins with conflicting names', async () => { + mockDiscover.mockReturnValue({ + error$: from([]), + plugin$: from([ + createPlugin('conflicting-id', { + path: 'path-4', + version: 'some-version', + configPath: 'path', + requiredPlugins: ['some-required-plugin', 'some-required-plugin-2'], + optionalPlugins: ['some-optional-plugin'], + }), + createPlugin('conflicting-id', { + path: 'path-4', + version: 'some-version', + configPath: 'path', + requiredPlugins: ['some-required-plugin', 'some-required-plugin-2'], + optionalPlugins: ['some-optional-plugin'], + }), + ]), + }); + + await expect(pluginsService.discover()).rejects.toMatchInlineSnapshot( + `[Error: Plugin with id "conflicting-id" is already registered!]` + ); + + expect(mockPluginSystem.addPlugin).not.toHaveBeenCalled(); + expect(mockPluginSystem.setupPlugins).not.toHaveBeenCalled(); + }); + + it('properly detects plugins that should be disabled.', async () => { + jest + .spyOn(configService, 'isEnabledAtPath') + .mockImplementation(path => Promise.resolve(!path.includes('disabled'))); + + mockPluginSystem.setupPlugins.mockResolvedValue(new Map()); + mockPluginSystem.uiPlugins.mockReturnValue({ public: new Map(), internal: new Map() }); + + mockDiscover.mockReturnValue({ + error$: from([]), + plugin$: from([ + createPlugin('explicitly-disabled-plugin', { + disabled: true, + path: 'path-1', + configPath: 'path-1', + }), + createPlugin('plugin-with-missing-required-deps', { + path: 'path-2', + configPath: 'path-2', + requiredPlugins: ['missing-plugin'], + }), + createPlugin('plugin-with-disabled-transitive-dep', { + path: 'path-3', + configPath: 'path-3', + requiredPlugins: ['another-explicitly-disabled-plugin'], + }), + createPlugin('another-explicitly-disabled-plugin', { + disabled: true, + path: 'path-4', + configPath: 'path-4-disabled', + }), + ]), + }); + + await pluginsService.discover(); + const setup = await pluginsService.setup(setupDeps); + + expect(setup.contracts).toBeInstanceOf(Map); + expect(setup.uiPlugins.public).toBeInstanceOf(Map); + expect(setup.uiPlugins.internal).toBeInstanceOf(Map); + expect(mockPluginSystem.addPlugin).not.toHaveBeenCalled(); + expect(mockPluginSystem.setupPlugins).toHaveBeenCalledTimes(1); + expect(mockPluginSystem.setupPlugins).toHaveBeenCalledWith(setupDeps); + + expect(loggingServiceMock.collect(logger).info).toMatchInlineSnapshot(` + Array [ + Array [ + "Plugin \\"explicitly-disabled-plugin\\" is disabled.", + ], + Array [ + "Plugin \\"plugin-with-missing-required-deps\\" has been disabled since some of its direct or transitive dependencies are missing or disabled.", + ], + Array [ + "Plugin \\"plugin-with-disabled-transitive-dep\\" has been disabled since some of its direct or transitive dependencies are missing or disabled.", + ], + Array [ + "Plugin \\"another-explicitly-disabled-plugin\\" is disabled.", + ], + ] + `); + }); + + it('does not throw in case of mutual plugin dependencies', async () => { + const firstPlugin = createPlugin('first-plugin', { + path: 'path-1', + requiredPlugins: ['second-plugin'], + }); + const secondPlugin = createPlugin('second-plugin', { + path: 'path-2', + requiredPlugins: ['first-plugin'], + }); - expect(mockPluginSystem.addPlugin).not.toHaveBeenCalled(); - expect(mockPluginSystem.setupPlugins).not.toHaveBeenCalled(); -}); + mockDiscover.mockReturnValue({ + error$: from([]), + plugin$: from([firstPlugin, secondPlugin]), + }); -test('`discover` properly detects plugins that should be disabled.', async () => { - jest - .spyOn(configService, 'isEnabledAtPath') - .mockImplementation(path => Promise.resolve(!path.includes('disabled'))); + await expect(pluginsService.discover()).resolves.toBeUndefined(); - mockPluginSystem.setupPlugins.mockResolvedValue(new Map()); - mockPluginSystem.uiPlugins.mockReturnValue({ public: new Map(), internal: new Map() }); + expect(mockDiscover).toHaveBeenCalledTimes(1); + expect(mockPluginSystem.addPlugin).toHaveBeenCalledTimes(2); + expect(mockPluginSystem.addPlugin).toHaveBeenCalledWith(firstPlugin); + expect(mockPluginSystem.addPlugin).toHaveBeenCalledWith(secondPlugin); + }); - mockDiscover.mockReturnValue({ - error$: from([]), - plugin$: from([ - createPlugin('explicitly-disabled-plugin', { - disabled: true, + it('does not throw in case of cyclic plugin dependencies', async () => { + const firstPlugin = createPlugin('first-plugin', { path: 'path-1', - configPath: 'path-1', - }), - createPlugin('plugin-with-missing-required-deps', { + requiredPlugins: ['second-plugin'], + }); + const secondPlugin = createPlugin('second-plugin', { path: 'path-2', - configPath: 'path-2', - requiredPlugins: ['missing-plugin'], - }), - createPlugin('plugin-with-disabled-transitive-dep', { + requiredPlugins: ['third-plugin', 'last-plugin'], + }); + const thirdPlugin = createPlugin('third-plugin', { path: 'path-3', - configPath: 'path-3', - requiredPlugins: ['another-explicitly-disabled-plugin'], - }), - createPlugin('another-explicitly-disabled-plugin', { - disabled: true, + requiredPlugins: ['last-plugin', 'first-plugin'], + }); + const lastPlugin = createPlugin('last-plugin', { path: 'path-4', - configPath: 'path-4-disabled', - }), - ]), - }); - - await pluginsService.discover(); - const setup = await pluginsService.setup(setupDeps); - - expect(setup.contracts).toBeInstanceOf(Map); - expect(setup.uiPlugins.public).toBeInstanceOf(Map); - expect(setup.uiPlugins.internal).toBeInstanceOf(Map); - expect(mockPluginSystem.addPlugin).not.toHaveBeenCalled(); - expect(mockPluginSystem.setupPlugins).toHaveBeenCalledTimes(1); - expect(mockPluginSystem.setupPlugins).toHaveBeenCalledWith(setupDeps); - - expect(loggingServiceMock.collect(logger).info).toMatchInlineSnapshot(` -Array [ - Array [ - "Plugin \\"explicitly-disabled-plugin\\" is disabled.", - ], - Array [ - "Plugin \\"plugin-with-missing-required-deps\\" has been disabled since some of its direct or transitive dependencies are missing or disabled.", - ], - Array [ - "Plugin \\"plugin-with-disabled-transitive-dep\\" has been disabled since some of its direct or transitive dependencies are missing or disabled.", - ], - Array [ - "Plugin \\"another-explicitly-disabled-plugin\\" is disabled.", - ], -] -`); -}); - -test('`discover` does not throw in case of mutual plugin dependencies', async () => { - const firstPlugin = createPlugin('first-plugin', { - path: 'path-1', - requiredPlugins: ['second-plugin'], - }); - const secondPlugin = createPlugin('second-plugin', { - path: 'path-2', - requiredPlugins: ['first-plugin'], - }); - - mockDiscover.mockReturnValue({ - error$: from([]), - plugin$: from([firstPlugin, secondPlugin]), - }); - - await expect(pluginsService.discover()).resolves.toBeUndefined(); - - expect(mockDiscover).toHaveBeenCalledTimes(1); - expect(mockPluginSystem.addPlugin).toHaveBeenCalledTimes(2); - expect(mockPluginSystem.addPlugin).toHaveBeenCalledWith(firstPlugin); - expect(mockPluginSystem.addPlugin).toHaveBeenCalledWith(secondPlugin); -}); - -test('`discover` does not throw in case of cyclic plugin dependencies', async () => { - const firstPlugin = createPlugin('first-plugin', { - path: 'path-1', - requiredPlugins: ['second-plugin'], - }); - const secondPlugin = createPlugin('second-plugin', { - path: 'path-2', - requiredPlugins: ['third-plugin', 'last-plugin'], - }); - const thirdPlugin = createPlugin('third-plugin', { - path: 'path-3', - requiredPlugins: ['last-plugin', 'first-plugin'], - }); - const lastPlugin = createPlugin('last-plugin', { - path: 'path-4', - requiredPlugins: ['first-plugin'], - }); - const missingDepsPlugin = createPlugin('missing-deps-plugin', { - path: 'path-5', - requiredPlugins: ['not-a-plugin'], - }); - - mockDiscover.mockReturnValue({ - error$: from([]), - plugin$: from([firstPlugin, secondPlugin, thirdPlugin, lastPlugin, missingDepsPlugin]), - }); - - await expect(pluginsService.discover()).resolves.toBeUndefined(); - - expect(mockDiscover).toHaveBeenCalledTimes(1); - expect(mockPluginSystem.addPlugin).toHaveBeenCalledTimes(4); - expect(mockPluginSystem.addPlugin).toHaveBeenCalledWith(firstPlugin); - expect(mockPluginSystem.addPlugin).toHaveBeenCalledWith(secondPlugin); - expect(mockPluginSystem.addPlugin).toHaveBeenCalledWith(thirdPlugin); - expect(mockPluginSystem.addPlugin).toHaveBeenCalledWith(lastPlugin); -}); - -test('`discover` properly invokes plugin discovery and ignores non-critical errors.', async () => { - const firstPlugin = createPlugin('some-id', { - path: 'path-1', - configPath: 'path', - requiredPlugins: ['some-other-id'], - optionalPlugins: ['missing-optional-dep'], - }); - const secondPlugin = createPlugin('some-other-id', { - path: 'path-2', - version: 'some-other-version', - configPath: ['plugin', 'path'], - }); - - mockDiscover.mockReturnValue({ - error$: from([ - PluginDiscoveryError.missingManifest('path-2', new Error('No manifest')), - PluginDiscoveryError.invalidSearchPath('dir-1', new Error('No dir')), - PluginDiscoveryError.invalidPluginPath('path4-1', new Error('No path')), - ]), - plugin$: from([firstPlugin, secondPlugin]), + requiredPlugins: ['first-plugin'], + }); + const missingDepsPlugin = createPlugin('missing-deps-plugin', { + path: 'path-5', + requiredPlugins: ['not-a-plugin'], + }); + + mockDiscover.mockReturnValue({ + error$: from([]), + plugin$: from([firstPlugin, secondPlugin, thirdPlugin, lastPlugin, missingDepsPlugin]), + }); + + await expect(pluginsService.discover()).resolves.toBeUndefined(); + + expect(mockDiscover).toHaveBeenCalledTimes(1); + expect(mockPluginSystem.addPlugin).toHaveBeenCalledTimes(4); + expect(mockPluginSystem.addPlugin).toHaveBeenCalledWith(firstPlugin); + expect(mockPluginSystem.addPlugin).toHaveBeenCalledWith(secondPlugin); + expect(mockPluginSystem.addPlugin).toHaveBeenCalledWith(thirdPlugin); + expect(mockPluginSystem.addPlugin).toHaveBeenCalledWith(lastPlugin); + }); + + it('properly invokes plugin discovery and ignores non-critical errors.', async () => { + const firstPlugin = createPlugin('some-id', { + path: 'path-1', + configPath: 'path', + requiredPlugins: ['some-other-id'], + optionalPlugins: ['missing-optional-dep'], + }); + const secondPlugin = createPlugin('some-other-id', { + path: 'path-2', + version: 'some-other-version', + configPath: ['plugin', 'path'], + }); + + mockDiscover.mockReturnValue({ + error$: from([ + PluginDiscoveryError.missingManifest('path-2', new Error('No manifest')), + PluginDiscoveryError.invalidSearchPath('dir-1', new Error('No dir')), + PluginDiscoveryError.invalidPluginPath('path4-1', new Error('No path')), + ]), + plugin$: from([firstPlugin, secondPlugin]), + }); + + await pluginsService.discover(); + expect(mockPluginSystem.addPlugin).toHaveBeenCalledTimes(2); + expect(mockPluginSystem.addPlugin).toHaveBeenCalledWith(firstPlugin); + expect(mockPluginSystem.addPlugin).toHaveBeenCalledWith(secondPlugin); + + expect(mockDiscover).toHaveBeenCalledTimes(1); + expect(mockDiscover).toHaveBeenCalledWith( + { + additionalPluginPaths: [], + initialize: true, + pluginSearchPaths: [ + resolve(process.cwd(), 'src', 'plugins'), + resolve(process.cwd(), 'x-pack', 'plugins'), + resolve(process.cwd(), 'plugins'), + resolve(process.cwd(), '..', 'kibana-extra'), + ], + }, + { coreId, env, logger, configService } + ); + + const logs = loggingServiceMock.collect(logger); + expect(logs.info).toHaveLength(0); + expect(logs.error).toHaveLength(0); + }); + + it('registers plugin config schema in config service', async () => { + const configSchema = schema.string(); + jest.spyOn(configService, 'setSchema').mockImplementation(() => Promise.resolve()); + jest.doMock( + join('path-with-schema', 'server'), + () => ({ + config: { + schema: configSchema, + }, + }), + { + virtual: true, + } + ); + mockDiscover.mockReturnValue({ + error$: from([]), + plugin$: from([ + createPlugin('some-id', { + path: 'path-with-schema', + configPath: 'path', + }), + ]), + }); + await pluginsService.discover(); + expect(configService.setSchema).toBeCalledWith('path', configSchema); + }); }); - await pluginsService.discover(); - expect(mockPluginSystem.addPlugin).toHaveBeenCalledTimes(2); - expect(mockPluginSystem.addPlugin).toHaveBeenCalledWith(firstPlugin); - expect(mockPluginSystem.addPlugin).toHaveBeenCalledWith(secondPlugin); - - expect(mockDiscover).toHaveBeenCalledTimes(1); - expect(mockDiscover).toHaveBeenCalledWith( - { - additionalPluginPaths: [], - initialize: true, - pluginSearchPaths: [ - resolve(process.cwd(), 'src', 'plugins'), - resolve(process.cwd(), 'x-pack', 'plugins'), - resolve(process.cwd(), 'plugins'), - resolve(process.cwd(), '..', 'kibana-extra'), - ], - }, - { coreId, env, logger, configService } - ); - - const logs = loggingServiceMock.collect(logger); - expect(logs.info).toHaveLength(0); - expect(logs.error).toHaveLength(0); -}); - -test('`stop` stops plugins system', async () => { - await pluginsService.stop(); - expect(mockPluginSystem.stopPlugins).toHaveBeenCalledTimes(1); -}); - -test('`discover` registers plugin config schema in config service', async () => { - const configSchema = schema.string(); - jest.spyOn(configService, 'setSchema').mockImplementation(() => Promise.resolve()); - jest.doMock( - join('path-with-schema', 'server'), - () => ({ - config: { - schema: configSchema, + describe('#generateUiPluginsConfigs()', () => { + const pluginToDiscoveredEntry = (plugin: PluginWrapper): [string, DiscoveredPluginInternal] => [ + plugin.name, + { + id: plugin.name, + path: plugin.path, + configPath: plugin.manifest.configPath, + requiredPlugins: [], + optionalPlugins: [], }, - }), - { - virtual: true, - } - ); - mockDiscover.mockReturnValue({ - error$: from([]), - plugin$: from([ - createPlugin('some-id', { - path: 'path-with-schema', + ]; + + it('properly generates client configs for plugins according to `exposeToBrowser`', async () => { + jest.doMock( + join('plugin-with-expose', 'server'), + () => ({ + config: { + exposeToBrowser: { + sharedProp: true, + }, + schema: schema.object({ + serverProp: schema.string({ defaultValue: 'serverProp default value' }), + sharedProp: schema.string({ defaultValue: 'sharedProp default value' }), + }), + }, + }), + { + virtual: true, + } + ); + const plugin = createPlugin('plugin-with-expose', { + path: 'plugin-with-expose', configPath: 'path', - }), - ]), + }); + mockDiscover.mockReturnValue({ + error$: from([]), + plugin$: from([plugin]), + }); + mockPluginSystem.uiPlugins.mockReturnValue({ + public: new Map([pluginToDiscoveredEntry(plugin)]), + internal: new Map([pluginToDiscoveredEntry(plugin)]), + }); + + await pluginsService.discover(); + const { uiPluginConfigs } = await pluginsService.setup(setupDeps); + + const uiConfig$ = uiPluginConfigs.get('plugin-with-expose'); + expect(uiConfig$).toBeDefined(); + + const uiConfig = await uiConfig$!.pipe(take(1)).toPromise(); + expect(uiConfig).toMatchInlineSnapshot(` + Object { + "sharedProp": "sharedProp default value", + } + `); + }); + + it('does not generate config for plugins not exposing to client', async () => { + jest.doMock( + join('plugin-without-expose', 'server'), + () => ({ + config: { + schema: schema.object({ + serverProp: schema.string({ defaultValue: 'serverProp default value' }), + }), + }, + }), + { + virtual: true, + } + ); + const plugin = createPlugin('plugin-without-expose', { + path: 'plugin-without-expose', + configPath: 'path', + }); + mockDiscover.mockReturnValue({ + error$: from([]), + plugin$: from([plugin]), + }); + mockPluginSystem.uiPlugins.mockReturnValue({ + public: new Map([pluginToDiscoveredEntry(plugin)]), + internal: new Map([pluginToDiscoveredEntry(plugin)]), + }); + + await pluginsService.discover(); + const { uiPluginConfigs } = await pluginsService.setup(setupDeps); + + expect([...uiPluginConfigs.entries()]).toHaveLength(0); + }); + }); + + describe('#stop()', () => { + it('`stop` stops plugins system', async () => { + await pluginsService.stop(); + expect(mockPluginSystem.stopPlugins).toHaveBeenCalledTimes(1); + }); }); - await pluginsService.discover(); - expect(configService.setSchema).toBeCalledWith('path', configSchema); }); diff --git a/src/core/server/plugins/plugins_service.ts b/src/core/server/plugins/plugins_service.ts index 38fe519567a63..79c9489a8b4c0 100644 --- a/src/core/server/plugins/plugins_service.ts +++ b/src/core/server/plugins/plugins_service.ts @@ -25,10 +25,17 @@ import { CoreContext } from '../core_context'; import { Logger } from '../logging'; import { discover, PluginDiscoveryError, PluginDiscoveryErrorType } from './discovery'; import { PluginWrapper } from './plugin'; -import { DiscoveredPlugin, DiscoveredPluginInternal, PluginName } from './types'; +import { + DiscoveredPlugin, + DiscoveredPluginInternal, + PluginConfigDescriptor, + PluginName, +} from './types'; import { PluginsConfig, PluginsConfigType } from './plugins_config'; import { PluginsSystem } from './plugins_system'; import { InternalCoreSetup } from '../internal_types'; +import { IConfigService } from '../config'; +import { pick } from '../../utils'; /** @public */ export interface PluginsServiceSetup { @@ -37,6 +44,7 @@ export interface PluginsServiceSetup { public: Map; internal: Map; }; + uiPluginConfigs: Map>; } /** @public */ @@ -54,11 +62,14 @@ export interface PluginsServiceStartDeps {} // eslint-disable-line @typescript-e export class PluginsService implements CoreService { private readonly log: Logger; private readonly pluginsSystem: PluginsSystem; + private readonly configService: IConfigService; private readonly config$: Observable; + private readonly pluginConfigDescriptors = new Map(); constructor(private readonly coreContext: CoreContext) { this.log = coreContext.logger.get('plugins-service'); this.pluginsSystem = new PluginsSystem(coreContext); + this.configService = coreContext.configService; this.config$ = coreContext.configService .atPath('plugins') .pipe(map(rawConfig => new PluginsConfig(rawConfig, coreContext.env))); @@ -82,17 +93,18 @@ export class PluginsService implements CoreService(); if (!config.initialize || this.coreContext.env.isDevClusterMaster) { this.log.info('Plugin initialization disabled.'); - return { - contracts: new Map(), - uiPlugins: this.pluginsSystem.uiPlugins(), - }; + } else { + contracts = await this.pluginsSystem.setupPlugins(deps); } + const uiPlugins = this.pluginsSystem.uiPlugins(); return { - contracts: await this.pluginsSystem.setupPlugins(deps), - uiPlugins: this.pluginsSystem.uiPlugins(), + contracts, + uiPlugins, + uiPluginConfigs: this.generateUiPluginsConfigs(uiPlugins.public), }; } @@ -107,6 +119,38 @@ export class PluginsService implements CoreService + ): Map> { + return new Map( + [...uiPlugins] + .filter(([pluginId, _]) => { + const configDescriptor = this.pluginConfigDescriptors.get(pluginId); + return ( + configDescriptor && + configDescriptor.exposeToBrowser && + Object.values(configDescriptor?.exposeToBrowser).some(exposed => exposed) + ); + }) + .map(([pluginId, plugin]) => { + const configDescriptor = this.pluginConfigDescriptors.get(pluginId)!; + return [ + pluginId, + this.configService.atPath(plugin.configPath).pipe( + map((config: any) => + pick( + config || {}, + Object.entries(configDescriptor.exposeToBrowser!) + .filter(([_, exposed]) => exposed) + .map(([key, _]) => key) + ) + ) + ), + ]; + }) + ); + } + private async handleDiscoveryErrors(error$: Observable) { // At this stage we report only errors that can occur when new platform plugin // manifest is present, otherwise we can't be sure that the plugin is for the new @@ -138,9 +182,13 @@ export class PluginsService implements CoreService { - const schema = plugin.getConfigSchema(); - if (schema) { - await this.coreContext.configService.setSchema(plugin.configPath, schema); + const configDescriptor = plugin.getConfigDescriptor(); + if (configDescriptor) { + this.pluginConfigDescriptors.set(plugin.name, configDescriptor); + await this.coreContext.configService.setSchema( + plugin.configPath, + configDescriptor.schema + ); } const isEnabled = await this.coreContext.configService.isEnabledAtPath(plugin.configPath); diff --git a/src/core/server/plugins/types.ts b/src/core/server/plugins/types.ts index 9a3e922b3cb89..17704ce687b92 100644 --- a/src/core/server/plugins/types.ts +++ b/src/core/server/plugins/types.ts @@ -24,7 +24,51 @@ import { ConfigPath, EnvironmentMode, PackageInfo } from '../config'; import { LoggerFactory } from '../logging'; import { CoreSetup, CoreStart } from '..'; -export type PluginConfigSchema = Type | null; +/** + * Dedicated type for plugin configuration schema. + * + * @public + */ +export type PluginConfigSchema = Type; + +/** + * Describes a plugin configuration schema and capabilities. + * + * @example + * ```typescript + * // my_plugin/server/index.ts + * import { schema, TypeOf } from '@kbn/config-schema'; + * import { PluginConfigDescriptor } from 'kibana/server'; + * + * const configSchema = schema.object({ + * secret: schema.string({ defaultValue: 'Only on server' }), + * uiProp: schema.string({ defaultValue: 'Accessible from client' }), + * }); + * + * type ConfigType = TypeOf; + * + * export const config: PluginConfigDescriptor = { + * exposeToBrowser: { + * uiProp: true, + * }, + * schema: configSchema, + * }; + * ``` + * + * @public + */ +export interface PluginConfigDescriptor { + /** + * List of configuration properties that will be available on the client-side plugin. + */ + exposeToBrowser?: { [P in keyof T]?: boolean }; + /** + * Schema to use to validate the plugin configuration. + * + * {@link PluginConfigSchema} + */ + schema: PluginConfigSchema; +} /** * Dedicated type for plugin name/id that is supposed to make Map/Set/Arrays diff --git a/src/core/server/server.api.md b/src/core/server/server.api.md index 97a04a4a4efab..7ecb9053a4bcf 100644 --- a/src/core/server/server.api.md +++ b/src/core/server/server.api.md @@ -959,6 +959,17 @@ export interface Plugin { + exposeToBrowser?: { + [P in keyof T]?: boolean; + }; + schema: PluginConfigSchema; +} + +// @public +export type PluginConfigSchema = Type; + // @public export type PluginInitializer = (core: PluginInitializerContext) => Plugin; @@ -1003,6 +1014,8 @@ export interface PluginsServiceSetup { // (undocumented) contracts: Map; // (undocumented) + uiPluginConfigs: Map>; + // (undocumented) uiPlugins: { public: Map; internal: Map; @@ -1615,6 +1628,6 @@ export interface UserProvidedValues { // Warnings were encountered during analysis: // // src/core/server/http/router/response.ts:316:3 - (ae-forgotten-export) The symbol "KibanaResponse" needs to be exported by the entry point index.d.ts -// src/core/server/plugins/plugins_service.ts:38:5 - (ae-forgotten-export) The symbol "DiscoveredPluginInternal" needs to be exported by the entry point index.d.ts +// src/core/server/plugins/plugins_service.ts:45:5 - (ae-forgotten-export) The symbol "DiscoveredPluginInternal" needs to be exported by the entry point index.d.ts ``` diff --git a/src/dev/build/tasks/clean_tasks.js b/src/dev/build/tasks/clean_tasks.js index 3ec1d6b6967e9..c33dfe6262128 100644 --- a/src/dev/build/tasks/clean_tasks.js +++ b/src/dev/build/tasks/clean_tasks.js @@ -169,7 +169,6 @@ export const CleanExtraFilesFromModulesTask = { await scanDelete({ directory: build.resolvePath('node_modules'), regularExpressions, - excludePaths: [build.resolvePath('node_modules/@elastic/ctags-langserver/vendor')], }) ); diff --git a/src/fixtures/stubbed_logstash_index_pattern.js b/src/fixtures/stubbed_logstash_index_pattern.js index e1fa5db8b7140..9f6d648477d29 100644 --- a/src/fixtures/stubbed_logstash_index_pattern.js +++ b/src/fixtures/stubbed_logstash_index_pattern.js @@ -21,6 +21,7 @@ import StubIndexPattern from 'test_utils/stub_index_pattern'; import stubbedLogstashFields from 'fixtures/logstash_fields'; import { getKbnFieldType } from '../plugins/data/common'; +import { mockUiSettings } from '../legacy/ui/public/new_platform/new_platform.karma_mock'; export default function stubbedLogstashIndexPatternService() { const mockLogstashFields = stubbedLogstashFields(); @@ -40,7 +41,7 @@ export default function stubbedLogstashIndexPatternService() { }; }); - const indexPattern = new StubIndexPattern('logstash-*', cfg => cfg, 'time', fields); + const indexPattern = new StubIndexPattern('logstash-*', cfg => cfg, 'time', fields, mockUiSettings); indexPattern.id = 'logstash-*'; indexPattern.isTimeNanosBased = () => false; diff --git a/src/legacy/core_plugins/data/public/filter/filter_bar/filter_bar.tsx b/src/legacy/core_plugins/data/public/filter/filter_bar/filter_bar.tsx index 5b389f5b98aba..23c9c9ffc94bb 100644 --- a/src/legacy/core_plugins/data/public/filter/filter_bar/filter_bar.tsx +++ b/src/legacy/core_plugins/data/public/filter/filter_bar/filter_bar.tsx @@ -21,13 +21,12 @@ import { EuiButtonEmpty, EuiFlexGroup, EuiFlexItem, EuiPopover } from '@elastic/ import { FormattedMessage, InjectedIntl, injectI18n } from '@kbn/i18n/react'; import classNames from 'classnames'; import React, { useState } from 'react'; -import { CoreStart } from 'src/core/public'; import { IndexPattern } from '../../index_patterns'; import { FilterEditor } from './filter_editor'; import { FilterItem } from './filter_item'; import { FilterOptions } from './filter_options'; -import { useKibana, KibanaContextProvider } from '../../../../../../plugins/kibana_react/public'; -import { DataPublicPluginStart, esFilters } from '../../../../../../plugins/data/public'; +import { useKibana } from '../../../../../../plugins/kibana_react/public'; +import { esFilters } from '../../../../../../plugins/data/public'; interface Props { filters: esFilters.Filter[]; @@ -35,48 +34,15 @@ interface Props { className: string; indexPatterns: IndexPattern[]; intl: InjectedIntl; - - // TODO: Only for filter-bar directive! - uiSettings?: CoreStart['uiSettings']; - docLinks?: CoreStart['docLinks']; - pluginDataStart?: DataPublicPluginStart; } function FilterBarUI(props: Props) { const [isAddFilterPopoverOpen, setIsAddFilterPopoverOpen] = useState(false); const kibana = useKibana(); - const uiSettings = kibana.services.uiSettings || props.uiSettings; + const uiSettings = kibana.services.uiSettings; if (!uiSettings) return null; - function hasContext() { - return Boolean(kibana.services.uiSettings); - } - - function wrapInContextIfMissing(content: JSX.Element) { - // TODO: Relevant only as long as directives are used! - if (!hasContext()) { - if (props.docLinks && props.uiSettings && props.pluginDataStart) { - return ( - - {content} - - ); - } else { - throw new Error( - 'Rending filter bar requires providing sufficient context: uiSettings, docLinks and NP data plugin' - ); - } - } - return content; - } - function onFiltersUpdated(filters: esFilters.Filter[]) { if (props.onFiltersUpdated) { props.onFiltersUpdated(filters); @@ -119,7 +85,7 @@ function FilterBarUI(props: Props) { ); - return wrapInContextIfMissing( + return ( { const filter = { ...phraseFilter, diff --git a/src/legacy/core_plugins/data/public/filter/filter_bar/filter_editor/phrase_suggestor.tsx b/src/legacy/core_plugins/data/public/filter/filter_bar/filter_editor/phrase_suggestor.tsx index 426c21c99ccdb..c8b36d84f440e 100644 --- a/src/legacy/core_plugins/data/public/filter/filter_bar/filter_editor/phrase_suggestor.tsx +++ b/src/legacy/core_plugins/data/public/filter/filter_bar/filter_editor/phrase_suggestor.tsx @@ -24,7 +24,7 @@ import { withKibana, KibanaReactContextValue, } from '../../../../../../../plugins/kibana_react/public'; -import { IDataPluginServices } from '../../../types'; +import { IDataPluginServices } from '../../../../../../../plugins/data/public'; export interface PhraseSuggestorProps { kibana: KibanaReactContextValue; diff --git a/src/legacy/core_plugins/data/public/index_patterns/fields/field.ts b/src/legacy/core_plugins/data/public/index_patterns/fields/field.ts index 6084b4c106452..91964655f6f3e 100644 --- a/src/legacy/core_plugins/data/public/index_patterns/fields/field.ts +++ b/src/legacy/core_plugins/data/public/index_patterns/fields/field.ts @@ -17,15 +17,13 @@ * under the License. */ -// @ts-ignore -import { fieldFormats } from 'ui/registry/field_formats'; import { i18n } from '@kbn/i18n'; // @ts-ignore import { ObjDefine } from './obj_define'; // @ts-ignore import { shortenDottedString } from '../../../../../core_plugins/kibana/common/utils/shorten_dotted_string'; import { IndexPattern } from '../index_patterns'; -import { getNotifications } from '../services'; +import { getNotifications, getFieldFormats } from '../services'; import { FieldFormat, @@ -104,6 +102,8 @@ export class Field implements FieldType { let format = spec.format; if (!format || !(format instanceof FieldFormat)) { + const fieldFormats = getFieldFormats(); + format = indexPattern.fieldFormatMap[spec.name] || fieldFormats.getDefaultInstance(spec.type, spec.esTypes); diff --git a/src/legacy/core_plugins/data/public/index_patterns/index_patterns/index_pattern.test.ts b/src/legacy/core_plugins/data/public/index_patterns/index_patterns/index_pattern.test.ts index 2d43faf49f63d..ee9f9b493ebf2 100644 --- a/src/legacy/core_plugins/data/public/index_patterns/index_patterns/index_pattern.test.ts +++ b/src/legacy/core_plugins/data/public/index_patterns/index_patterns/index_pattern.test.ts @@ -27,17 +27,14 @@ import mockLogStashFields from '../../../../../../fixtures/logstash_fields'; import { stubbedSavedObjectIndexPattern } from '../../../../../../fixtures/stubbed_saved_object_index_pattern'; import { Field } from '../index_patterns_service'; -import { setNotifications } from '../services'; +import { setNotifications, setFieldFormats } from '../services'; // Temporary disable eslint, will be removed after moving to new platform folder // eslint-disable-next-line @kbn/eslint/no-restricted-paths import { notificationServiceMock } from '../../../../../../core/public/notifications/notifications_service.mock'; +import { FieldFormatRegisty } from '../../../../../../plugins/data/public'; -jest.mock('ui/registry/field_formats', () => ({ - fieldFormats: { - getDefaultInstance: jest.fn(), - }, -})); +jest.mock('ui/new_platform'); jest.mock('../../../../../../plugins/kibana_utils/public', () => { const originalModule = jest.requireActual('../../../../../../plugins/kibana_utils/public'); @@ -142,6 +139,9 @@ describe('IndexPattern', () => { // create an indexPattern instance for each test beforeEach(() => { setNotifications(notifications); + setFieldFormats(({ + getDefaultInstance: jest.fn(), + } as unknown) as FieldFormatRegisty); return create(indexPatternId).then((pattern: IndexPattern) => { indexPattern = pattern; diff --git a/src/legacy/core_plugins/data/public/index_patterns/index_patterns/index_pattern.ts b/src/legacy/core_plugins/data/public/index_patterns/index_patterns/index_pattern.ts index 12aa3c2fb0d51..f77342c7bc274 100644 --- a/src/legacy/core_plugins/data/public/index_patterns/index_patterns/index_pattern.ts +++ b/src/legacy/core_plugins/data/public/index_patterns/index_patterns/index_pattern.ts @@ -19,8 +19,6 @@ import _, { each, reject } from 'lodash'; import { i18n } from '@kbn/i18n'; -// @ts-ignore -import { fieldFormats } from 'ui/registry/field_formats'; import { SavedObjectsClientContract } from 'src/core/public'; import { DuplicateField, @@ -30,6 +28,12 @@ import { MappingObject, } from '../../../../../../plugins/kibana_utils/public'; +import { + ES_FIELD_TYPES, + KBN_FIELD_TYPES, + IIndexPattern, +} from '../../../../../../plugins/data/public'; + import { findIndexPatternByTitle, getRoutes } from '../utils'; import { IndexPatternMissingIndices } from '../errors'; import { Field, FieldList, FieldListInterface, FieldType } from '../fields'; @@ -37,8 +41,7 @@ import { createFieldsFetcher } from './_fields_fetcher'; import { formatHitProvider } from './format_hit'; import { flattenHitWrapper } from './flatten_hit'; import { IIndexPatternsApiClient } from './index_patterns_api_client'; -import { ES_FIELD_TYPES, IIndexPattern } from '../../../../../../plugins/data/public'; -import { getNotifications } from '../services'; +import { getNotifications, getFieldFormats } from '../services'; const MAX_ATTEMPTS_TO_RESOLVE_CONFLICTS = 3; const type = 'index-pattern'; @@ -114,7 +117,10 @@ export class IndexPattern implements IIndexPattern { this.fields = new FieldList(this, [], this.shortDotsEnable); this.fieldsFetcher = createFieldsFetcher(this, apiClient, this.getConfig('metaFields')); this.flattenHit = flattenHitWrapper(this, this.getConfig('metaFields')); - this.formatHit = formatHitProvider(this, fieldFormats.getDefaultInstance('string')); + this.formatHit = formatHitProvider( + this, + getFieldFormats().getDefaultInstance(KBN_FIELD_TYPES.STRING) + ); this.formatField = this.formatHit.formatField; } @@ -125,12 +131,14 @@ export class IndexPattern implements IIndexPattern { } private deserializeFieldFormatMap(mapping: any) { - const FieldFormat = fieldFormats.getType(mapping.id); + const FieldFormat = getFieldFormats().getType(mapping.id); + return FieldFormat && new FieldFormat(mapping.params, this.getConfig); } private initFields(input?: any) { const newValue = input || this.fields; + this.fields = new FieldList(this, newValue, this.shortDotsEnable); } @@ -451,6 +459,7 @@ export class IndexPattern implements IIndexPattern { const { toasts } = getNotifications(); toasts.addDanger(message); + throw err; } @@ -492,6 +501,7 @@ export class IndexPattern implements IIndexPattern { if (err instanceof IndexPatternMissingIndices) { toasts.addDanger((err as any).message); + return []; } diff --git a/src/legacy/core_plugins/data/public/index_patterns/index_patterns/index_patterns.test.ts b/src/legacy/core_plugins/data/public/index_patterns/index_patterns/index_patterns.test.ts index 8a5c78d13c251..0a5d1bfcae21f 100644 --- a/src/legacy/core_plugins/data/public/index_patterns/index_patterns/index_patterns.test.ts +++ b/src/legacy/core_plugins/data/public/index_patterns/index_patterns/index_patterns.test.ts @@ -29,12 +29,6 @@ jest.mock('../errors', () => ({ IndexPatternMissingIndices: jest.fn(), })); -jest.mock('ui/registry/field_formats', () => ({ - fieldFormats: { - getDefaultInstance: jest.fn(), - }, -})); - jest.mock('./index_pattern', () => { class IndexPattern { init = async () => { diff --git a/src/legacy/core_plugins/data/public/index_patterns/index_patterns/index_patterns.ts b/src/legacy/core_plugins/data/public/index_patterns/index_patterns/index_patterns.ts index 2c58af9deaf49..c8e80b3aede20 100644 --- a/src/legacy/core_plugins/data/public/index_patterns/index_patterns/index_patterns.ts +++ b/src/legacy/core_plugins/data/public/index_patterns/index_patterns/index_patterns.ts @@ -24,8 +24,6 @@ import { UiSettingsClientContract, HttpServiceBase, } from 'src/core/public'; -// @ts-ignore -import { fieldFormats } from 'ui/registry/field_formats'; import { createIndexPatternCache } from './_pattern_cache'; import { IndexPattern } from './index_pattern'; @@ -34,8 +32,6 @@ import { IndexPatternsApiClient, GetFieldsOptions } from './index_patterns_api_c const indexPatternCache = createIndexPatternCache(); export class IndexPatterns { - fieldFormats: fieldFormats; - private config: UiSettingsClientContract; private savedObjectsClient: SavedObjectsClientContract; private savedObjectsCache?: Array>> | null; diff --git a/src/legacy/core_plugins/data/public/index_patterns/index_patterns_service.ts b/src/legacy/core_plugins/data/public/index_patterns/index_patterns_service.ts index 9ce1b5f2e4a20..c9c52400b1f19 100644 --- a/src/legacy/core_plugins/data/public/index_patterns/index_patterns_service.ts +++ b/src/legacy/core_plugins/data/public/index_patterns/index_patterns_service.ts @@ -23,9 +23,10 @@ import { HttpServiceBase, NotificationsStart, } from 'src/core/public'; +import { FieldFormatsStart } from '../../../../../plugins/data/public'; import { Field, FieldList, FieldListInterface, FieldType } from './fields'; import { createIndexPatternSelect } from './components'; -import { setNotifications } from './services'; +import { setNotifications, setFieldFormats } from './services'; import { createFlattenHitWrapper, @@ -40,6 +41,7 @@ export interface IndexPatternDependencies { savedObjectsClient: SavedObjectsClientContract; http: HttpServiceBase; notifications: NotificationsStart; + fieldFormats: FieldFormatsStart; } /** @@ -64,8 +66,15 @@ export class IndexPatternsService { return this.setupApi; } - public start({ uiSettings, savedObjectsClient, http, notifications }: IndexPatternDependencies) { + public start({ + uiSettings, + savedObjectsClient, + http, + notifications, + fieldFormats, + }: IndexPatternDependencies) { setNotifications(notifications); + setFieldFormats(fieldFormats); return { ...this.setupApi, diff --git a/src/legacy/core_plugins/data/public/index_patterns/services.ts b/src/legacy/core_plugins/data/public/index_patterns/services.ts index 5cc087548d6fb..ecd898b28de63 100644 --- a/src/legacy/core_plugins/data/public/index_patterns/services.ts +++ b/src/legacy/core_plugins/data/public/index_patterns/services.ts @@ -19,7 +19,12 @@ import { NotificationsStart } from 'src/core/public'; import { createGetterSetter } from '../../../../../plugins/kibana_utils/public'; +import { FieldFormatsStart } from '../../../../../plugins/data/public'; export const [getNotifications, setNotifications] = createGetterSetter( 'Notifications' ); + +export const [getFieldFormats, setFieldFormats] = createGetterSetter( + 'FieldFormats' +); diff --git a/src/legacy/core_plugins/data/public/plugin.ts b/src/legacy/core_plugins/data/public/plugin.ts index 2059f61fde59e..da24576655d2b 100644 --- a/src/legacy/core_plugins/data/public/plugin.ts +++ b/src/legacy/core_plugins/data/public/plugin.ts @@ -94,6 +94,7 @@ export class DataPlugin implements Plugin void; onChange: (payload: { dateRange: TimeRange; query?: Query }) => void; onRefresh?: (payload: { dateRange: TimeRange }) => void; + dataTestSubj?: string; disableAutoFocus?: boolean; screenTitle?: string; indexPatterns?: Array; @@ -189,6 +190,7 @@ function QueryBarTopRowUI(props: Props) { onChange={onQueryChange} onSubmit={onInputSubmit} persistedLog={persistedLog} + dataTestSubj={props.dataTestSubj} /> ); diff --git a/src/legacy/core_plugins/data/public/search/search_bar/components/search_bar.tsx b/src/legacy/core_plugins/data/public/search/search_bar/components/search_bar.tsx index e97c06ace1579..c8b76c9cda99d 100644 --- a/src/legacy/core_plugins/data/public/search/search_bar/components/search_bar.tsx +++ b/src/legacy/core_plugins/data/public/search/search_bar/components/search_bar.tsx @@ -35,8 +35,8 @@ import { withKibana, KibanaReactContextValue, } from '../../../../../../../plugins/kibana_react/public'; -import { IDataPluginServices } from '../../../types'; import { + IDataPluginServices, TimeRange, Query, esFilters, @@ -64,7 +64,7 @@ export interface SearchBarOwnProps { isLoading?: boolean; customSubmitButton?: React.ReactNode; screenTitle?: string; - + dataTestSubj?: string; // Togglers showQueryBar?: boolean; showQueryInput?: boolean; @@ -415,6 +415,7 @@ class SearchBarUI extends Component { customSubmitButton={ this.props.customSubmitButton ? this.props.customSubmitButton : undefined } + dataTestSubj={this.props.dataTestSubj} /> ); } diff --git a/src/legacy/core_plugins/data/public/shim/legacy_module.ts b/src/legacy/core_plugins/data/public/shim/legacy_module.ts index edc389b411971..06c5caa04ba9a 100644 --- a/src/legacy/core_plugins/data/public/shim/legacy_module.ts +++ b/src/legacy/core_plugins/data/public/shim/legacy_module.ts @@ -19,58 +19,11 @@ import { once } from 'lodash'; -import { wrapInI18nContext } from 'ui/i18n'; - // @ts-ignore import { uiModules } from 'ui/modules'; -import { npStart } from 'ui/new_platform'; -import { FilterBar } from '../filter'; import { IndexPatterns } from '../index_patterns/index_patterns'; /** @internal */ export const initLegacyModule = once((indexPatterns: IndexPatterns): void => { - uiModules - .get('app/kibana', ['react']) - .directive('filterBar', () => { - return { - restrict: 'E', - template: '', - compile: (elem: any) => { - const child = document.createElement('filter-bar-helper'); - - // Copy attributes to the child directive - for (const attr of elem[0].attributes) { - child.setAttribute(attr.name, attr.value); - } - - child.setAttribute('ui-settings', 'uiSettings'); - child.setAttribute('doc-links', 'docLinks'); - child.setAttribute('plugin-data-start', 'pluginDataStart'); - - // Append helper directive - elem.append(child); - - const linkFn = ($scope: any) => { - $scope.uiSettings = npStart.core.uiSettings; - $scope.docLinks = npStart.core.docLinks; - $scope.pluginDataStart = npStart.plugins.data; - }; - - return linkFn; - }, - }; - }) - .directive('filterBarHelper', (reactDirective: any) => { - return reactDirective(wrapInI18nContext(FilterBar), [ - ['uiSettings', { watchDepth: 'reference' }], - ['docLinks', { watchDepth: 'reference' }], - ['onFiltersUpdated', { watchDepth: 'reference' }], - ['indexPatterns', { watchDepth: 'collection' }], - ['filters', { watchDepth: 'collection' }], - ['className', { watchDepth: 'reference' }], - ['pluginDataStart', { watchDepth: 'reference' }], - ]); - }); - uiModules.get('kibana/index_patterns').value('indexPatterns', indexPatterns); }); diff --git a/src/legacy/core_plugins/kibana/index.js b/src/legacy/core_plugins/kibana/index.js index c7cda8aec0165..dcb7d7998ff1a 100644 --- a/src/legacy/core_plugins/kibana/index.js +++ b/src/legacy/core_plugins/kibana/index.js @@ -64,7 +64,6 @@ export default function (kibana) { hacks: [ 'plugins/kibana/dev_tools', ], - fieldFormats: ['plugins/kibana/field_formats/register'], savedObjectTypes: [ 'plugins/kibana/visualize/saved_visualizations/saved_visualization_register', 'plugins/kibana/discover/saved_searches/saved_search_register', diff --git a/src/legacy/core_plugins/kibana/public/dashboard/dashboard_app.html b/src/legacy/core_plugins/kibana/public/dashboard/dashboard_app.html index a94fd500257d9..b645bb408300f 100644 --- a/src/legacy/core_plugins/kibana/public/dashboard/dashboard_app.html +++ b/src/legacy/core_plugins/kibana/public/dashboard/dashboard_app.html @@ -36,8 +36,7 @@ --> ({ - fieldFormats: { - getDefaultInstance: jest.fn(), - }, -})); - jest.mock('ui/state_management/state', () => ({ State: {}, })); diff --git a/src/legacy/core_plugins/kibana/public/dashboard/help_menu/help_menu.js b/src/legacy/core_plugins/kibana/public/dashboard/help_menu/help_menu.js deleted file mode 100644 index 1b1a7f84c8131..0000000000000 --- a/src/legacy/core_plugins/kibana/public/dashboard/help_menu/help_menu.js +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR 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 { EuiButton, EuiHorizontalRule, EuiSpacer } from '@elastic/eui'; -import { FormattedMessage, I18nProvider } from '@kbn/i18n/react'; - -export class HelpMenu extends PureComponent { - render() { - return ( - - <> - - - - - - - - ); - } -} diff --git a/src/legacy/core_plugins/kibana/public/dashboard/help_menu/help_menu_util.js b/src/legacy/core_plugins/kibana/public/dashboard/help_menu/help_menu_util.js index 2dc8ce523a7da..55abfa179b56d 100644 --- a/src/legacy/core_plugins/kibana/public/dashboard/help_menu/help_menu_util.js +++ b/src/legacy/core_plugins/kibana/public/dashboard/help_menu/help_menu_util.js @@ -17,15 +17,19 @@ * under the License. */ -import React from 'react'; -import { render, unmountComponentAtNode } from 'react-dom'; -import { HelpMenu } from './help_menu'; +import { i18n } from '@kbn/i18n'; +import { ELASTIC_WEBSITE_URL, DOC_LINK_VERSION } from 'ui/documentation_links'; -export function addHelpMenuToAppChrome(chrome, docLinks) { - chrome.setHelpExtension(domElement => { - render(, domElement); - return () => { - unmountComponentAtNode(domElement); - }; +export function addHelpMenuToAppChrome(chrome) { + chrome.setHelpExtension({ + appName: i18n.translate('kbn.dashboard.helpMenu.appName', { + defaultMessage: 'Dashboards', + }), + links: [ + { + linkType: 'documentation', + href: `${ELASTIC_WEBSITE_URL}guide/en/kibana/${DOC_LINK_VERSION}/dashboard.html`, + }, + ], }); } diff --git a/src/legacy/core_plugins/kibana/public/discover/__tests__/directives/field_chooser.js b/src/legacy/core_plugins/kibana/public/discover/__tests__/directives/field_chooser.js index a5b55e50eb90e..bac56f008233c 100644 --- a/src/legacy/core_plugins/kibana/public/discover/__tests__/directives/field_chooser.js +++ b/src/legacy/core_plugins/kibana/public/discover/__tests__/directives/field_chooser.js @@ -241,7 +241,6 @@ describe('discover field chooser directives', function () { $scope.computeDetails(field); expect(field.details.buckets).to.not.be(undefined); expect(field.details.buckets[0].value).to.be(40.141592); - expect(field.details.buckets[0].display).to.be('40.142'); }); diff --git a/src/legacy/core_plugins/kibana/public/discover/angular/context_app.html b/src/legacy/core_plugins/kibana/public/discover/angular/context_app.html index 68e1d536a91ce..3e0f8a8329154 100644 --- a/src/legacy/core_plugins/kibana/public/discover/angular/context_app.html +++ b/src/legacy/core_plugins/kibana/public/discover/angular/context_app.html @@ -1,9 +1,16 @@ - +> + +
{ - render(, domElement); - return () => { - unmountComponentAtNode(domElement); - }; + chrome.setHelpExtension({ + appName: i18n.translate('kbn.discover.helpMenu.appName', { + defaultMessage: 'Discover', + }), + links: [ + { + linkType: 'documentation', + href: `${docLinks.ELASTIC_WEBSITE_URL}guide/en/kibana/${docLinks.DOC_LINK_VERSION}/discover.html`, + }, + ], }); } diff --git a/src/legacy/core_plugins/kibana/public/field_formats/__tests__/_conformance.js b/src/legacy/core_plugins/kibana/public/field_formats/__tests__/_conformance.js deleted file mode 100644 index 1c63d2efc7e0b..0000000000000 --- a/src/legacy/core_plugins/kibana/public/field_formats/__tests__/_conformance.js +++ /dev/null @@ -1,142 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES 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 '@kbn/expect'; -import { fieldFormats } from 'ui/registry/field_formats'; -import { npStart } from 'ui/new_platform'; -import { FieldFormat } from '../../../../../../plugins/data/public'; - -const config = npStart.core.uiSettings; - -const formatIds = [ - 'bytes', - 'date', - 'date_nanos', - 'duration', - 'ip', - 'number', - 'percent', - 'color', - 'string', - 'url', - '_source', - 'truncate', - 'boolean', - 'relative_date', - 'static_lookup' -]; - -// eslint-disable-next-line import/no-default-export -export default describe('conformance', function () { - - const getConfig = (...args) => config.get(...args); - - formatIds.forEach(function (id) { - let instance; - let Type; - - beforeEach(function () { - Type = fieldFormats.getType(id); - instance = fieldFormats.getInstance(id); - }); - - describe(id + ' Type', function () { - it('has an id', function () { - expect(Type.id).to.be.a('string'); - }); - - it('has a title', function () { - expect(Type.title).to.be.a('string'); - }); - - it('declares compatible field formats as a string or array', function () { - expect(Type.fieldType).to.be.ok(); - expect(_.isString(Type.fieldType) || Array.isArray(Type.fieldType)).to.be(true); - }); - }); - - describe(id + ' Instance', function () { - it('extends FieldFormat', function () { - expect(instance).to.be.a(FieldFormat); - }); - }); - }); - - it('registers all of the fieldFormats', function () { - expect(_.difference(fieldFormats.raw, formatIds.map(fieldFormats.getType))).to.eql([]); - }); - - describe('Bytes format', basicPatternTests('bytes', require('numeral'))); - describe('Percent Format', basicPatternTests('percent', require('numeral'))); - describe('Date Format', basicPatternTests('date', require('moment'))); - - describe('Number Format', function () { - basicPatternTests('number', require('numeral'))(); - - it('tries to parse strings', function () { - const number = new (fieldFormats.getType('number'))({ pattern: '0.0b' }, getConfig); - expect(number.convert(123.456)).to.be('123.5B'); - expect(number.convert('123.456')).to.be('123.5B'); - }); - - }); - - function basicPatternTests(id, lib) { - const confKey = id === 'date' ? 'dateFormat' : 'format:' + id + ':defaultPattern'; - - return function () { - it('converts using the format:' + id + ':defaultPattern config', function () { - const inst = fieldFormats.getInstance(id); - [ - '0b', - '0 b', - '0.[000] b', - '0.[000]b', - '0.[0]b' - ].forEach(function (pattern) { - const original = config.get(confKey); - const num = _.random(-10000, 10000, true); - config.set(confKey, pattern); - expect(inst.convert(num)).to.be(lib(num).format(pattern)); - config.set(confKey, original); - }); - }); - - it('uses the pattern param if available', function () { - const original = config.get(confKey); - const num = _.random(-10000, 10000, true); - const defFormat = '0b'; - const customFormat = '0.00000%'; - - config.set(confKey, defFormat); - const defInst = fieldFormats.getInstance(id); - - const Type = fieldFormats.getType(id); - const customInst = new Type({ pattern: customFormat }, getConfig); - - expect(defInst.convert(num)).to.not.be(customInst.convert(num)); - expect(defInst.convert(num)).to.be(lib(num).format(defFormat)); - expect(customInst.convert(num)).to.be(lib(num).format(customFormat)); - - config.set(confKey, original); - }); - }; - } -}); diff --git a/src/legacy/core_plugins/kibana/public/home/components/__snapshots__/add_data.test.js.snap b/src/legacy/core_plugins/kibana/public/home/components/__snapshots__/add_data.test.js.snap index bbcb2096b6f64..35a7216df8bc6 100644 --- a/src/legacy/core_plugins/kibana/public/home/components/__snapshots__/add_data.test.js.snap +++ b/src/legacy/core_plugins/kibana/public/home/components/__snapshots__/add_data.test.js.snap @@ -67,10 +67,7 @@ exports[`apmUiEnabled 1`] = ` type="logoAPM" /> } - layout="vertical" - textAlign="center" title="APM" - titleElement="span" /> } - layout="vertical" - textAlign="center" title="Logs" - titleElement="span" /> } - layout="vertical" - textAlign="center" title="Metrics" - titleElement="span" /> } - layout="vertical" - textAlign="center" title="SIEM" - titleElement="span" /> @@ -332,10 +320,7 @@ exports[`isNewKibanaInstance 1`] = ` type="logoLogging" /> } - layout="vertical" - textAlign="center" title="Logs" - titleElement="span" /> } - layout="vertical" - textAlign="center" title="Metrics" - titleElement="span" /> } - layout="vertical" - textAlign="center" title="SIEM" - titleElement="span" /> @@ -560,10 +539,7 @@ exports[`mlEnabled 1`] = ` type="logoAPM" /> } - layout="vertical" - textAlign="center" title="APM" - titleElement="span" /> } - layout="vertical" - textAlign="center" title="Logs" - titleElement="span" /> } - layout="vertical" - textAlign="center" title="Metrics" - titleElement="span" /> } - layout="vertical" - textAlign="center" title="SIEM" - titleElement="span" /> @@ -861,10 +828,7 @@ exports[`render 1`] = ` type="logoLogging" /> } - layout="vertical" - textAlign="center" title="Logs" - titleElement="span" /> } - layout="vertical" - textAlign="center" title="Metrics" - titleElement="span" /> } - layout="vertical" - textAlign="center" title="SIEM" - titleElement="span" /> diff --git a/src/legacy/core_plugins/kibana/public/home/components/__snapshots__/synopsis.test.js.snap b/src/legacy/core_plugins/kibana/public/home/components/__snapshots__/synopsis.test.js.snap index 1970d048be4fd..34cc0eb9265ff 100644 --- a/src/legacy/core_plugins/kibana/public/home/components/__snapshots__/synopsis.test.js.snap +++ b/src/legacy/core_plugins/kibana/public/home/components/__snapshots__/synopsis.test.js.snap @@ -14,9 +14,7 @@ exports[`props iconType 1`] = ` /> } layout="horizontal" - textAlign="center" title="Great tutorial" - titleElement="span" /> `; @@ -35,9 +33,7 @@ exports[`props iconUrl 1`] = ` /> } layout="horizontal" - textAlign="center" title="Great tutorial" - titleElement="span" /> `; @@ -49,9 +45,7 @@ exports[`props isBeta 1`] = ` description="this is a great tutorial about..." href="link_to_item" layout="horizontal" - textAlign="center" title="Great tutorial" - titleElement="span" /> `; @@ -63,8 +57,6 @@ exports[`render 1`] = ` description="this is a great tutorial about..." href="link_to_item" layout="horizontal" - textAlign="center" title="Great tutorial" - titleElement="span" /> `; diff --git a/src/legacy/core_plugins/kibana/public/kibana.js b/src/legacy/core_plugins/kibana/public/kibana.js index 14fc2ec6ead00..98def2252b75c 100644 --- a/src/legacy/core_plugins/kibana/public/kibana.js +++ b/src/legacy/core_plugins/kibana/public/kibana.js @@ -31,7 +31,6 @@ import 'uiExports/visTypes'; import 'uiExports/visEditorTypes'; import 'uiExports/visualize'; import 'uiExports/savedObjectTypes'; -import 'uiExports/fieldFormats'; import 'uiExports/fieldFormatEditors'; import 'uiExports/navbarExtensions'; import 'uiExports/contextMenuActions'; diff --git a/src/legacy/core_plugins/kibana/public/visualize/editor/editor.html b/src/legacy/core_plugins/kibana/public/visualize/editor/editor.html index 0ef3cce832bc7..bf9ac9b9bbe36 100644 --- a/src/legacy/core_plugins/kibana/public/visualize/editor/editor.html +++ b/src/legacy/core_plugins/kibana/public/visualize/editor/editor.html @@ -1,7 +1,7 @@
@@ -33,6 +33,7 @@ show-query-bar is set to "true". -->
{ + $scope.$evalAsync(() => { + $scope.isVisible = isVisible; + }); + })); + // update the searchSource when query updates $scope.fetch = function () { $state.save(); diff --git a/src/legacy/core_plugins/kibana/public/visualize/help_menu/help_menu_util.js b/src/legacy/core_plugins/kibana/public/visualize/help_menu/help_menu_util.js index 58a92193de63e..d27003f39d4c0 100644 --- a/src/legacy/core_plugins/kibana/public/visualize/help_menu/help_menu_util.js +++ b/src/legacy/core_plugins/kibana/public/visualize/help_menu/help_menu_util.js @@ -17,15 +17,20 @@ * under the License. */ -import React from 'react'; -import { render, unmountComponentAtNode } from 'react-dom'; -import { HelpMenu } from './help_menu'; +import { i18n } from '@kbn/i18n'; +import { getServices } from '../kibana_services'; +const { docLinks } = getServices(); export function addHelpMenuToAppChrome(chrome) { - chrome.setHelpExtension(domElement => { - render(, domElement); - return () => { - unmountComponentAtNode(domElement); - }; + chrome.setHelpExtension({ + appName: i18n.translate('kbn.visualize.helpMenu.appName', { + defaultMessage: 'Visualize', + }), + links: [ + { + linkType: 'documentation', + href: `${docLinks.ELASTIC_WEBSITE_URL}guide/en/kibana/${docLinks.DOC_LINK_VERSION}/visualize.html`, + }, + ], }); } diff --git a/src/legacy/core_plugins/kibana/server/tutorials/apm/index_pattern.json b/src/legacy/core_plugins/kibana/server/tutorials/apm/index_pattern.json index f54c2fa35f80d..69a165c09c2f9 100644 --- a/src/legacy/core_plugins/kibana/server/tutorials/apm/index_pattern.json +++ b/src/legacy/core_plugins/kibana/server/tutorials/apm/index_pattern.json @@ -1,11 +1,11 @@ { "attributes": { - "fieldFormatMap": "{\"client.bytes\":{\"id\":\"bytes\"},\"client.nat.port\":{\"id\":\"string\"},\"client.port\":{\"id\":\"string\"},\"destination.bytes\":{\"id\":\"bytes\"},\"destination.nat.port\":{\"id\":\"string\"},\"destination.port\":{\"id\":\"string\"},\"event.duration\":{\"id\":\"duration\",\"params\":{\"inputFormat\":\"nanoseconds\",\"outputFormat\":\"asMilliseconds\",\"outputPrecision\":1}},\"event.sequence\":{\"id\":\"string\"},\"event.severity\":{\"id\":\"string\"},\"http.request.body.bytes\":{\"id\":\"bytes\"},\"http.request.bytes\":{\"id\":\"bytes\"},\"http.response.body.bytes\":{\"id\":\"bytes\"},\"http.response.bytes\":{\"id\":\"bytes\"},\"http.response.status_code\":{\"id\":\"string\"},\"network.bytes\":{\"id\":\"bytes\"},\"process.pgid\":{\"id\":\"string\"},\"process.pid\":{\"id\":\"string\"},\"process.ppid\":{\"id\":\"string\"},\"process.thread.id\":{\"id\":\"string\"},\"server.bytes\":{\"id\":\"bytes\"},\"server.nat.port\":{\"id\":\"string\"},\"server.port\":{\"id\":\"string\"},\"source.bytes\":{\"id\":\"bytes\"},\"source.nat.port\":{\"id\":\"string\"},\"source.port\":{\"id\":\"string\"},\"system.cpu.total.norm.pct\":{\"id\":\"percent\"},\"system.memory.actual.free\":{\"id\":\"bytes\"},\"system.memory.total\":{\"id\":\"bytes\"},\"system.process.cpu.total.norm.pct\":{\"id\":\"percent\"},\"system.process.memory.rss.bytes\":{\"id\":\"bytes\"},\"system.process.memory.size\":{\"id\":\"bytes\"},\"url.port\":{\"id\":\"string\"},\"view spans\":{\"id\":\"url\",\"params\":{\"labelTemplate\":\"View Spans\"}}}", - "fields": "[{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"@timestamp\",\"scripted\":false,\"searchable\":true,\"type\":\"date\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"labels\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"message\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tags\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"agent.ephemeral_id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"agent.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"agent.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"agent.type\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"agent.version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"as.number\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"as.organization.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.address\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.as.number\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.as.organization.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.bytes\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.geo.city_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.geo.continent_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.geo.country_iso_code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.geo.country_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.geo.location\",\"scripted\":false,\"searchable\":true,\"type\":\"geo_point\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.geo.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.geo.region_iso_code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.geo.region_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.ip\",\"scripted\":false,\"searchable\":true,\"type\":\"ip\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.mac\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.nat.ip\",\"scripted\":false,\"searchable\":true,\"type\":\"ip\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.nat.port\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.packets\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.port\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.user.domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.user.email\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.user.full_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.user.group.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.user.group.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.user.hash\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.user.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.user.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"cloud.account.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"cloud.availability_zone\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"cloud.instance.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"cloud.instance.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"cloud.machine.type\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"cloud.provider\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"cloud.region\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"container.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"container.image.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"container.image.tag\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"container.labels\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"container.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"container.runtime\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.address\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.as.number\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.as.organization.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.bytes\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.geo.city_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.geo.continent_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.geo.country_iso_code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.geo.country_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.geo.location\",\"scripted\":false,\"searchable\":true,\"type\":\"geo_point\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.geo.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.geo.region_iso_code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.geo.region_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.ip\",\"scripted\":false,\"searchable\":true,\"type\":\"ip\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.mac\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.nat.ip\",\"scripted\":false,\"searchable\":true,\"type\":\"ip\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.nat.port\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.packets\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.port\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.user.domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.user.email\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.user.full_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.user.group.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.user.group.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.user.hash\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.user.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.user.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dns.answers\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dns.answers.class\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dns.answers.data\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dns.answers.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dns.answers.ttl\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dns.answers.type\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dns.header_flags\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dns.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dns.op_code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dns.question.class\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dns.question.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dns.question.registered_domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dns.question.type\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dns.resolved_ip\",\"scripted\":false,\"searchable\":true,\"type\":\"ip\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dns.response_code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dns.type\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"ecs.version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"error.code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":4,\"doc_values\":true,\"indexed\":true,\"name\":\"error.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"error.message\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.action\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.category\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.created\",\"scripted\":false,\"searchable\":true,\"type\":\"date\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.dataset\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.duration\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.end\",\"scripted\":false,\"searchable\":true,\"type\":\"date\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.hash\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.kind\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.module\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.original\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.outcome\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.provider\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.risk_score\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.risk_score_norm\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.sequence\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.severity\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.start\",\"scripted\":false,\"searchable\":true,\"type\":\"date\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.timezone\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.type\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.accessed\",\"scripted\":false,\"searchable\":true,\"type\":\"date\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.created\",\"scripted\":false,\"searchable\":true,\"type\":\"date\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.ctime\",\"scripted\":false,\"searchable\":true,\"type\":\"date\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.device\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.directory\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.extension\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.gid\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.group\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.hash.md5\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.hash.sha1\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.hash.sha256\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.hash.sha512\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.inode\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.mode\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.mtime\",\"scripted\":false,\"searchable\":true,\"type\":\"date\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.owner\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.path\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.size\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.target_path\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.type\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.uid\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"geo.city_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"geo.continent_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"geo.country_iso_code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"geo.country_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"geo.location\",\"scripted\":false,\"searchable\":true,\"type\":\"geo_point\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"geo.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"geo.region_iso_code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"geo.region_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"group.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"group.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"hash.md5\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"hash.sha1\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"hash.sha256\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"hash.sha512\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.architecture\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.geo.city_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.geo.continent_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.geo.country_iso_code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.geo.country_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.geo.location\",\"scripted\":false,\"searchable\":true,\"type\":\"geo_point\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.geo.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.geo.region_iso_code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.geo.region_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.hostname\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.ip\",\"scripted\":false,\"searchable\":true,\"type\":\"ip\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.mac\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.os.family\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.os.full\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.os.kernel\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.os.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.os.platform\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.os.version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.type\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.uptime\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.user.domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.user.email\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.user.full_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.user.group.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.user.group.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.user.hash\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.user.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.user.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"http.request.body.bytes\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"http.request.body.content\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"http.request.bytes\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"http.request.method\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"http.request.referrer\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"http.response.body.bytes\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"http.response.body.content\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"http.response.bytes\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"http.response.status_code\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"http.version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"log.level\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"log.logger\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"log.original\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"network.application\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"network.bytes\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"network.community_id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"network.direction\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"network.forwarded_ip\",\"scripted\":false,\"searchable\":true,\"type\":\"ip\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"network.iana_number\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"network.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"network.packets\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"network.protocol\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"network.transport\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"network.type\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.geo.city_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.geo.continent_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.geo.country_iso_code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.geo.country_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.geo.location\",\"scripted\":false,\"searchable\":true,\"type\":\"geo_point\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.geo.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.geo.region_iso_code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.geo.region_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.hostname\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.ip\",\"scripted\":false,\"searchable\":true,\"type\":\"ip\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.mac\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.os.family\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.os.full\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.os.kernel\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.os.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.os.platform\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.os.version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.serial_number\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.type\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.vendor\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"organization.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"organization.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"os.family\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"os.full\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"os.kernel\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"os.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"os.platform\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"os.version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.args\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.executable\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.hash.md5\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.hash.sha1\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.hash.sha256\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.hash.sha512\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.pgid\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.pid\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.ppid\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.start\",\"scripted\":false,\"searchable\":true,\"type\":\"date\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.thread.id\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.thread.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.title\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.uptime\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.working_directory\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"related.ip\",\"scripted\":false,\"searchable\":true,\"type\":\"ip\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.address\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.as.number\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.as.organization.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.bytes\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.geo.city_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.geo.continent_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.geo.country_iso_code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.geo.country_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.geo.location\",\"scripted\":false,\"searchable\":true,\"type\":\"geo_point\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.geo.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.geo.region_iso_code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.geo.region_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.ip\",\"scripted\":false,\"searchable\":true,\"type\":\"ip\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.mac\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.nat.ip\",\"scripted\":false,\"searchable\":true,\"type\":\"ip\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.nat.port\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.packets\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.port\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.user.domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.user.email\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.user.full_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.user.group.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.user.group.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.user.hash\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.user.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.user.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"service.ephemeral_id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"service.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"service.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"service.state\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"service.type\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"service.version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.address\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.as.number\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.as.organization.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.bytes\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.geo.city_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.geo.continent_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.geo.country_iso_code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.geo.country_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.geo.location\",\"scripted\":false,\"searchable\":true,\"type\":\"geo_point\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.geo.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.geo.region_iso_code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.geo.region_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.ip\",\"scripted\":false,\"searchable\":true,\"type\":\"ip\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.mac\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.nat.ip\",\"scripted\":false,\"searchable\":true,\"type\":\"ip\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.nat.port\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.packets\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.port\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.user.domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.user.email\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.user.full_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.user.group.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.user.group.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.user.hash\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.user.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.user.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tracing.trace.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tracing.transaction.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"url.domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"url.fragment\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"url.full\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"url.original\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"url.password\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"url.path\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"url.port\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"url.query\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"url.scheme\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"url.username\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user.domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user.email\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user.full_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user.group.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user.group.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user.hash\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user_agent.device.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user_agent.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user_agent.original\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user_agent.os.family\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user_agent.os.full\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user_agent.os.kernel\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user_agent.os.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user_agent.os.platform\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user_agent.os.version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user_agent.version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"agent.hostname\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"fields\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"error.type\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"timeseries.instance\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"cloud.project.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"cloud.image.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"docker.container.labels\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.containerized\",\"scripted\":false,\"searchable\":true,\"type\":\"boolean\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.os.build\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.os.codename\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"kubernetes.pod.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"kubernetes.pod.uid\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"kubernetes.namespace\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"kubernetes.node.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"kubernetes.labels.*\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"kubernetes.annotations.*\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"kubernetes.replicaset.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"kubernetes.deployment.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"kubernetes.statefulset.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"kubernetes.container.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"kubernetes.container.image\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"processor.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"processor.event\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":1,\"doc_values\":true,\"indexed\":true,\"name\":\"timestamp.us\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":false,\"enabled\":false,\"indexed\":false,\"name\":\"http.request.headers\",\"scripted\":false,\"searchable\":false},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"http.response.finished\",\"scripted\":false,\"searchable\":true,\"type\":\"boolean\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":false,\"enabled\":false,\"indexed\":false,\"name\":\"http.response.headers\",\"scripted\":false,\"searchable\":false},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"service.environment\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"service.node.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"service.language.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"service.language.version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"service.runtime.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"service.runtime.version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"service.framework.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"service.framework.version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.sampled\",\"scripted\":false,\"searchable\":true,\"type\":\"boolean\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.type\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.name.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.duration.count\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.duration.sum.us\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.self_time.count\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.self_time.sum.us\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.breakdown.count\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":1,\"doc_values\":true,\"indexed\":true,\"name\":\"span.type\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":1,\"doc_values\":true,\"indexed\":true,\"name\":\"span.subtype\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"span.self_time.count\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"span.self_time.sum.us\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"trace.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"parent.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.listening\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.version_major\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user_agent.original.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"experimental\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":true,\"analyzed\":false,\"count\":2,\"doc_values\":true,\"indexed\":true,\"name\":\"error.culprit\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"error.grouping_key\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"error.exception.code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":2,\"doc_values\":true,\"indexed\":true,\"name\":\"error.exception.message\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"error.exception.module\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":4,\"doc_values\":true,\"indexed\":true,\"name\":\"error.exception.type\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":2,\"doc_values\":true,\"indexed\":true,\"name\":\"error.exception.handled\",\"scripted\":false,\"searchable\":true,\"type\":\"boolean\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"error.log.level\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"error.log.logger_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":2,\"doc_values\":true,\"indexed\":true,\"name\":\"error.log.message\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"error.log.param_message\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"system.cpu.total.norm.pct\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"system.memory.total\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"system.memory.actual.free\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"system.process.cpu.total.norm.pct\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"system.process.memory.size\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"system.process.memory.rss.bytes\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"sourcemap.service.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"sourcemap.service.version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"sourcemap.bundle_filepath\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"view spans\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"span.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":1,\"doc_values\":true,\"indexed\":true,\"name\":\"span.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":1,\"doc_values\":true,\"indexed\":true,\"name\":\"span.action\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":1,\"doc_values\":true,\"indexed\":true,\"name\":\"span.start.us\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":1,\"doc_values\":true,\"indexed\":true,\"name\":\"span.duration.us\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"span.sync\",\"scripted\":false,\"searchable\":true,\"type\":\"boolean\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"span.db.link\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.duration.us\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.result\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.marks\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.marks.*.*\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.span_count.dropped\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":false,\"indexed\":false,\"name\":\"_id\",\"scripted\":false,\"searchable\":false,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":false,\"indexed\":false,\"name\":\"_type\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":false,\"indexed\":false,\"name\":\"_index\",\"scripted\":false,\"searchable\":false,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":false,\"indexed\":false,\"name\":\"_score\",\"scripted\":false,\"searchable\":false,\"type\":\"number\"}]", + "fieldFormatMap": "{\"client.bytes\":{\"id\":\"bytes\"},\"client.nat.port\":{\"id\":\"string\"},\"client.port\":{\"id\":\"string\"},\"destination.bytes\":{\"id\":\"bytes\"},\"destination.nat.port\":{\"id\":\"string\"},\"destination.port\":{\"id\":\"string\"},\"event.duration\":{\"id\":\"duration\",\"params\":{\"inputFormat\":\"nanoseconds\",\"outputFormat\":\"asMilliseconds\",\"outputPrecision\":1}},\"event.sequence\":{\"id\":\"string\"},\"event.severity\":{\"id\":\"string\"},\"http.request.body.bytes\":{\"id\":\"bytes\"},\"http.request.bytes\":{\"id\":\"bytes\"},\"http.response.body.bytes\":{\"id\":\"bytes\"},\"http.response.bytes\":{\"id\":\"bytes\"},\"http.response.status_code\":{\"id\":\"string\"},\"log.syslog.facility.code\":{\"id\":\"string\"},\"log.syslog.priority\":{\"id\":\"string\"},\"network.bytes\":{\"id\":\"bytes\"},\"package.size\":{\"id\":\"string\"},\"process.pgid\":{\"id\":\"string\"},\"process.pid\":{\"id\":\"string\"},\"process.ppid\":{\"id\":\"string\"},\"process.thread.id\":{\"id\":\"string\"},\"server.bytes\":{\"id\":\"bytes\"},\"server.nat.port\":{\"id\":\"string\"},\"server.port\":{\"id\":\"string\"},\"source.bytes\":{\"id\":\"bytes\"},\"source.nat.port\":{\"id\":\"string\"},\"source.port\":{\"id\":\"string\"},\"system.cpu.total.norm.pct\":{\"id\":\"percent\"},\"system.memory.actual.free\":{\"id\":\"bytes\"},\"system.memory.total\":{\"id\":\"bytes\"},\"system.process.cpu.total.norm.pct\":{\"id\":\"percent\"},\"system.process.memory.rss.bytes\":{\"id\":\"bytes\"},\"system.process.memory.size\":{\"id\":\"bytes\"},\"url.port\":{\"id\":\"string\"},\"view spans\":{\"id\":\"url\",\"params\":{\"labelTemplate\":\"View Spans\"}}}", + "fields": "[{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"@timestamp\",\"scripted\":false,\"searchable\":true,\"type\":\"date\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"labels\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"message\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tags\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"agent.ephemeral_id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"agent.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"agent.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"agent.type\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"agent.version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"as.number\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"as.organization.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.address\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.as.number\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.as.organization.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.bytes\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.geo.city_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.geo.continent_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.geo.country_iso_code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.geo.country_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.geo.location\",\"scripted\":false,\"searchable\":true,\"type\":\"geo_point\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.geo.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.geo.region_iso_code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.geo.region_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.ip\",\"scripted\":false,\"searchable\":true,\"type\":\"ip\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.mac\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.nat.ip\",\"scripted\":false,\"searchable\":true,\"type\":\"ip\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.nat.port\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.packets\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.port\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.registered_domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.top_level_domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.user.domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.user.email\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.user.full_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.user.group.domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.user.group.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.user.group.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.user.hash\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.user.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.user.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"cloud.account.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"cloud.availability_zone\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"cloud.instance.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"cloud.instance.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"cloud.machine.type\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"cloud.provider\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"cloud.region\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"container.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"container.image.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"container.image.tag\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"container.labels\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"container.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"container.runtime\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.address\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.as.number\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.as.organization.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.bytes\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.geo.city_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.geo.continent_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.geo.country_iso_code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.geo.country_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.geo.location\",\"scripted\":false,\"searchable\":true,\"type\":\"geo_point\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.geo.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.geo.region_iso_code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.geo.region_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.ip\",\"scripted\":false,\"searchable\":true,\"type\":\"ip\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.mac\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.nat.ip\",\"scripted\":false,\"searchable\":true,\"type\":\"ip\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.nat.port\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.packets\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.port\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.registered_domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.top_level_domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.user.domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.user.email\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.user.full_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.user.group.domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.user.group.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.user.group.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.user.hash\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.user.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.user.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dns.answers\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dns.answers.class\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dns.answers.data\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dns.answers.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dns.answers.ttl\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dns.answers.type\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dns.header_flags\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dns.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dns.op_code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dns.question.class\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dns.question.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dns.question.registered_domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dns.question.subdomain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dns.question.top_level_domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dns.question.type\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dns.resolved_ip\",\"scripted\":false,\"searchable\":true,\"type\":\"ip\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dns.response_code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dns.type\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"ecs.version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"error.code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":4,\"doc_values\":true,\"indexed\":true,\"name\":\"error.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"error.message\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"error.stack_trace\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"error.type\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.action\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.category\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.created\",\"scripted\":false,\"searchable\":true,\"type\":\"date\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.dataset\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.duration\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.end\",\"scripted\":false,\"searchable\":true,\"type\":\"date\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.hash\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.kind\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.module\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.original\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.outcome\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.provider\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.risk_score\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.risk_score_norm\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.sequence\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.severity\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.start\",\"scripted\":false,\"searchable\":true,\"type\":\"date\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.timezone\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.type\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.accessed\",\"scripted\":false,\"searchable\":true,\"type\":\"date\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.created\",\"scripted\":false,\"searchable\":true,\"type\":\"date\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.ctime\",\"scripted\":false,\"searchable\":true,\"type\":\"date\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.device\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.directory\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.extension\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.gid\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.group\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.hash.md5\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.hash.sha1\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.hash.sha256\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.hash.sha512\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.inode\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.mode\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.mtime\",\"scripted\":false,\"searchable\":true,\"type\":\"date\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.owner\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.path\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.size\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.target_path\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.type\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.uid\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"geo.city_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"geo.continent_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"geo.country_iso_code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"geo.country_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"geo.location\",\"scripted\":false,\"searchable\":true,\"type\":\"geo_point\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"geo.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"geo.region_iso_code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"geo.region_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"group.domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"group.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"group.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"hash.md5\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"hash.sha1\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"hash.sha256\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"hash.sha512\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.architecture\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.geo.city_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.geo.continent_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.geo.country_iso_code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.geo.country_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.geo.location\",\"scripted\":false,\"searchable\":true,\"type\":\"geo_point\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.geo.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.geo.region_iso_code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.geo.region_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.hostname\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.ip\",\"scripted\":false,\"searchable\":true,\"type\":\"ip\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.mac\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.os.family\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.os.full\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.os.kernel\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.os.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.os.platform\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.os.version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.type\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.uptime\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.user.domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.user.email\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.user.full_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.user.group.domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.user.group.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.user.group.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.user.hash\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.user.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.user.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"http.request.body.bytes\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"http.request.body.content\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"http.request.bytes\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"http.request.method\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"http.request.referrer\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"http.response.body.bytes\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"http.response.body.content\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"http.response.bytes\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"http.response.status_code\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"http.version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"log.level\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"log.logger\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"log.origin.file.line\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"log.origin.file.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"log.origin.function\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"log.original\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"log.syslog\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"log.syslog.facility.code\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"log.syslog.facility.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"log.syslog.priority\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"log.syslog.severity.code\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"log.syslog.severity.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"network.application\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"network.bytes\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"network.community_id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"network.direction\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"network.forwarded_ip\",\"scripted\":false,\"searchable\":true,\"type\":\"ip\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"network.iana_number\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"network.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"network.packets\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"network.protocol\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"network.transport\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"network.type\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.geo.city_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.geo.continent_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.geo.country_iso_code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.geo.country_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.geo.location\",\"scripted\":false,\"searchable\":true,\"type\":\"geo_point\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.geo.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.geo.region_iso_code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.geo.region_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.hostname\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.ip\",\"scripted\":false,\"searchable\":true,\"type\":\"ip\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.mac\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.os.family\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.os.full\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.os.kernel\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.os.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.os.platform\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.os.version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.product\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.serial_number\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.type\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.vendor\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"organization.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"organization.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"os.family\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"os.full\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"os.kernel\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"os.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"os.platform\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"os.version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"package.architecture\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"package.checksum\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"package.description\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"package.install_scope\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"package.installed\",\"scripted\":false,\"searchable\":true,\"type\":\"date\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"package.license\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"package.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"package.path\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"package.size\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"package.version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.args\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.executable\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.hash.md5\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.hash.sha1\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.hash.sha256\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.hash.sha512\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.pgid\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.pid\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.ppid\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.start\",\"scripted\":false,\"searchable\":true,\"type\":\"date\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.thread.id\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.thread.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.title\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.uptime\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.working_directory\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"related.ip\",\"scripted\":false,\"searchable\":true,\"type\":\"ip\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.address\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.as.number\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.as.organization.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.bytes\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.geo.city_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.geo.continent_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.geo.country_iso_code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.geo.country_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.geo.location\",\"scripted\":false,\"searchable\":true,\"type\":\"geo_point\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.geo.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.geo.region_iso_code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.geo.region_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.ip\",\"scripted\":false,\"searchable\":true,\"type\":\"ip\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.mac\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.nat.ip\",\"scripted\":false,\"searchable\":true,\"type\":\"ip\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.nat.port\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.packets\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.port\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.registered_domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.top_level_domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.user.domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.user.email\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.user.full_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.user.group.domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.user.group.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.user.group.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.user.hash\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.user.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.user.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"service.ephemeral_id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"service.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"service.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"service.node.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"service.state\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"service.type\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"service.version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.address\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.as.number\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.as.organization.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.bytes\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.geo.city_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.geo.continent_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.geo.country_iso_code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.geo.country_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.geo.location\",\"scripted\":false,\"searchable\":true,\"type\":\"geo_point\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.geo.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.geo.region_iso_code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.geo.region_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.ip\",\"scripted\":false,\"searchable\":true,\"type\":\"ip\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.mac\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.nat.ip\",\"scripted\":false,\"searchable\":true,\"type\":\"ip\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.nat.port\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.packets\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.port\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.registered_domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.top_level_domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.user.domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.user.email\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.user.full_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.user.group.domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.user.group.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.user.group.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.user.hash\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.user.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.user.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"threat.framework\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"threat.tactic.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"threat.tactic.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"threat.tactic.reference\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"threat.technique.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"threat.technique.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"threat.technique.reference\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tracing.trace.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tracing.transaction.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"url.domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"url.extension\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"url.fragment\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"url.full\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"url.original\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"url.password\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"url.path\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"url.port\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"url.query\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"url.registered_domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"url.scheme\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"url.top_level_domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"url.username\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user.domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user.email\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user.full_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user.group.domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user.group.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user.group.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user.hash\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user_agent.device.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user_agent.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user_agent.original\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user_agent.os.family\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user_agent.os.full\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user_agent.os.kernel\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user_agent.os.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user_agent.os.platform\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user_agent.os.version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user_agent.version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"agent.hostname\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"fields\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"timeseries.instance\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"cloud.project.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"cloud.image.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"docker.container.labels\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.containerized\",\"scripted\":false,\"searchable\":true,\"type\":\"boolean\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.os.build\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.os.codename\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"kubernetes.pod.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"kubernetes.pod.uid\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"kubernetes.namespace\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"kubernetes.node.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"kubernetes.labels.*\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"kubernetes.annotations.*\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"kubernetes.replicaset.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"kubernetes.deployment.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"kubernetes.statefulset.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"kubernetes.container.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"kubernetes.container.image\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"processor.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"processor.event\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":1,\"doc_values\":true,\"indexed\":true,\"name\":\"timestamp.us\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":false,\"enabled\":false,\"indexed\":false,\"name\":\"http.request.headers\",\"scripted\":false,\"searchable\":false},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"http.response.finished\",\"scripted\":false,\"searchable\":true,\"type\":\"boolean\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":false,\"enabled\":false,\"indexed\":false,\"name\":\"http.response.headers\",\"scripted\":false,\"searchable\":false},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"service.environment\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"service.language.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"service.language.version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"service.runtime.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"service.runtime.version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"service.framework.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"service.framework.version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.sampled\",\"scripted\":false,\"searchable\":true,\"type\":\"boolean\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.type\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.name.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.duration.count\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.duration.sum.us\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.self_time.count\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.self_time.sum.us\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.breakdown.count\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":1,\"doc_values\":true,\"indexed\":true,\"name\":\"span.type\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":1,\"doc_values\":true,\"indexed\":true,\"name\":\"span.subtype\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"span.self_time.count\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"span.self_time.sum.us\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"trace.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"parent.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.listening\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.version_major\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user_agent.original.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"experimental\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":true,\"analyzed\":false,\"count\":2,\"doc_values\":true,\"indexed\":true,\"name\":\"error.culprit\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"error.grouping_key\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"error.exception.code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":2,\"doc_values\":true,\"indexed\":true,\"name\":\"error.exception.message\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"error.exception.module\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":4,\"doc_values\":true,\"indexed\":true,\"name\":\"error.exception.type\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":2,\"doc_values\":true,\"indexed\":true,\"name\":\"error.exception.handled\",\"scripted\":false,\"searchable\":true,\"type\":\"boolean\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"error.log.level\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"error.log.logger_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":2,\"doc_values\":true,\"indexed\":true,\"name\":\"error.log.message\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"error.log.param_message\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"system.cpu.total.norm.pct\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"system.memory.total\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"system.memory.actual.free\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"system.process.cpu.total.norm.pct\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"system.process.memory.size\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"system.process.memory.rss.bytes\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"sourcemap.service.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"sourcemap.service.version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"sourcemap.bundle_filepath\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"view spans\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"span.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":1,\"doc_values\":true,\"indexed\":true,\"name\":\"span.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":1,\"doc_values\":true,\"indexed\":true,\"name\":\"span.action\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":1,\"doc_values\":true,\"indexed\":true,\"name\":\"span.start.us\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":1,\"doc_values\":true,\"indexed\":true,\"name\":\"span.duration.us\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"span.sync\",\"scripted\":false,\"searchable\":true,\"type\":\"boolean\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"span.db.link\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.duration.us\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.result\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.marks\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.marks.*.*\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.span_count.dropped\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":false,\"indexed\":false,\"name\":\"_id\",\"scripted\":false,\"searchable\":false,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":false,\"indexed\":false,\"name\":\"_type\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":false,\"indexed\":false,\"name\":\"_index\",\"scripted\":false,\"searchable\":false,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":false,\"indexed\":false,\"name\":\"_score\",\"scripted\":false,\"searchable\":false,\"type\":\"number\"}]", "sourceFilters": "[{\"value\":\"sourcemap.sourcemap\"}]", "timeFieldName": "@timestamp" }, "id": "apm-*", "type": "index-pattern", "version": "1" -} +} \ No newline at end of file diff --git a/src/legacy/core_plugins/status_page/public/components/__snapshots__/metric_tiles.test.js.snap b/src/legacy/core_plugins/status_page/public/components/__snapshots__/metric_tiles.test.js.snap index ce24ff89776c8..b88210758a00d 100644 --- a/src/legacy/core_plugins/status_page/public/components/__snapshots__/metric_tiles.test.js.snap +++ b/src/legacy/core_plugins/status_page/public/components/__snapshots__/metric_tiles.test.js.snap @@ -4,9 +4,7 @@ exports[`byte metric 1`] = ` `; @@ -14,9 +12,7 @@ exports[`float metric 1`] = ` `; @@ -24,9 +20,7 @@ exports[`general metric 1`] = ` `; @@ -34,8 +28,6 @@ exports[`millisecond metric 1`] = ` `; diff --git a/src/legacy/core_plugins/timelion/public/app.js b/src/legacy/core_plugins/timelion/public/app.js index 5bc5355d7c061..04edfc5b61141 100644 --- a/src/legacy/core_plugins/timelion/public/app.js +++ b/src/legacy/core_plugins/timelion/public/app.js @@ -30,8 +30,6 @@ import { timefilter } from 'ui/timefilter'; import { npStart } from 'ui/new_platform'; import { getSavedSheetBreadcrumbs, getCreateBreadcrumbs } from './breadcrumbs'; -// import the uiExports that we want to "use" -import 'uiExports/fieldFormats'; import 'uiExports/savedObjectTypes'; require('ui/autoload/all'); diff --git a/src/legacy/core_plugins/vis_type_metric/public/__snapshots__/metric_vis_fn.test.ts.snap b/src/legacy/core_plugins/vis_type_metric/public/__snapshots__/metric_vis_fn.test.ts.snap index 9aee51aa6c93d..d0fba4d164dbf 100644 --- a/src/legacy/core_plugins/vis_type_metric/public/__snapshots__/metric_vis_fn.test.ts.snap +++ b/src/legacy/core_plugins/vis_type_metric/public/__snapshots__/metric_vis_fn.test.ts.snap @@ -14,7 +14,7 @@ Object { }, "metric": Object { "colorSchema": "\\"Green to Red\\"", - "colorsRange": undefined, + "colorsRange": "{range from=0 to=10000}", "invertColors": false, "labels": Object { "show": true, diff --git a/src/legacy/core_plugins/vis_type_metric/public/__tests__/metric_vis_controller.js b/src/legacy/core_plugins/vis_type_metric/public/__tests__/metric_vis_controller.js index 8dd2b093c6f91..9f58d00d38271 100644 --- a/src/legacy/core_plugins/vis_type_metric/public/__tests__/metric_vis_controller.js +++ b/src/legacy/core_plugins/vis_type_metric/public/__tests__/metric_vis_controller.js @@ -51,7 +51,7 @@ describe('metric_vis - controller', function () { expect(metrics.length).to.be(1); expect(metrics[0].label).to.be('Count'); - expect(metrics[0].value).to.be(4301021); + expect(metrics[0].value).to.be('4301021'); }); it('should support multi-value metrics', function () { @@ -66,8 +66,8 @@ describe('metric_vis - controller', function () { expect(metrics.length).to.be(2); expect(metrics[0].label).to.be('1st percentile of bytes'); - expect(metrics[0].value).to.be(182); + expect(metrics[0].value).to.be('182'); expect(metrics[1].label).to.be('99th percentile of bytes'); - expect(metrics[1].value).to.be(445842.4634666484); + expect(metrics[1].value).to.be('445842.4634666484'); }); }); diff --git a/src/legacy/core_plugins/vis_type_metric/public/metric_vis_fn.ts b/src/legacy/core_plugins/vis_type_metric/public/metric_vis_fn.ts index 39bc96933c66e..b64361f17c470 100644 --- a/src/legacy/core_plugins/vis_type_metric/public/metric_vis_fn.ts +++ b/src/legacy/core_plugins/vis_type_metric/public/metric_vis_fn.ts @@ -99,6 +99,7 @@ export const createMetricVisFn = (): ExpressionFunction< colorRange: { types: ['range'], multi: true, + default: '{range from=0 to=10000}', help: i18n.translate('visTypeMetric.function.colorRange.help', { defaultMessage: 'A range object specifying groups of values to which different colors should be applied.', diff --git a/src/legacy/core_plugins/vis_type_timeseries/public/components/lib/tick_formatter.js b/src/legacy/core_plugins/vis_type_timeseries/public/components/lib/tick_formatter.js index 0459d11c74ef0..1192b678ae148 100644 --- a/src/legacy/core_plugins/vis_type_timeseries/public/components/lib/tick_formatter.js +++ b/src/legacy/core_plugins/vis_type_timeseries/public/components/lib/tick_formatter.js @@ -19,10 +19,14 @@ import handlebars from 'handlebars/dist/handlebars'; import { isNumber } from 'lodash'; -import { fieldFormats } from 'ui/registry/field_formats'; +import { npStart } from 'ui/new_platform'; import { inputFormats, outputFormats, isDuration } from '../lib/durations'; + + export const createTickFormatter = (format = '0,0.[00]', template, getConfig = null) => { + const fieldFormats = npStart.plugins.data.fieldFormats; + if (!template) template = '{{value}}'; const render = handlebars.compile(template, { knownHelpersOnly: true }); let formatter; diff --git a/src/legacy/core_plugins/vis_type_timeseries/public/components/vis_types/table/vis.js b/src/legacy/core_plugins/vis_type_timeseries/public/components/vis_types/table/vis.js index 8af175d116556..10fc34fccd2cc 100644 --- a/src/legacy/core_plugins/vis_type_timeseries/public/components/vis_types/table/vis.js +++ b/src/legacy/core_plugins/vis_type_timeseries/public/components/vis_types/table/vis.js @@ -20,18 +20,17 @@ import _, { isArray, last, get } from 'lodash'; import React, { Component } from 'react'; import PropTypes from 'prop-types'; -import { fieldFormats } from 'ui/registry/field_formats'; +import { npStart } from 'ui/new_platform'; import { createTickFormatter } from '../../lib/tick_formatter'; import { calculateLabel } from '../../../../common/calculate_label'; import { isSortable } from './is_sortable'; import { EuiToolTip, EuiIcon } from '@elastic/eui'; import { replaceVars } from '../../lib/replace_vars'; +import { FIELD_FORMAT_IDS } from '../../../../../../../plugins/data/public'; import { FormattedMessage } from '@kbn/i18n/react'; import { METRIC_TYPES } from '../../../../common/metric_types'; -const DateFormat = fieldFormats.getType('date'); - function getColor(rules, colorKey, value) { let color; if (rules) { @@ -49,6 +48,10 @@ function getColor(rules, colorKey, value) { export class TableVis extends Component { constructor(props) { super(props); + + const fieldFormats = npStart.plugins.data.fieldFormats; + const DateFormat = fieldFormats.getType(FIELD_FORMAT_IDS.DATE); + this.dateFormatter = new DateFormat({}, this.props.getConfig); } diff --git a/src/legacy/plugin_discovery/types.ts b/src/legacy/plugin_discovery/types.ts index 97d3a4352c2f8..d987260b099bd 100644 --- a/src/legacy/plugin_discovery/types.ts +++ b/src/legacy/plugin_discovery/types.ts @@ -62,6 +62,8 @@ export interface LegacyPluginOptions { }>; apps: any; hacks: string[]; + visualize: string[]; + devTools: string[]; styleSheetPaths: string; injectDefaultVars: (server: Server) => Record; noParse: string[]; diff --git a/src/legacy/server/kbn_server.d.ts b/src/legacy/server/kbn_server.d.ts index 9cc4e30d4252d..7399f2d08508f 100644 --- a/src/legacy/server/kbn_server.d.ts +++ b/src/legacy/server/kbn_server.d.ts @@ -107,6 +107,7 @@ export default class KbnServer { __internals: { hapiServer: LegacyServiceSetupDeps['core']['http']['server']; uiPlugins: LegacyServiceSetupDeps['core']['plugins']['uiPlugins']; + uiPluginConfigs: LegacyServiceSetupDeps['core']['plugins']['uiPluginConfigs']; elasticsearch: LegacyServiceSetupDeps['core']['elasticsearch']; uiSettings: LegacyServiceSetupDeps['core']['uiSettings']; kibanaMigrator: LegacyServiceStartDeps['core']['savedObjects']['migrator']; diff --git a/src/legacy/ui/field_formats/mixin/field_formats_mixin.ts b/src/legacy/ui/field_formats/mixin/field_formats_mixin.ts index 66466b96abe83..370c312706242 100644 --- a/src/legacy/ui/field_formats/mixin/field_formats_mixin.ts +++ b/src/legacy/ui/field_formats/mixin/field_formats_mixin.ts @@ -20,10 +20,10 @@ import { has } from 'lodash'; import { Legacy } from 'kibana'; import { FieldFormatsService } from './field_formats_service'; -import { FieldFormat } from '../../../../plugins/data/public'; +import { IFieldFormatType } from '../../../../plugins/data/public'; export function fieldFormatsMixin(kbnServer: any, server: Legacy.Server) { - const fieldFormatClasses: Array = []; + const fieldFormatClasses: IFieldFormatType[] = []; // for use outside of the request context, for special cases server.decorate('server', 'fieldFormatServiceFactory', async function(uiSettings) { diff --git a/src/legacy/ui/field_formats/mixin/field_formats_service.ts b/src/legacy/ui/field_formats/mixin/field_formats_service.ts index c0800fcd4162b..c5bc25333985b 100644 --- a/src/legacy/ui/field_formats/mixin/field_formats_service.ts +++ b/src/legacy/ui/field_formats/mixin/field_formats_service.ts @@ -18,7 +18,7 @@ */ import { indexBy, Dictionary } from 'lodash'; -import { FieldFormat } from '../../../../plugins/data/public'; +import { FieldFormat, IFieldFormatType } from '../../../../plugins/data/common'; interface FieldFormatConfig { id: string; @@ -27,9 +27,9 @@ interface FieldFormatConfig { export class FieldFormatsService { getConfig: any; - _fieldFormats: Dictionary; + _fieldFormats: Dictionary; - constructor(fieldFormatClasses: Array, getConfig: Function) { + constructor(fieldFormatClasses: IFieldFormatType[], getConfig: Function) { this._fieldFormats = indexBy(fieldFormatClasses, 'id'); this.getConfig = getConfig; } diff --git a/src/legacy/ui/public/agg_response/hierarchical/build_hierarchical_data.test.js b/src/legacy/ui/public/agg_response/hierarchical/build_hierarchical_data.test.js index ce7d87c228fbd..49d814c33209c 100644 --- a/src/legacy/ui/public/agg_response/hierarchical/build_hierarchical_data.test.js +++ b/src/legacy/ui/public/agg_response/hierarchical/build_hierarchical_data.test.js @@ -20,16 +20,7 @@ import { buildHierarchicalData } from './build_hierarchical_data'; import { legacyResponseHandlerProvider } from '../../vis/response_handlers/legacy'; -jest.mock('../../registry/field_formats', () => { - return { fieldFormats: { - getType: id => { - if(id === '1') { return jest.fn(); } - if(id === 'agg_1') { return jest.fn(); } - } - } - }; -} -); +jest.mock('ui/new_platform'); jest.mock('../../chrome', () => ({ getUiSettingsClient: jest.fn() diff --git a/src/legacy/ui/public/agg_types/agg_config.ts b/src/legacy/ui/public/agg_types/agg_config.ts index becfaf8c89e27..de1a6059774e7 100644 --- a/src/legacy/ui/public/agg_types/agg_config.ts +++ b/src/legacy/ui/public/agg_types/agg_config.ts @@ -26,16 +26,14 @@ import _ from 'lodash'; import { i18n } from '@kbn/i18n'; +import { npStart } from 'ui/new_platform'; import { AggType } from './agg_type'; import { FieldParamType } from './param_types/field'; import { AggGroupNames } from '../vis/editors/default/agg_groups'; import { writeParams } from './agg_params'; import { AggConfigs } from './agg_configs'; import { Schema } from '../vis/editors/default/schemas'; -import { ContentType } from '../../../../plugins/data/public'; - -// @ts-ignore -import { fieldFormats } from '../registry/field_formats'; +import { ContentType, KBN_FIELD_TYPES } from '../../../../plugins/data/public'; export interface AggConfigOptions { enabled: boolean; @@ -378,14 +376,16 @@ export class AggConfig { if (format) { return format.getConverterFor(contentType); } + return this.fieldOwnFormatter(contentType, defaultFormat); } fieldOwnFormatter(contentType?: ContentType, defaultFormat?: any) { + const fieldFormats = npStart.plugins.data.fieldFormats; const field = this.getField(); let format = field && field.format; if (!format) format = defaultFormat; - if (!format) format = fieldFormats.getDefaultInstance('string'); + if (!format) format = fieldFormats.getDefaultInstance(KBN_FIELD_TYPES.STRING); return format.getConverterFor(contentType); } diff --git a/src/legacy/ui/public/agg_types/agg_type.test.ts b/src/legacy/ui/public/agg_types/agg_type.test.ts index 1c1453b74fe98..9b34910e81e88 100644 --- a/src/legacy/ui/public/agg_types/agg_type.test.ts +++ b/src/legacy/ui/public/agg_types/agg_type.test.ts @@ -19,15 +19,10 @@ import { AggType, AggTypeConfig } from './agg_type'; import { AggConfig } from './agg_config'; +import { npStart } from 'ui/new_platform'; jest.mock('ui/new_platform'); -jest.mock('ui/registry/field_formats', () => ({ - fieldFormats: { - getDefaultInstance: jest.fn(() => 'default'), - }, -})); - describe('AggType Class', () => { describe('constructor', () => { it("requires a valid config object as it's first param", () => { @@ -158,6 +153,8 @@ describe('AggType Class', () => { }); it('returns default formatter', () => { + npStart.plugins.data.fieldFormats.getDefaultInstance = jest.fn(() => 'default') as any; + const aggType = new AggType({ name: 'name', title: 'title', diff --git a/src/legacy/ui/public/agg_types/agg_type.ts b/src/legacy/ui/public/agg_types/agg_type.ts index 7be8ec1406d3c..5216affb3e52d 100644 --- a/src/legacy/ui/public/agg_types/agg_type.ts +++ b/src/legacy/ui/public/agg_types/agg_type.ts @@ -19,6 +19,7 @@ import { constant, noop, identity } from 'lodash'; import { i18n } from '@kbn/i18n'; +import { npStart } from 'ui/new_platform'; import { AggParam, initParams } from './agg_params'; import { AggConfig } from '../vis'; @@ -27,8 +28,7 @@ import { SearchSource } from '../courier'; import { Adapters } from '../inspector'; import { BaseParamType } from './param_types/base'; -// @ts-ignore -import { FieldFormat, fieldFormats } from '../registry/field_formats'; +import { KBN_FIELD_TYPES, FieldFormat } from '../../../../plugins/data/public'; export interface AggTypeConfig< TAggConfig extends AggConfig = AggConfig, @@ -62,7 +62,9 @@ export interface AggTypeConfig< const getFormat = (agg: AggConfig) => { const field = agg.getField(); - return field ? field.format : fieldFormats.getDefaultInstance('string'); + const fieldFormats = npStart.plugins.data.fieldFormats; + + return field ? field.format : fieldFormats.getDefaultInstance(KBN_FIELD_TYPES.STRING); }; export class AggType { diff --git a/src/legacy/ui/public/agg_types/buckets/date_range.ts b/src/legacy/ui/public/agg_types/buckets/date_range.ts index 908d921d12313..860d76ff2aa7b 100644 --- a/src/legacy/ui/public/agg_types/buckets/date_range.ts +++ b/src/legacy/ui/public/agg_types/buckets/date_range.ts @@ -23,13 +23,15 @@ import { npStart } from 'ui/new_platform'; import { BUCKET_TYPES } from './bucket_agg_types'; import { BucketAggType, IBucketAggConfig } from './_bucket_agg_type'; import { createFilterDateRange } from './create_filter/date_range'; -import { FieldFormat, KBN_FIELD_TYPES } from '../../../../../plugins/data/public'; import { DateRangesParamEditor } from '../../vis/editors/default/controls/date_ranges'; -// @ts-ignore -import { fieldFormats } from '../../registry/field_formats'; // @ts-ignore import { dateRange } from '../../utils/date_range'; +import { + KBN_FIELD_TYPES, + TEXT_CONTEXT_TYPE, + FieldFormat, +} from '../../../../../plugins/data/public'; const dateRangeTitle = i18n.translate('common.ui.aggTypes.buckets.dateRangeTitle', { defaultMessage: 'Date Range', @@ -48,7 +50,12 @@ export const dateRangeBucketAgg = new BucketAggType({ return { from, to }; }, getFormat(agg) { - const formatter = agg.fieldOwnFormatter('text', fieldFormats.getDefaultInstance('date')); + const fieldFormats = npStart.plugins.data.fieldFormats; + + const formatter = agg.fieldOwnFormatter( + TEXT_CONTEXT_TYPE, + fieldFormats.getDefaultInstance(KBN_FIELD_TYPES.DATE) + ); const DateRangeFormat = FieldFormat.from(function(range: DateRangeKey) { return dateRange.toString(range, formatter); }); diff --git a/src/legacy/ui/public/agg_types/buckets/ip_range.ts b/src/legacy/ui/public/agg_types/buckets/ip_range.ts index 7ef415ff8d0c4..35155a482734c 100644 --- a/src/legacy/ui/public/agg_types/buckets/ip_range.ts +++ b/src/legacy/ui/public/agg_types/buckets/ip_range.ts @@ -19,17 +19,20 @@ import { noop, map, omit, isNull } from 'lodash'; import { i18n } from '@kbn/i18n'; +import { npStart } from 'ui/new_platform'; import { BucketAggType, IBucketAggConfig } from './_bucket_agg_type'; import { IpRangeTypeParamEditor } from '../../vis/editors/default/controls/ip_range_type'; import { IpRangesParamEditor } from '../../vis/editors/default/controls/ip_ranges'; -// @ts-ignore -import { fieldFormats } from '../../registry/field_formats'; -import { FieldFormat, KBN_FIELD_TYPES } from '../../../../../plugins/data/public'; import { ipRange } from '../../utils/ip_range'; import { BUCKET_TYPES } from './bucket_agg_types'; // @ts-ignore import { createFilterIpRange } from './create_filter/ip_range'; +import { + KBN_FIELD_TYPES, + TEXT_CONTEXT_TYPE, + FieldFormat, +} from '../../../../../plugins/data/public'; const ipRangeTitle = i18n.translate('common.ui.aggTypes.buckets.ipRangeTitle', { defaultMessage: 'IPv4 Range', @@ -50,7 +53,11 @@ export const ipRangeBucketAgg = new BucketAggType({ return { type: 'range', from: bucket.from, to: bucket.to }; }, getFormat(agg) { - const formatter = agg.fieldOwnFormatter('text', fieldFormats.getDefaultInstance('ip')); + const fieldFormats = npStart.plugins.data.fieldFormats; + const formatter = agg.fieldOwnFormatter( + TEXT_CONTEXT_TYPE, + fieldFormats.getDefaultInstance(KBN_FIELD_TYPES.IP) + ); const IpRangeFormat = FieldFormat.from(function(range: IpRangeKey) { return ipRange.toString(range, formatter); }); diff --git a/src/legacy/ui/public/agg_types/buckets/terms.ts b/src/legacy/ui/public/agg_types/buckets/terms.ts index c0f870c27f10d..89e33784fb5fb 100644 --- a/src/legacy/ui/public/agg_types/buckets/terms.ts +++ b/src/legacy/ui/public/agg_types/buckets/terms.ts @@ -41,7 +41,7 @@ import { OtherBucketParamEditor } from '../../vis/editors/default/controls/other import { AggConfigs } from '../agg_configs'; import { Adapters } from '../../../../../plugins/inspector/public'; -import { ContentType, KBN_FIELD_TYPES } from '../../../../../plugins/data/public'; +import { ContentType, FieldFormat, KBN_FIELD_TYPES } from '../../../../../plugins/data/public'; // @ts-ignore import { Schemas } from '../../vis/editors/default/schemas'; @@ -75,7 +75,7 @@ export const termsBucketAgg = new BucketAggType({ const params = agg.params; return agg.getFieldDisplayName() + ': ' + params.order.text; }, - getFormat(bucket) { + getFormat(bucket): FieldFormat { return { getConverterFor: (type: ContentType) => { return (val: any) => { @@ -91,10 +91,11 @@ export const termsBucketAgg = new BucketAggType({ basePath: chrome.getBasePath(), }; const converter = bucket.params.field.format.getConverterFor(type); + return converter(val, undefined, undefined, parsedUrl); }; }, - }; + } as FieldFormat; }, createFilter: createFilterTerms, postFlightRequest: async ( diff --git a/src/legacy/ui/public/agg_types/metrics/cardinality.ts b/src/legacy/ui/public/agg_types/metrics/cardinality.ts index 221e1c6d6b083..301ae2c80116c 100644 --- a/src/legacy/ui/public/agg_types/metrics/cardinality.ts +++ b/src/legacy/ui/public/agg_types/metrics/cardinality.ts @@ -18,10 +18,10 @@ */ import { i18n } from '@kbn/i18n'; +import { npStart } from 'ui/new_platform'; import { MetricAggType } from './metric_agg_type'; -// @ts-ignore -import { fieldFormats } from '../../registry/field_formats'; import { METRIC_TYPES } from './metric_agg_types'; +import { KBN_FIELD_TYPES } from '../../../../../plugins/data/public'; const uniqueCountTitle = i18n.translate('common.ui.aggTypes.metrics.uniqueCountTitle', { defaultMessage: 'Unique Count', @@ -37,7 +37,9 @@ export const cardinalityMetricAgg = new MetricAggType({ }); }, getFormat() { - return fieldFormats.getDefaultInstance('number'); + const fieldFormats = npStart.plugins.data.fieldFormats; + + return fieldFormats.getDefaultInstance(KBN_FIELD_TYPES.NUMBER); }, params: [ { diff --git a/src/legacy/ui/public/agg_types/metrics/count.ts b/src/legacy/ui/public/agg_types/metrics/count.ts index 12964c8873e97..b5b844e8658d6 100644 --- a/src/legacy/ui/public/agg_types/metrics/count.ts +++ b/src/legacy/ui/public/agg_types/metrics/count.ts @@ -18,12 +18,11 @@ */ import { i18n } from '@kbn/i18n'; +import { npStart } from 'ui/new_platform'; +import { KBN_FIELD_TYPES } from '../../../../../plugins/data/public'; import { MetricAggType } from './metric_agg_type'; import { METRIC_TYPES } from './metric_agg_types'; -// @ts-ignore -import { fieldFormats } from '../../registry/field_formats'; - export const countMetricAgg = new MetricAggType({ name: METRIC_TYPES.COUNT, title: i18n.translate('common.ui.aggTypes.metrics.countTitle', { @@ -36,7 +35,9 @@ export const countMetricAgg = new MetricAggType({ }); }, getFormat() { - return fieldFormats.getDefaultInstance('number'); + const fieldFormats = npStart.plugins.data.fieldFormats; + + return fieldFormats.getDefaultInstance(KBN_FIELD_TYPES.NUMBER); }, getValue(agg, bucket) { return bucket.doc_count; diff --git a/src/legacy/ui/public/agg_types/metrics/metric_agg_type.ts b/src/legacy/ui/public/agg_types/metrics/metric_agg_type.ts index 7428bd6caa22d..a466b9f852607 100644 --- a/src/legacy/ui/public/agg_types/metrics/metric_agg_type.ts +++ b/src/legacy/ui/public/agg_types/metrics/metric_agg_type.ts @@ -18,6 +18,7 @@ */ import { i18n } from '@kbn/i18n'; +import { npStart } from 'ui/new_platform'; import { AggType, AggTypeConfig } from '../agg_type'; import { AggParamType } from '../param_types/agg'; import { AggConfig } from '../agg_config'; @@ -72,8 +73,9 @@ export class MetricAggType< this.getFormat = config.getFormat || (agg => { + const registeredFormats = npStart.plugins.data.fieldFormats; const field = agg.getField(); - return field ? field.format : fieldFormats.getDefaultInstance('number'); + return field ? field.format : registeredFormats.getDefaultInstance(KBN_FIELD_TYPES.NUMBER); }); this.subtype = diff --git a/src/legacy/ui/public/agg_types/metrics/percentile_ranks.ts b/src/legacy/ui/public/agg_types/metrics/percentile_ranks.ts index 4fabe137f1bc8..ead5122278b5a 100644 --- a/src/legacy/ui/public/agg_types/metrics/percentile_ranks.ts +++ b/src/legacy/ui/public/agg_types/metrics/percentile_ranks.ts @@ -18,24 +18,27 @@ */ import { i18n } from '@kbn/i18n'; +import { npStart } from 'ui/new_platform'; import { PercentileRanksEditor } from '../../vis/editors/default/controls/percentile_ranks'; import { IMetricAggConfig, MetricAggType } from './metric_agg_type'; import { getResponseAggConfigClass, IResponseAggConfig } from './lib/get_response_agg_config_class'; import { getPercentileValue } from './percentiles_get_value'; import { METRIC_TYPES } from './metric_agg_types'; -// @ts-ignore -import { fieldFormats } from '../../registry/field_formats'; -import { KBN_FIELD_TYPES } from '../../../../../plugins/data/public'; +import { FIELD_FORMAT_IDS, KBN_FIELD_TYPES } from '../../../../../plugins/data/public'; // required by the values editor export type IPercentileRanksAggConfig = IResponseAggConfig; +const getFieldFormats = () => npStart.plugins.data.fieldFormats; + const valueProps = { makeLabel(this: IPercentileRanksAggConfig) { + const fieldFormats = getFieldFormats(); const field = this.getField(); - const format = (field && field.format) || fieldFormats.getDefaultInstance('number'); + const format = + (field && field.format) || fieldFormats.getDefaultInstance(KBN_FIELD_TYPES.NUMBER); const customLabel = this.getParam('customLabel'); const label = customLabel || this.getFieldDisplayName(); @@ -81,7 +84,11 @@ export const percentileRanksMetricAgg = new MetricAggType new ValueAggConfig(value)); }, getFormat() { - return fieldFormats.getInstance('percent') || fieldFormats.getDefaultInstance('number'); + const fieldFormats = getFieldFormats(); + return ( + fieldFormats.getInstance(FIELD_FORMAT_IDS.PERCENT) || + fieldFormats.getDefaultInstance(KBN_FIELD_TYPES.NUMBER) + ); }, getValue(agg, bucket) { return getPercentileValue(agg, bucket) / 100; diff --git a/src/legacy/ui/public/field_editor/field_editor.js b/src/legacy/ui/public/field_editor/field_editor.js index 896fb8fc5ddd8..f3c5990caae64 100644 --- a/src/legacy/ui/public/field_editor/field_editor.js +++ b/src/legacy/ui/public/field_editor/field_editor.js @@ -27,10 +27,6 @@ import { getSupportedScriptingLanguages, } from 'ui/scripting_languages'; -import { - fieldFormats -} from 'ui/registry/field_formats'; - import { getDocLink } from 'ui/documentation_links'; @@ -39,6 +35,8 @@ import { toastNotifications } from 'ui/notify'; +import { npStart } from 'ui/new_platform'; + import { EuiBasicTable, EuiButton, @@ -84,7 +82,10 @@ import { FormattedMessage } from '@kbn/i18n/react'; // This loads Ace editor's "groovy" mode, used below to highlight the script. import 'brace/mode/groovy'; +const getFieldFormats = () => npStart.plugins.data.fieldFormats; + export class FieldEditor extends PureComponent { + static propTypes = { indexPattern: PropTypes.object.isRequired, field: PropTypes.object.isRequired, @@ -141,9 +142,10 @@ export class FieldEditor extends PureComponent { const fieldTypes = get(FIELD_TYPES_BY_LANG, field.lang, DEFAULT_FIELD_TYPES); field.type = fieldTypes.includes(field.type) ? field.type : fieldTypes[0]; - const DefaultFieldFormat = fieldFormats.getDefaultType(field.type, field.esTypes); + const fieldFormats = getFieldFormats(); + const fieldTypeFormats = [ - getDefaultFormat(DefaultFieldFormat), + getDefaultFormat(fieldFormats.getDefaultType(field.type, field.esTypes)), ...fieldFormats.getByFieldType(field.type), ]; @@ -169,12 +171,14 @@ export class FieldEditor extends PureComponent { onTypeChange = (type) => { const { getConfig } = this.props.helpers; const { field } = this.state; + const fieldFormats = getFieldFormats(); const DefaultFieldFormat = fieldFormats.getDefaultType(type); + field.type = type; const fieldTypeFormats = [ getDefaultFormat(DefaultFieldFormat), - ...fieldFormats.getByFieldType(field.type), + ...getFieldFormats().getByFieldType(field.type), ]; const FieldFormat = fieldTypeFormats[0]; @@ -202,6 +206,7 @@ export class FieldEditor extends PureComponent { const { getConfig } = this.props.helpers; const { field, fieldTypeFormats } = this.state; const FieldFormat = fieldTypeFormats.find((format) => format.id === formatId) || fieldTypeFormats[0]; + field.format = new FieldFormat(params, getConfig); this.setState({ @@ -684,6 +689,7 @@ export class FieldEditor extends PureComponent { } saveField = async () => { + const fieldFormat = this.state.field.format; const field = this.state.field.toActualField(); const { indexPattern } = this.props; const { fieldFormatId } = this.state; @@ -721,7 +727,7 @@ export class FieldEditor extends PureComponent { if (!fieldFormatId) { indexPattern.fieldFormatMap[field.name] = undefined; } else { - indexPattern.fieldFormatMap[field.name] = field.format; + indexPattern.fieldFormatMap[field.name] = fieldFormat; } return indexPattern.save() diff --git a/src/legacy/ui/public/field_editor/field_editor.test.js b/src/legacy/ui/public/field_editor/field_editor.test.js index 34503238f437d..72eebee960b52 100644 --- a/src/legacy/ui/public/field_editor/field_editor.test.js +++ b/src/legacy/ui/public/field_editor/field_editor.test.js @@ -20,9 +20,12 @@ jest.mock('ui/kfetch', () => ({})); import React from 'react'; + +import { npStart } from 'ui/new_platform'; import { shallowWithI18nProvider } from 'test_utils/enzyme_helpers'; jest.mock('brace/mode/groovy', () => ({})); +jest.mock('ui/new_platform'); import { FieldEditor } from './field_editor'; @@ -46,6 +49,10 @@ jest.mock('@elastic/eui', () => ({ EuiSpacer: 'eui-spacer', EuiText: 'eui-text', EuiTextArea: 'eui-textArea', + htmlIdGenerator: () => 42, + palettes: { + euiPaletteColorBlind: { colors: ['red'] } + } })); jest.mock('ui/scripting_languages', () => ({ @@ -54,26 +61,6 @@ jest.mock('ui/scripting_languages', () => ({ getDeprecatedScriptingLanguages: () => ['testlang'], })); -jest.mock('ui/registry/field_formats', () => { - class Format { - static id = 'test_format'; static title = 'Test format'; - params() {} - } - - return { - fieldFormats: { - getDefaultType: () => { - return Format; - }, - getByFieldType: (fieldType) => { - if(fieldType === 'number') { - return [Format]; - } - } - }, - }; -}); - jest.mock('ui/documentation_links', () => ({ getDocLink: (doc) => `(docLink for ${doc})`, })); @@ -133,6 +120,13 @@ describe('FieldEditor', () => { indexPattern = { fields, }; + + npStart.plugins.data.fieldFormats.getDefaultType = jest.fn(() => Format); + npStart.plugins.data.fieldFormats.getByFieldType = jest.fn((fieldType) => { + if(fieldType === 'number') { + return [Format]; + } + }); }); it('should render create new scripted field correctly', async () => { diff --git a/src/legacy/ui/public/new_platform/new_platform.karma_mock.js b/src/legacy/ui/public/new_platform/new_platform.karma_mock.js index 5c269c7b019aa..8703e8750fda4 100644 --- a/src/legacy/ui/public/new_platform/new_platform.karma_mock.js +++ b/src/legacy/ui/public/new_platform/new_platform.karma_mock.js @@ -18,6 +18,7 @@ */ import sinon from 'sinon'; +import { getFieldFormatsRegistry } from '../../../../test_utils/public/stub_field_formats'; const mockObservable = () => { return { @@ -25,9 +26,24 @@ const mockObservable = () => { }; }; +export const mockUiSettings = { + get: (item) => { + return mockUiSettings[item]; + }, + getUpdate$: () => ({ + subscribe: sinon.fake(), + }), + 'query:allowLeadingWildcards': true, + 'query:queryString:options': {}, + 'courier:ignoreFilterIfFieldNotInIndex': true, + 'dateFormat:tz': 'Browser', + 'format:defaultTypeMap': {}, +}; + export const npSetup = { core: { - chrome: {} + chrome: {}, + uiSettings: mockUiSettings, }, plugins: { embeddable: { @@ -61,6 +77,7 @@ export const npSetup = { history: sinon.fake(), } }, + fieldFormats: getFieldFormatsRegistry(mockUiSettings), }, share: { register: () => {}, @@ -81,6 +98,9 @@ export const npSetup = { registerAction: sinon.fake(), registerTrigger: sinon.fake(), }, + feature_catalogue: { + register: sinon.fake(), + }, }, }; @@ -164,6 +184,7 @@ export const npStart = { history: sinon.fake(), }, }, + fieldFormats: getFieldFormatsRegistry(mockUiSettings), }, share: { toggleShareContextMenu: () => {}, @@ -185,6 +206,9 @@ export const npStart = { getTriggerActions: sinon.fake(), getTriggerCompatibleActions: sinon.fake(), }, + feature_catalogue: { + register: sinon.fake(), + }, }, }; diff --git a/src/legacy/ui/public/registry/field_formats.js b/src/legacy/ui/public/registry/field_formats.js deleted file mode 100644 index 9e03ef2e3cdd9..0000000000000 --- a/src/legacy/ui/public/registry/field_formats.js +++ /dev/null @@ -1,186 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import { memoize, forOwn, isFunction } from 'lodash'; -import { npStart } from 'ui/new_platform'; - -class FieldFormatRegistry { - constructor() { - this.fieldFormats = new Map(); - this._uiSettings = npStart.core.uiSettings; - this.getConfig = (...args) => this._uiSettings.get(...args); - this._defaultMap = []; - this.init(); - } - - init() { - this.parseDefaultTypeMap(this._uiSettings.get('format:defaultTypeMap')); - - this._uiSettings.getUpdate$().subscribe(({ key, newValue }) => { - if (key === 'format:defaultTypeMap') { - this.parseDefaultTypeMap(newValue); - } - }); - } - - /** - * Get the id of the default type for this field type - * using the format:defaultTypeMap config map - * - * @param {String} fieldType - the field type - * @param {String[]} esTypes - Array of ES data types - * @return {Object} - */ - getDefaultConfig = (fieldType, esTypes) => { - const type = this.getDefaultTypeName(fieldType, esTypes); - return this._defaultMap[type] || this._defaultMap._default_; - }; - - /** - * Get a FieldFormat type (class) by it's id. - * - * @param {String} formatId - the format id - * @return {Function} - */ - getType = (formatId) => { - return this.fieldFormats.get(formatId); - }; - /** - * Get the default FieldFormat type (class) for - * a field type, using the format:defaultTypeMap. - * used by the field editor - * - * @param {String} fieldType - * @param {String} esTypes - Array of ES data types - * @return {Function} - */ - getDefaultType = (fieldType, esTypes) => { - const config = this.getDefaultConfig(fieldType, esTypes); - return this.getType(config.id); - }; - - /** - * Get the name of the default type for ES types like date_nanos - * using the format:defaultTypeMap config map - * - * @param {String[]} esTypes - Array of ES data types - * @return {String|undefined} - */ - getTypeNameByEsTypes = (esTypes) => { - if(!Array.isArray(esTypes)) { - return; - } - return esTypes.find(type => this._defaultMap[type] && this._defaultMap[type].es); - }; - /** - * Get the default FieldFormat type name for - * a field type, using the format:defaultTypeMap. - * - * @param {String} fieldType - * @param {String[]} esTypes - * @return {string} - */ - getDefaultTypeName = (fieldType, esTypes) => { - return this.getTypeNameByEsTypes(esTypes) || fieldType; - }; - - /** - * Get the singleton instance of the FieldFormat type by it's id. - * - * @param {String} formatId - * @return {FieldFormat} - */ - getInstance = memoize(function (formatId) { - const FieldFormat = this.getType(formatId); - if (!FieldFormat) { - throw new Error(`Field Format '${formatId}' not found!`); - } - return new FieldFormat(null, this.getConfig); - }); - - /** - * Get the default fieldFormat instance for a field format. - * - * @param {String} fieldType - * @param {String[]} esTypes - * @return {FieldFormat} - */ - getDefaultInstancePlain(fieldType, esTypes) { - const conf = this.getDefaultConfig(fieldType, esTypes); - - const FieldFormat = this.getType(conf.id); - return new FieldFormat(conf.params, this.getConfig); - } - /** - * Returns a cache key built by the given variables for caching in memoized - * Where esType contains fieldType, fieldType is returned - * -> kibana types have a higher priority in that case - * -> would lead to failing tests that match e.g. date format with/without esTypes - * https://lodash.com/docs#memoize - * - * @param {String} fieldType - * @param {String[]} esTypes - * @return {string} - */ - getDefaultInstanceCacheResolver(fieldType, esTypes) { - return Array.isArray(esTypes) && esTypes.indexOf(fieldType) === -1 - ? [fieldType, ...esTypes].join('-') - : fieldType; - } - - /** - * Get filtered list of field formats by format type - * - * @param {String} fieldType - * @return {FieldFormat[]} - */ - - getByFieldType(fieldType) { - return [ ...this.fieldFormats.values()] - .filter(format => format.fieldType.indexOf(fieldType) !== -1); - } - - /** - * Get the default fieldFormat instance for a field format. - * It's a memoized function that builds and reads a cache - * - * @param {String} fieldType - * @param {String[]} esTypes - * @return {FieldFormat} - */ - getDefaultInstance = memoize(this.getDefaultInstancePlain, this.getDefaultInstanceCacheResolver); - - parseDefaultTypeMap(value) { - this._defaultMap = value; - forOwn(this, function (fn) { - if (isFunction(fn) && fn.cache) { - // clear all memoize caches - fn.cache = new memoize.Cache(); - } - }); - } - - register = derivedFieldFormat => { - this.fieldFormats.set(derivedFieldFormat.id, derivedFieldFormat); - - return this; - }; -} - -export const fieldFormats = new FieldFormatRegistry(); diff --git a/src/legacy/ui/public/saved_objects/__tests__/saved_object.js b/src/legacy/ui/public/saved_objects/__tests__/saved_object.js index ff53d48de758a..56124a047ba6d 100644 --- a/src/legacy/ui/public/saved_objects/__tests__/saved_object.js +++ b/src/legacy/ui/public/saved_objects/__tests__/saved_object.js @@ -26,6 +26,7 @@ import { SavedObjectProvider } from '../saved_object'; import StubIndexPattern from 'test_utils/stub_index_pattern'; import { SavedObjectsClientProvider } from '../saved_objects_client_provider'; import { InvalidJSONProperty } from '../../../../../plugins/kibana_utils/public'; +import { mockUiSettings } from '../../new_platform/new_platform.karma_mock'; const getConfig = cfg => cfg; @@ -337,7 +338,7 @@ describe('Saved Object', function () { type: 'dashboard', }); }); - const indexPattern = new StubIndexPattern('my-index', getConfig, null, []); + const indexPattern = new StubIndexPattern('my-index', getConfig, null, [], mockUiSettings); indexPattern.title = indexPattern.id; savedObject.searchSource.setField('index', indexPattern); return savedObject @@ -725,7 +726,7 @@ describe('Saved Object', function () { const savedObject = new SavedObject(config); sinon.stub(savedObject, 'hydrateIndexPattern').callsFake(() => { - const indexPattern = new StubIndexPattern(indexPatternId, getConfig, null, []); + const indexPattern = new StubIndexPattern(indexPatternId, getConfig, null, [], mockUiSettings); indexPattern.title = indexPattern.id; savedObject.searchSource.setField('index', indexPattern); return Promise.resolve(indexPattern); diff --git a/src/legacy/ui/public/time_buckets/time_buckets.js b/src/legacy/ui/public/time_buckets/time_buckets.js index bcd5cd161edd3..c875d7820373e 100644 --- a/src/legacy/ui/public/time_buckets/time_buckets.js +++ b/src/legacy/ui/public/time_buckets/time_buckets.js @@ -20,13 +20,14 @@ import _ from 'lodash'; import moment from 'moment'; import chrome from '../chrome'; +import { npStart } from 'ui/new_platform'; import { parseInterval } from '../utils/parse_interval'; import { calcAutoIntervalLessThan, calcAutoIntervalNear } from './calc_auto_interval'; import { convertDurationToNormalizedEsInterval, convertIntervalToEsInterval, } from './calc_es_interval'; -import { fieldFormats } from '../registry/field_formats'; +import { FIELD_FORMAT_IDS } from '../../../../plugins/data/public'; const config = chrome.getUiSettingsClient(); @@ -311,7 +312,9 @@ TimeBuckets.prototype.getScaledDateFormat = function () { }; TimeBuckets.prototype.getScaledDateFormatter = function () { - const DateFieldFormat = fieldFormats.getType('date'); + const fieldFormats = npStart.plugins.data.fieldFormats; + const DateFieldFormat = fieldFormats.getType(FIELD_FORMAT_IDS.DATE); + return new DateFieldFormat({ pattern: this.getScaledDateFormat() }, getConfig); diff --git a/src/legacy/ui/public/vis/__tests__/_agg_config.js b/src/legacy/ui/public/vis/__tests__/_agg_config.js index 2e2e0c31bdb8a..9b0398cf8853e 100644 --- a/src/legacy/ui/public/vis/__tests__/_agg_config.js +++ b/src/legacy/ui/public/vis/__tests__/_agg_config.js @@ -24,7 +24,6 @@ import { Vis } from '..'; import { AggType } from '../../agg_types/agg_type'; import { AggConfig } from '../../agg_types/agg_config'; import FixturesStubbedLogstashIndexPatternProvider from 'fixtures/stubbed_logstash_index_pattern'; -import { fieldFormats } from '../../registry/field_formats'; describe('AggConfig', function () { @@ -439,12 +438,15 @@ describe('AggConfig', function () { } ] }); - expect(vis.aggs.aggs[0].fieldFormatter()).to.be(fieldFormats.getDefaultInstance('number').getConverterFor()); + + const fieldFormatter = vis.aggs.aggs[0].fieldFormatter(); + + expect(fieldFormatter).to.be.defined; + expect(fieldFormatter('text')).to.be('text'); }); }); describe('#fieldFormatter - no custom getFormat handler', function () { - const visStateAggWithoutCustomGetFormat = { aggs: [ { @@ -467,13 +469,17 @@ describe('AggConfig', function () { it('returns the string format if the field does not have a format', function () { const agg = vis.aggs.aggs[0]; agg.params.field = { type: 'number', format: null }; - expect(agg.fieldFormatter()).to.be(fieldFormats.getDefaultInstance('string').getConverterFor()); + const fieldFormatter = agg.fieldFormatter(); + expect(fieldFormatter).to.be.defined; + expect(fieldFormatter('text')).to.be('text'); }); it('returns the string format if their is no field', function () { const agg = vis.aggs.aggs[0]; delete agg.params.field; - expect(agg.fieldFormatter()).to.be(fieldFormats.getDefaultInstance('string').getConverterFor()); + const fieldFormatter = agg.fieldFormatter(); + expect(fieldFormatter).to.be.defined; + expect(fieldFormatter('text')).to.be('text'); }); it('returns the html converter if "html" is passed in', function () { diff --git a/src/legacy/ui/public/visualize/loader/pipeline_helpers/utilities.ts b/src/legacy/ui/public/visualize/loader/pipeline_helpers/utilities.ts index 6598da76f60ba..f49e0f08e8732 100644 --- a/src/legacy/ui/public/visualize/loader/pipeline_helpers/utilities.ts +++ b/src/legacy/ui/public/visualize/loader/pipeline_helpers/utilities.ts @@ -20,14 +20,13 @@ import { i18n } from '@kbn/i18n'; import { identity } from 'lodash'; import { AggConfig, Vis } from 'ui/vis'; +import { npStart } from 'ui/new_platform'; import { SerializedFieldFormat } from 'src/plugins/expressions/public'; -import { FieldFormat } from '../../../../../../plugins/data/public'; +import { IFieldFormatId, FieldFormat } from '../../../../../../plugins/data/public'; import { tabifyGetColumns } from '../../../agg_response/tabify/_get_columns'; import chrome from '../../../chrome'; -// @ts-ignore -import { fieldFormats } from '../../../registry/field_formats'; import { dateRange } from '../../../utils/date_range'; import { ipRange } from '../../../utils/ip_range'; import { DateRangeKey } from '../../../agg_types/buckets/date_range'; @@ -45,18 +44,22 @@ function isTermsFieldFormat( return serializedFieldFormat.id === 'terms'; } -const config = chrome.getUiSettingsClient(); +const getConfig = (key: string, defaultOverride?: any): any => + npStart.core.uiSettings.get(key, defaultOverride); +const DefaultFieldFormat = FieldFormat.from(identity); -const getConfig = (...args: any[]): any => config.get(...args); -const getDefaultFieldFormat = () => ({ convert: identity }); +const getFieldFormat = (id?: IFieldFormatId, params: object = {}): FieldFormat => { + const fieldFormats = npStart.plugins.data.fieldFormats; -const getFieldFormat = (id: string | undefined, params: object = {}) => { - const Format = fieldFormats.getType(id); - if (Format) { - return new Format(params, getConfig); - } else { - return getDefaultFieldFormat(); + if (id) { + const Format = fieldFormats.getType(id); + + if (Format) { + return new Format(params, getConfig); + } } + + return new DefaultFieldFormat(); }; export const createFormat = (agg: AggConfig): SerializedFieldFormat => { @@ -93,9 +96,9 @@ export const createFormat = (agg: AggConfig): SerializedFieldFormat => { export type FormatFactory = (mapping?: SerializedFieldFormat) => FieldFormat; -export const getFormat: FormatFactory = (mapping = {}) => { +export const getFormat: FormatFactory = mapping => { if (!mapping) { - return getDefaultFieldFormat(); + return new DefaultFieldFormat(); } const { id } = mapping; if (id === 'range') { @@ -145,6 +148,7 @@ export const getFormat: FormatFactory = (mapping = {}) => { pathname: window.location.pathname, basePath: chrome.getBasePath(), }; + // @ts-ignore return format.convert(val, undefined, undefined, parsedUrl); }; }, @@ -161,9 +165,10 @@ export const getFormat: FormatFactory = (mapping = {}) => { pathname: window.location.pathname, basePath: chrome.getBasePath(), }; + // @ts-ignore return format.convert(val, type, undefined, parsedUrl); }, - }; + } as FieldFormat; } else { return getFieldFormat(id, mapping.params); } diff --git a/src/legacy/ui/ui_render/ui_render_mixin.js b/src/legacy/ui/ui_render/ui_render_mixin.js index 0d05ea259d1a1..c0885cd5d3d13 100644 --- a/src/legacy/ui/ui_render/ui_render_mixin.js +++ b/src/legacy/ui/ui_render/ui_render_mixin.js @@ -17,6 +17,7 @@ * under the License. */ +import { take } from 'rxjs/operators'; import { createHash } from 'crypto'; import { props, reduce as reduceAsync } from 'bluebird'; import Boom from 'boom'; @@ -42,21 +43,31 @@ export function uiRenderMixin(kbnServer, server, config) { let defaultInjectedVars = {}; kbnServer.afterPluginsInit(() => { const { defaultInjectedVarProviders = [] } = kbnServer.uiExports; - defaultInjectedVars = defaultInjectedVarProviders - .reduce((allDefaults, { fn, pluginSpec }) => ( + defaultInjectedVars = defaultInjectedVarProviders.reduce( + (allDefaults, { fn, pluginSpec }) => mergeVariables( allDefaults, fn(kbnServer.server, pluginSpec.readConfigValue(kbnServer.config, [])) - ) - ), {}); + ), + {} + ); }); // render all views from ./views server.setupViews(resolve(__dirname, 'views')); - server.exposeStaticDir('/node_modules/@elastic/eui/dist/{path*}', fromRoot('node_modules/@elastic/eui/dist')); - server.exposeStaticDir('/node_modules/@kbn/ui-framework/dist/{path*}', fromRoot('node_modules/@kbn/ui-framework/dist')); - server.exposeStaticDir('/node_modules/@elastic/charts/dist/{path*}', fromRoot('node_modules/@elastic/charts/dist')); + server.exposeStaticDir( + '/node_modules/@elastic/eui/dist/{path*}', + fromRoot('node_modules/@elastic/eui/dist') + ); + server.exposeStaticDir( + '/node_modules/@kbn/ui-framework/dist/{path*}', + fromRoot('node_modules/@kbn/ui-framework/dist') + ); + server.exposeStaticDir( + '/node_modules/@elastic/charts/dist/{path*}', + fromRoot('node_modules/@elastic/charts/dist') + ); const translationsCache = { translations: null, hash: null }; server.route({ @@ -80,11 +91,12 @@ export function uiRenderMixin(kbnServer, server, config) { .digest('hex'); } - return h.response(translationsCache.translations) + return h + .response(translationsCache.translations) .header('cache-control', 'must-revalidate') .header('content-type', 'application/json') .etag(translationsCache.hash); - } + }, }); // register the bootstrap.js route after plugins are initialized so that we can @@ -105,42 +117,38 @@ export function uiRenderMixin(kbnServer, server, config) { const isCore = !app; const uiSettings = request.getUiSettingsService(); - const darkMode = !authEnabled || request.auth.isAuthenticated - ? await uiSettings.get('theme:darkMode') - : false; + const darkMode = + !authEnabled || request.auth.isAuthenticated + ? await uiSettings.get('theme:darkMode') + : false; const basePath = config.get('server.basePath'); const regularBundlePath = `${basePath}/bundles`; const dllBundlePath = `${basePath}/built_assets/dlls`; const styleSheetPaths = [ `${dllBundlePath}/vendors.style.dll.css`, - ...( - darkMode ? - [ - `${basePath}/node_modules/@elastic/eui/dist/eui_theme_dark.css`, - `${basePath}/node_modules/@kbn/ui-framework/dist/kui_dark.css`, - `${basePath}/node_modules/@elastic/charts/dist/theme_only_dark.css`, - ] : [ - `${basePath}/node_modules/@elastic/eui/dist/eui_theme_light.css`, - `${basePath}/node_modules/@kbn/ui-framework/dist/kui_light.css`, - `${basePath}/node_modules/@elastic/charts/dist/theme_only_light.css`, - ] - ), + ...(darkMode + ? [ + `${basePath}/node_modules/@elastic/eui/dist/eui_theme_dark.css`, + `${basePath}/node_modules/@kbn/ui-framework/dist/kui_dark.css`, + `${basePath}/node_modules/@elastic/charts/dist/theme_only_dark.css`, + ] + : [ + `${basePath}/node_modules/@elastic/eui/dist/eui_theme_light.css`, + `${basePath}/node_modules/@kbn/ui-framework/dist/kui_light.css`, + `${basePath}/node_modules/@elastic/charts/dist/theme_only_light.css`, + ]), `${regularBundlePath}/${darkMode ? 'dark' : 'light'}_theme.style.css`, `${regularBundlePath}/commons.style.css`, - ...( - !isCore ? [`${regularBundlePath}/${app.getId()}.style.css`] : [] - ), + ...(!isCore ? [`${regularBundlePath}/${app.getId()}.style.css`] : []), ...kbnServer.uiExports.styleSheetPaths - .filter(path => ( - path.theme === '*' || path.theme === (darkMode ? 'dark' : 'light') - )) - .map(path => ( + .filter(path => path.theme === '*' || path.theme === (darkMode ? 'dark' : 'light')) + .map(path => path.localPath.endsWith('.scss') ? `${basePath}/built_assets/css/${path.publicPath}` : `${basePath}/${path.publicPath}` - )) - .reverse() + ) + .reverse(), ]; const bootstrap = new AppBootstrap({ @@ -149,17 +157,18 @@ export function uiRenderMixin(kbnServer, server, config) { regularBundlePath, dllBundlePath, styleSheetPaths, - } + }, }); const body = await bootstrap.getJsFile(); const etag = await bootstrap.getJsFileHash(); - return h.response(body) + return h + .response(body) .header('cache-control', 'must-revalidate') .header('content-type', 'application/javascript') .etag(etag); - } + }, }); }); @@ -179,14 +188,14 @@ export function uiRenderMixin(kbnServer, server, config) { } catch (err) { throw Boom.boomify(err); } - } + }, }); async function getUiSettings({ request, includeUserProvidedConfig }) { const uiSettings = request.getUiSettingsService(); return props({ defaults: uiSettings.getRegistered(), - user: includeUserProvidedConfig && uiSettings.getUserProvided() + user: includeUserProvidedConfig && uiSettings.getUserProvided(), }); } @@ -206,7 +215,12 @@ export function uiRenderMixin(kbnServer, server, config) { }; } - async function renderApp({ app, h, includeUserProvidedConfig = true, injectedVarsOverrides = {} }) { + async function renderApp({ + app, + h, + includeUserProvidedConfig = true, + injectedVarsOverrides = {}, + }) { const request = h.request; const basePath = request.getBasePath(); const uiSettings = await getUiSettings({ request, includeUserProvidedConfig }); @@ -215,14 +229,22 @@ export function uiRenderMixin(kbnServer, server, config) { const legacyMetadata = getLegacyKibanaPayload({ app, basePath, - uiSettings + uiSettings, }); // Get the list of new platform plugins. // Convert the Map into an array of objects so it is JSON serializable and order is preserved. - const uiPlugins = [ - ...kbnServer.newPlatform.__internals.uiPlugins.public.entries() - ].map(([id, plugin]) => ({ id, plugin })); + const uiPluginConfigs = kbnServer.newPlatform.__internals.uiPluginConfigs; + const uiPlugins = await Promise.all([ + ...kbnServer.newPlatform.__internals.uiPlugins.public.entries(), + ].map(async ([id, plugin]) => { + const config$ = uiPluginConfigs.get(id); + if (config$) { + return { id, plugin, config: await config$.pipe(take(1)).toPromise() }; + } else { + return { id, plugin, config: {} }; + } + })); const response = h.view('ui_app', { strictCsp: config.get('csp.strict'), @@ -250,8 +272,8 @@ export function uiRenderMixin(kbnServer, server, config) { mergeVariables( injectedVarsOverrides, app ? await server.getInjectedUiAppVars(app.getId()) : {}, - defaultInjectedVars, - ), + defaultInjectedVars + ) ), uiPlugins, diff --git a/src/legacy/core_plugins/data/public/filter/filter_bar/filter_editor/lib/fixtures/exists_filter.ts b/src/plugins/data/common/es_query/filters/stubs/exists_filter.ts similarity index 93% rename from src/legacy/core_plugins/data/public/filter/filter_bar/filter_editor/lib/fixtures/exists_filter.ts rename to src/plugins/data/common/es_query/filters/stubs/exists_filter.ts index 5af97818f9bfb..13b8189b6e22f 100644 --- a/src/legacy/core_plugins/data/public/filter/filter_bar/filter_editor/lib/fixtures/exists_filter.ts +++ b/src/plugins/data/common/es_query/filters/stubs/exists_filter.ts @@ -17,7 +17,7 @@ * under the License. */ -import { esFilters } from '../../../../../../../../../plugins/data/public'; +import { esFilters } from '../../..'; export const existsFilter: esFilters.ExistsFilter = { meta: { diff --git a/src/legacy/ui/public/registry/field_formats.d.ts b/src/plugins/data/common/es_query/filters/stubs/index.ts similarity index 85% rename from src/legacy/ui/public/registry/field_formats.d.ts rename to src/plugins/data/common/es_query/filters/stubs/index.ts index 79eec7a5a4e74..4f4c11f2e5ab7 100644 --- a/src/legacy/ui/public/registry/field_formats.d.ts +++ b/src/plugins/data/common/es_query/filters/stubs/index.ts @@ -17,4 +17,7 @@ * under the License. */ -export type FieldFormat = any; +export * from './exists_filter'; +export * from './phrase_filter'; +export * from './phrases_filter'; +export * from './range_filter'; diff --git a/src/legacy/core_plugins/data/public/filter/filter_bar/filter_editor/lib/fixtures/phrase_filter.ts b/src/plugins/data/common/es_query/filters/stubs/phrase_filter.ts similarity index 93% rename from src/legacy/core_plugins/data/public/filter/filter_bar/filter_editor/lib/fixtures/phrase_filter.ts rename to src/plugins/data/common/es_query/filters/stubs/phrase_filter.ts index b6c8b9905e6b3..7456e056a02b1 100644 --- a/src/legacy/core_plugins/data/public/filter/filter_bar/filter_editor/lib/fixtures/phrase_filter.ts +++ b/src/plugins/data/common/es_query/filters/stubs/phrase_filter.ts @@ -17,7 +17,7 @@ * under the License. */ -import { esFilters } from '../../../../../../../../../plugins/data/public'; +import { esFilters } from '../../..'; export const phraseFilter: esFilters.PhraseFilter = { meta: { diff --git a/src/legacy/core_plugins/data/public/filter/filter_bar/filter_editor/lib/fixtures/phrases_filter.ts b/src/plugins/data/common/es_query/filters/stubs/phrases_filter.ts similarity index 93% rename from src/legacy/core_plugins/data/public/filter/filter_bar/filter_editor/lib/fixtures/phrases_filter.ts rename to src/plugins/data/common/es_query/filters/stubs/phrases_filter.ts index 2e2ba4f798bdd..4bd70b85e186a 100644 --- a/src/legacy/core_plugins/data/public/filter/filter_bar/filter_editor/lib/fixtures/phrases_filter.ts +++ b/src/plugins/data/common/es_query/filters/stubs/phrases_filter.ts @@ -17,7 +17,7 @@ * under the License. */ -import { esFilters } from '../../../../../../../../../plugins/data/public'; +import { esFilters } from '../../..'; export const phrasesFilter: esFilters.PhrasesFilter = { meta: { diff --git a/src/legacy/core_plugins/data/public/filter/filter_bar/filter_editor/lib/fixtures/range_filter.ts b/src/plugins/data/common/es_query/filters/stubs/range_filter.ts similarity index 93% rename from src/legacy/core_plugins/data/public/filter/filter_bar/filter_editor/lib/fixtures/range_filter.ts rename to src/plugins/data/common/es_query/filters/stubs/range_filter.ts index c6438e30ecec6..5a6d245e2ef6f 100644 --- a/src/legacy/core_plugins/data/public/filter/filter_bar/filter_editor/lib/fixtures/range_filter.ts +++ b/src/plugins/data/common/es_query/filters/stubs/range_filter.ts @@ -17,7 +17,7 @@ * under the License. */ -import { esFilters } from '../../../../../../../../../plugins/data/public'; +import { esFilters } from '../../..'; export const rangeFilter: esFilters.RangeFilter = { meta: { diff --git a/src/plugins/data/common/field_formats/converters/boolean.test.ts b/src/plugins/data/common/field_formats/converters/boolean.test.ts index 2a548a6c1b179..3650df6517611 100644 --- a/src/plugins/data/common/field_formats/converters/boolean.test.ts +++ b/src/plugins/data/common/field_formats/converters/boolean.test.ts @@ -23,7 +23,7 @@ describe('Boolean Format', () => { let boolean: Record; beforeEach(() => { - boolean = new BoolFormat(); + boolean = new BoolFormat({}, jest.fn()); }); [ diff --git a/src/plugins/data/common/field_formats/converters/boolean.ts b/src/plugins/data/common/field_formats/converters/boolean.ts index 96e353592d676..6cc6c71465d50 100644 --- a/src/plugins/data/common/field_formats/converters/boolean.ts +++ b/src/plugins/data/common/field_formats/converters/boolean.ts @@ -19,11 +19,11 @@ import { KBN_FIELD_TYPES } from '../../kbn_field_types/types'; import { FieldFormat } from '../field_format'; -import { TextContextTypeConvert } from '../types'; +import { TextContextTypeConvert, FIELD_FORMAT_IDS } from '../types'; import { asPrettyString } from '../utils'; export class BoolFormat extends FieldFormat { - static id = 'boolean'; + static id = FIELD_FORMAT_IDS.BOOLEAN; static title = 'Boolean'; static fieldType = [KBN_FIELD_TYPES.BOOLEAN, KBN_FIELD_TYPES.NUMBER, KBN_FIELD_TYPES.STRING]; diff --git a/src/plugins/data/common/field_formats/converters/bytes.ts b/src/plugins/data/common/field_formats/converters/bytes.ts index 146f7afe74ccb..6c6df5eb7367d 100644 --- a/src/plugins/data/common/field_formats/converters/bytes.ts +++ b/src/plugins/data/common/field_formats/converters/bytes.ts @@ -18,9 +18,10 @@ */ import { NumeralFormat } from './numeral'; +import { FIELD_FORMAT_IDS } from '../types'; export class BytesFormat extends NumeralFormat { - static id = 'bytes'; + static id = FIELD_FORMAT_IDS.BYTES; static title = 'Bytes'; id = BytesFormat.id; diff --git a/src/plugins/data/common/field_formats/converters/color.test.ts b/src/plugins/data/common/field_formats/converters/color.test.ts index b7fcbf61227eb..f7aa26d449c7b 100644 --- a/src/plugins/data/common/field_formats/converters/color.test.ts +++ b/src/plugins/data/common/field_formats/converters/color.test.ts @@ -23,16 +23,19 @@ import { HTML_CONTEXT_TYPE } from '../content_types'; describe('Color Format', () => { describe('field is a number', () => { test('should add colors if the value is in range', () => { - const colorer = new ColorFormat({ - fieldType: 'number', - colors: [ - { - range: '100:150', - text: 'blue', - background: 'yellow', - }, - ], - }); + const colorer = new ColorFormat( + { + fieldType: 'number', + colors: [ + { + range: '100:150', + text: 'blue', + background: 'yellow', + }, + ], + }, + jest.fn() + ); expect(colorer.convert(99, HTML_CONTEXT_TYPE)).toBe('99'); expect(colorer.convert(100, HTML_CONTEXT_TYPE)).toBe( @@ -45,16 +48,19 @@ describe('Color Format', () => { }); test('should not convert invalid ranges', () => { - const colorer = new ColorFormat({ - fieldType: 'number', - colors: [ - { - range: '100150', - text: 'blue', - background: 'yellow', - }, - ], - }); + const colorer = new ColorFormat( + { + fieldType: 'number', + colors: [ + { + range: '100150', + text: 'blue', + background: 'yellow', + }, + ], + }, + jest.fn() + ); expect(colorer.convert(99, HTML_CONTEXT_TYPE)).toBe('99'); }); @@ -62,16 +68,19 @@ describe('Color Format', () => { describe('field is a string', () => { test('should add colors if the regex matches', () => { - const colorer = new ColorFormat({ - fieldType: 'string', - colors: [ - { - regex: 'A.*', - text: 'blue', - background: 'yellow', - }, - ], - }); + const colorer = new ColorFormat( + { + fieldType: 'string', + colors: [ + { + regex: 'A.*', + text: 'blue', + background: 'yellow', + }, + ], + }, + jest.fn() + ); const converter = colorer.getConverterFor(HTML_CONTEXT_TYPE) as Function; expect(converter('B', HTML_CONTEXT_TYPE)).toBe('B'); @@ -97,16 +106,19 @@ describe('Color Format', () => { }); test('returns original value (escaped) when regex is invalid', () => { - const colorer = new ColorFormat({ - fieldType: 'string', - colors: [ - { - regex: 'A.*', - text: 'blue', - background: 'yellow', - }, - ], - }); + const colorer = new ColorFormat( + { + fieldType: 'string', + colors: [ + { + regex: 'A.*', + text: 'blue', + background: 'yellow', + }, + ], + }, + jest.fn() + ); const converter = colorer.getConverterFor(HTML_CONTEXT_TYPE) as Function; expect(converter('<', HTML_CONTEXT_TYPE)).toBe('<'); diff --git a/src/plugins/data/common/field_formats/converters/color.ts b/src/plugins/data/common/field_formats/converters/color.ts index 6ba8bb97332e8..ffc72ba9a2c30 100644 --- a/src/plugins/data/common/field_formats/converters/color.ts +++ b/src/plugins/data/common/field_formats/converters/color.ts @@ -20,14 +20,14 @@ import { findLast, cloneDeep, template, escape } from 'lodash'; import { KBN_FIELD_TYPES } from '../../kbn_field_types/types'; import { FieldFormat } from '../field_format'; -import { HtmlContextTypeConvert } from '../types'; +import { HtmlContextTypeConvert, FIELD_FORMAT_IDS } from '../types'; import { asPrettyString } from '../utils'; import { DEFAULT_CONVERTER_COLOR } from '../constants'; const convertTemplate = template('<%- val %>'); export class ColorFormat extends FieldFormat { - static id = 'color'; + static id = FIELD_FORMAT_IDS.COLOR; static title = 'Color'; static fieldType = [KBN_FIELD_TYPES.NUMBER, KBN_FIELD_TYPES.STRING]; diff --git a/src/plugins/data/common/field_formats/converters/custom.ts b/src/plugins/data/common/field_formats/converters/custom.ts index 8ab31e5784566..687870306c873 100644 --- a/src/plugins/data/common/field_formats/converters/custom.ts +++ b/src/plugins/data/common/field_formats/converters/custom.ts @@ -18,13 +18,11 @@ */ import { FieldFormat } from '../field_format'; -import { TextContextTypeConvert } from '../types'; - -const ID = 'custom'; +import { TextContextTypeConvert, FIELD_FORMAT_IDS } from '../types'; export const createCustomFieldFormat = (convert: TextContextTypeConvert) => class CustomFieldFormat extends FieldFormat { - static id = ID; + static id = FIELD_FORMAT_IDS.CUSTOM; textConvert = convert; }; diff --git a/src/plugins/data/common/field_formats/converters/date.ts b/src/plugins/data/common/field_formats/converters/date.ts index 0017d5afb0608..06af64d9c17c2 100644 --- a/src/plugins/data/common/field_formats/converters/date.ts +++ b/src/plugins/data/common/field_formats/converters/date.ts @@ -19,28 +19,23 @@ import { memoize, noop } from 'lodash'; import moment from 'moment'; -import { FieldFormat, KBN_FIELD_TYPES, TextContextTypeConvert } from '../../index'; +import { KBN_FIELD_TYPES } from '../../kbn_field_types/types'; +import { FieldFormat } from '../field_format'; +import { TextContextTypeConvert, FIELD_FORMAT_IDS } from '../types'; export class DateFormat extends FieldFormat { - static id = 'date'; + static id = FIELD_FORMAT_IDS.DATE; static title = 'Date'; static fieldType = KBN_FIELD_TYPES.DATE; - private getConfig: Function; private memoizedConverter: Function = noop; private memoizedPattern: string = ''; private timeZone: string = ''; - constructor(params: Record, getConfig: Function) { - super(params); - - this.getConfig = getConfig; - } - getParamDefaults() { return { - pattern: this.getConfig('dateFormat'), - timezone: this.getConfig('dateFormat:tz'), + pattern: this.getConfig!('dateFormat'), + timezone: this.getConfig!('dateFormat:tz'), }; } diff --git a/src/plugins/data/common/field_formats/converters/date_nanos.ts b/src/plugins/data/common/field_formats/converters/date_nanos.ts index aef47f362bc97..8b0f8b111694e 100644 --- a/src/plugins/data/common/field_formats/converters/date_nanos.ts +++ b/src/plugins/data/common/field_formats/converters/date_nanos.ts @@ -21,7 +21,7 @@ import moment, { Moment } from 'moment'; import { memoize, noop } from 'lodash'; import { KBN_FIELD_TYPES } from '../../kbn_field_types/types'; import { FieldFormat } from '../field_format'; -import { TextContextTypeConvert } from '../types'; +import { TextContextTypeConvert, FIELD_FORMAT_IDS } from '../types'; /** * Analyse the given moment.js format pattern for the fractional sec part (S,SS,SSS...) @@ -69,26 +69,19 @@ export function formatWithNanos( } export class DateNanosFormat extends FieldFormat { - static id = 'date_nanos'; + static id = FIELD_FORMAT_IDS.DATE_NANOS; static title = 'Date Nanos'; static fieldType = KBN_FIELD_TYPES.DATE; - private getConfig: Function; private memoizedConverter: Function = noop; private memoizedPattern: string = ''; private timeZone: string = ''; - constructor(params: Record, getConfig: Function) { - super(params); - - this.getConfig = getConfig; - } - getParamDefaults() { return { - pattern: this.getConfig('dateNanosFormat'), - fallbackPattern: this.getConfig('dateFormat'), - timezone: this.getConfig('dateFormat:tz'), + pattern: this.getConfig!('dateNanosFormat'), + fallbackPattern: this.getConfig!('dateFormat'), + timezone: this.getConfig!('dateFormat:tz'), }; } diff --git a/src/plugins/data/common/field_formats/converters/date_server.ts b/src/plugins/data/common/field_formats/converters/date_server.ts index 7ed2745a256c4..0c214e424f163 100644 --- a/src/plugins/data/common/field_formats/converters/date_server.ts +++ b/src/plugins/data/common/field_formats/converters/date_server.ts @@ -21,22 +21,20 @@ import { memoize, noop } from 'lodash'; import moment from 'moment-timezone'; import { KBN_FIELD_TYPES } from '../../kbn_field_types/types'; import { FieldFormat } from '../field_format'; -import { TextContextTypeConvert } from '../types'; +import { TextContextTypeConvert, FIELD_FORMAT_IDS } from '../types'; export class DateFormat extends FieldFormat { - static id = 'date'; + static id = FIELD_FORMAT_IDS.DATE; static title = 'Date'; static fieldType = KBN_FIELD_TYPES.DATE; - private getConfig: Function; private memoizedConverter: Function = noop; private memoizedPattern: string = ''; private timeZone: string = ''; constructor(params: Record, getConfig: Function) { - super(params); + super(params, getConfig); - this.getConfig = getConfig; this.memoizedConverter = memoize((val: any) => { if (val == null) { return '-'; @@ -66,8 +64,8 @@ export class DateFormat extends FieldFormat { getParamDefaults() { return { - pattern: this.getConfig('dateFormat'), - timezone: this.getConfig('dateFormat:tz'), + pattern: this.getConfig!('dateFormat'), + timezone: this.getConfig!('dateFormat:tz'), }; } diff --git a/src/plugins/data/common/field_formats/converters/duration.test.ts b/src/plugins/data/common/field_formats/converters/duration.test.ts index b892884475eec..d6205d54bd702 100644 --- a/src/plugins/data/common/field_formats/converters/duration.test.ts +++ b/src/plugins/data/common/field_formats/converters/duration.test.ts @@ -142,7 +142,10 @@ describe('Duration Format', () => { test(`should format ${input} ${inputFormat} through ${outputFormat}${ outputPrecision ? `, ${outputPrecision} decimals` : '' }`, () => { - const duration = new DurationFormat({ inputFormat, outputFormat, outputPrecision }); + const duration = new DurationFormat( + { inputFormat, outputFormat, outputPrecision }, + jest.fn() + ); expect(duration.convert(input)).toBe(output); }); }); diff --git a/src/plugins/data/common/field_formats/converters/duration.ts b/src/plugins/data/common/field_formats/converters/duration.ts index 5eed523214ab3..d02de1a2fd889 100644 --- a/src/plugins/data/common/field_formats/converters/duration.ts +++ b/src/plugins/data/common/field_formats/converters/duration.ts @@ -21,7 +21,7 @@ import { i18n } from '@kbn/i18n'; import moment, { unitOfTime, Duration } from 'moment'; import { KBN_FIELD_TYPES } from '../../kbn_field_types/types'; import { FieldFormat } from '../field_format'; -import { TextContextTypeConvert } from '../types'; +import { TextContextTypeConvert, FIELD_FORMAT_IDS } from '../types'; const ratioToSeconds: Record = { picoseconds: 0.000000000001, @@ -166,7 +166,7 @@ function parseInputAsDuration(val: number, inputFormat: string) { } export class DurationFormat extends FieldFormat { - static id = 'duration'; + static id = FIELD_FORMAT_IDS.DURATION; static title = 'Duration'; static fieldType = KBN_FIELD_TYPES.NUMBER; static inputFormats = inputFormats; diff --git a/src/plugins/data/common/field_formats/converters/ip.test.ts b/src/plugins/data/common/field_formats/converters/ip.test.ts index cc42d41adc4a1..a9a02d1a43ea8 100644 --- a/src/plugins/data/common/field_formats/converters/ip.test.ts +++ b/src/plugins/data/common/field_formats/converters/ip.test.ts @@ -23,7 +23,7 @@ describe('IP Address Format', () => { let ip: Record; beforeEach(() => { - ip = new IpFormat(); + ip = new IpFormat({}, jest.fn()); }); test('converts a value from a decimal to a string', () => { diff --git a/src/plugins/data/common/field_formats/converters/ip.ts b/src/plugins/data/common/field_formats/converters/ip.ts index 669f7d1b605d7..3e011e8d7dde8 100644 --- a/src/plugins/data/common/field_formats/converters/ip.ts +++ b/src/plugins/data/common/field_formats/converters/ip.ts @@ -19,10 +19,10 @@ import { KBN_FIELD_TYPES } from '../../kbn_field_types/types'; import { FieldFormat } from '../field_format'; -import { TextContextTypeConvert } from '../types'; +import { TextContextTypeConvert, FIELD_FORMAT_IDS } from '../types'; export class IpFormat extends FieldFormat { - static id = 'ip'; + static id = FIELD_FORMAT_IDS.IP; static title = 'IP Address'; static fieldType = KBN_FIELD_TYPES.IP; diff --git a/src/plugins/data/common/field_formats/converters/number.ts b/src/plugins/data/common/field_formats/converters/number.ts index e0c22f5350716..6969c1551e1cc 100644 --- a/src/plugins/data/common/field_formats/converters/number.ts +++ b/src/plugins/data/common/field_formats/converters/number.ts @@ -18,9 +18,10 @@ */ import { NumeralFormat } from './numeral'; +import { FIELD_FORMAT_IDS } from '../types'; export class NumberFormat extends NumeralFormat { - static id = 'number'; + static id = FIELD_FORMAT_IDS.NUMBER; static title = 'Number'; id = NumberFormat.id; diff --git a/src/plugins/data/common/field_formats/converters/numeral.ts b/src/plugins/data/common/field_formats/converters/numeral.ts index f7bf7ddfd1701..d8e46a480294f 100644 --- a/src/plugins/data/common/field_formats/converters/numeral.ts +++ b/src/plugins/data/common/field_formats/converters/numeral.ts @@ -37,15 +37,8 @@ export abstract class NumeralFormat extends FieldFormat { abstract id: string; abstract title: string; - protected getConfig: Function; - - constructor(params: Record, getConfig: Function) { - super(params); - this.getConfig = getConfig; - } - getParamDefaults = () => ({ - pattern: this.getConfig(`format:${this.id}:defaultPattern`), + pattern: this.getConfig!(`format:${this.id}:defaultPattern`), }); protected getConvertedValue(val: any): string { diff --git a/src/plugins/data/common/field_formats/converters/percent.ts b/src/plugins/data/common/field_formats/converters/percent.ts index f810f12377362..2ae32c7c77f07 100644 --- a/src/plugins/data/common/field_formats/converters/percent.ts +++ b/src/plugins/data/common/field_formats/converters/percent.ts @@ -18,17 +18,17 @@ */ import { NumeralFormat } from './numeral'; -import { TextContextTypeConvert } from '../types'; +import { TextContextTypeConvert, FIELD_FORMAT_IDS } from '../types'; export class PercentFormat extends NumeralFormat { - static id = 'percent'; + static id = FIELD_FORMAT_IDS.PERCENT; static title = 'Percentage'; id = PercentFormat.id; title = PercentFormat.title; getParamDefaults = () => ({ - pattern: this.getConfig('format:percent:defaultPattern'), + pattern: this.getConfig!('format:percent:defaultPattern'), fractional: true, }); diff --git a/src/plugins/data/common/field_formats/converters/relative_date.test.ts b/src/plugins/data/common/field_formats/converters/relative_date.test.ts index bde5aec0a5ab5..6311402a34b46 100644 --- a/src/plugins/data/common/field_formats/converters/relative_date.test.ts +++ b/src/plugins/data/common/field_formats/converters/relative_date.test.ts @@ -24,7 +24,7 @@ describe('Relative Date Format', () => { let convert: Function; beforeEach(() => { - const relativeDate = new RelativeDateFormat({}); + const relativeDate = new RelativeDateFormat({}, jest.fn()); convert = relativeDate.convert.bind(relativeDate); }); diff --git a/src/plugins/data/common/field_formats/converters/relative_date.ts b/src/plugins/data/common/field_formats/converters/relative_date.ts index caab8c3a2d7da..273b2cef28a03 100644 --- a/src/plugins/data/common/field_formats/converters/relative_date.ts +++ b/src/plugins/data/common/field_formats/converters/relative_date.ts @@ -20,17 +20,13 @@ import moment from 'moment'; import { KBN_FIELD_TYPES } from '../../kbn_field_types/types'; import { FieldFormat } from '../field_format'; -import { TextContextTypeConvert } from '../types'; +import { TextContextTypeConvert, FIELD_FORMAT_IDS } from '../types'; export class RelativeDateFormat extends FieldFormat { - static id = 'relative_date'; + static id = FIELD_FORMAT_IDS.RELATIVE_DATE; static title = 'Relative Date'; static fieldType = KBN_FIELD_TYPES.DATE; - constructor(params: Record) { - super(params); - } - textConvert: TextContextTypeConvert = val => { if (val === null || val === undefined) { return '-'; diff --git a/src/plugins/data/common/field_formats/converters/source.ts b/src/plugins/data/common/field_formats/converters/source.ts index 35eb14ca59ebb..54977c7e66976 100644 --- a/src/plugins/data/common/field_formats/converters/source.ts +++ b/src/plugins/data/common/field_formats/converters/source.ts @@ -24,7 +24,7 @@ import { noWhiteSpace } from '../../../../../legacy/core_plugins/kibana/common/u import { shortenDottedString } from '../../../../../legacy/core_plugins/kibana/common/utils/shorten_dotted_string'; import { KBN_FIELD_TYPES } from '../../kbn_field_types/types'; import { FieldFormat } from '../field_format'; -import { TextContextTypeConvert, HtmlContextTypeConvert } from '../types'; +import { TextContextTypeConvert, HtmlContextTypeConvert, FIELD_FORMAT_IDS } from '../types'; const templateHtml = `
@@ -37,18 +37,10 @@ const templateHtml = ` const doTemplate = template(noWhiteSpace(templateHtml)); export class SourceFormat extends FieldFormat { - static id = '_source'; + static id = FIELD_FORMAT_IDS._SOURCE; static title = '_source'; static fieldType = KBN_FIELD_TYPES._SOURCE; - private getConfig: Function; - - constructor(params: Record, getConfig: Function) { - super(params); - - this.getConfig = getConfig; - } - textConvert: TextContextTypeConvert = value => JSON.stringify(value); htmlConvert: HtmlContextTypeConvert = (value, field, hit) => { @@ -62,7 +54,7 @@ export class SourceFormat extends FieldFormat { const formatted = field.indexPattern.formatHit(hit); const highlightPairs: any[] = []; const sourcePairs: any[] = []; - const isShortDots = this.getConfig('shortDots:enable'); + const isShortDots = this.getConfig!('shortDots:enable'); keys(formatted).forEach(key => { const pairs = highlights[key] ? highlightPairs : sourcePairs; diff --git a/src/plugins/data/common/field_formats/converters/static_lookup.ts b/src/plugins/data/common/field_formats/converters/static_lookup.ts index 29c64fd4f4046..419e7c786640b 100644 --- a/src/plugins/data/common/field_formats/converters/static_lookup.ts +++ b/src/plugins/data/common/field_formats/converters/static_lookup.ts @@ -19,7 +19,7 @@ import { KBN_FIELD_TYPES } from '../../kbn_field_types/types'; import { FieldFormat } from '../field_format'; -import { TextContextTypeConvert } from '../types'; +import { TextContextTypeConvert, FIELD_FORMAT_IDS } from '../types'; function convertLookupEntriesToMap(lookupEntries: any[]) { return lookupEntries.reduce( @@ -32,7 +32,7 @@ function convertLookupEntriesToMap(lookupEntries: any[]) { } export class StaticLookupFormat extends FieldFormat { - static id = 'static_lookup'; + static id = FIELD_FORMAT_IDS.STATIC_LOOKUP; static title = 'Static Lookup'; static fieldType = [ KBN_FIELD_TYPES.STRING, diff --git a/src/plugins/data/common/field_formats/converters/string.test.ts b/src/plugins/data/common/field_formats/converters/string.test.ts index bb0fd5cc011b6..b2d96ed5c0308 100644 --- a/src/plugins/data/common/field_formats/converters/string.test.ts +++ b/src/plugins/data/common/field_formats/converters/string.test.ts @@ -21,30 +21,42 @@ import { StringFormat } from './string'; describe('String Format', () => { test('convert a string to lower case', () => { - const string = new StringFormat({ - transform: 'lower', - }); + const string = new StringFormat( + { + transform: 'lower', + }, + jest.fn() + ); expect(string.convert('Kibana')).toBe('kibana'); }); test('convert a string to upper case', () => { - const string = new StringFormat({ - transform: 'upper', - }); + const string = new StringFormat( + { + transform: 'upper', + }, + jest.fn() + ); expect(string.convert('Kibana')).toBe('KIBANA'); }); test('decode a base64 string', () => { - const string = new StringFormat({ - transform: 'base64', - }); + const string = new StringFormat( + { + transform: 'base64', + }, + jest.fn() + ); expect(string.convert('Zm9vYmFy')).toBe('foobar'); }); test('convert a string to title case', () => { - const string = new StringFormat({ - transform: 'title', - }); + const string = new StringFormat( + { + transform: 'title', + }, + jest.fn() + ); expect(string.convert('PLEASE DO NOT SHOUT')).toBe('Please Do Not Shout'); expect(string.convert('Mean, variance and standard_deviation.')).toBe( 'Mean, Variance And Standard_deviation.' @@ -53,24 +65,33 @@ describe('String Format', () => { }); test('convert a string to short case', () => { - const string = new StringFormat({ - transform: 'short', - }); + const string = new StringFormat( + { + transform: 'short', + }, + jest.fn() + ); expect(string.convert('dot.notated.string')).toBe('d.n.string'); }); test('convert a string to unknown transform case', () => { - const string = new StringFormat({ - transform: 'unknown_transform', - }); + const string = new StringFormat( + { + transform: 'unknown_transform', + }, + jest.fn() + ); const value = 'test test test'; expect(string.convert(value)).toBe(value); }); test('decode a URL Param string', () => { - const string = new StringFormat({ - transform: 'urlparam', - }); + const string = new StringFormat( + { + transform: 'urlparam', + }, + jest.fn() + ); expect(string.convert('%EC%95%88%EB%85%95%20%ED%82%A4%EB%B0%94%EB%82%98')).toBe('안녕 키바나'); }); }); diff --git a/src/plugins/data/common/field_formats/converters/string.ts b/src/plugins/data/common/field_formats/converters/string.ts index 82547c0b0dee5..0edd219ca60f9 100644 --- a/src/plugins/data/common/field_formats/converters/string.ts +++ b/src/plugins/data/common/field_formats/converters/string.ts @@ -21,7 +21,7 @@ import { i18n } from '@kbn/i18n'; import { asPrettyString } from '../index'; import { KBN_FIELD_TYPES } from '../../kbn_field_types/types'; import { FieldFormat } from '../field_format'; -import { TextContextTypeConvert } from '../types'; +import { TextContextTypeConvert, FIELD_FORMAT_IDS } from '../types'; // @ts-ignore import { shortenDottedString } from '../../../../../legacy/core_plugins/kibana/common/utils/shorten_dotted_string'; @@ -72,7 +72,7 @@ const TRANSFORM_OPTIONS = [ const DEFAULT_TRANSFORM_OPTION = false; export class StringFormat extends FieldFormat { - static id = 'string'; + static id = FIELD_FORMAT_IDS.STRING; static title = 'String'; static fieldType = [ KBN_FIELD_TYPES.NUMBER, diff --git a/src/plugins/data/common/field_formats/converters/truncate.test.ts b/src/plugins/data/common/field_formats/converters/truncate.test.ts index 7de4bdb3dedfe..472d9673346d7 100644 --- a/src/plugins/data/common/field_formats/converters/truncate.test.ts +++ b/src/plugins/data/common/field_formats/converters/truncate.test.ts @@ -21,25 +21,25 @@ import { TruncateFormat } from './truncate'; describe('String TruncateFormat', () => { test('truncate large string', () => { - const truncate = new TruncateFormat({ fieldLength: 4 }); + const truncate = new TruncateFormat({ fieldLength: 4 }, jest.fn()); expect(truncate.convert('This is some text')).toBe('This...'); }); test('does not truncate large string when field length is not a string', () => { - const truncate = new TruncateFormat({ fieldLength: 'not number' }); + const truncate = new TruncateFormat({ fieldLength: 'not number' }, jest.fn()); expect(truncate.convert('This is some text')).toBe('This is some text'); }); test('does not truncate large string when field length is null', () => { - const truncate = new TruncateFormat({ fieldLength: null }); + const truncate = new TruncateFormat({ fieldLength: null }, jest.fn()); expect(truncate.convert('This is some text')).toBe('This is some text'); }); test('does not truncate large string when field length larger than the text', () => { - const truncate = new TruncateFormat({ fieldLength: 100000 }); + const truncate = new TruncateFormat({ fieldLength: 100000 }, jest.fn()); expect(truncate.convert('This is some text')).toBe('This is some text'); }); diff --git a/src/plugins/data/common/field_formats/converters/truncate.ts b/src/plugins/data/common/field_formats/converters/truncate.ts index acccf2a20c69a..dc25d71ec95d7 100644 --- a/src/plugins/data/common/field_formats/converters/truncate.ts +++ b/src/plugins/data/common/field_formats/converters/truncate.ts @@ -20,12 +20,12 @@ import { trunc } from 'lodash'; import { KBN_FIELD_TYPES } from '../../kbn_field_types/types'; import { FieldFormat } from '../field_format'; -import { TextContextTypeConvert } from '../types'; +import { TextContextTypeConvert, FIELD_FORMAT_IDS } from '../types'; const omission = '...'; export class TruncateFormat extends FieldFormat { - static id = 'truncate'; + static id = FIELD_FORMAT_IDS.TRUNCATE; static title = 'Truncated String'; static fieldType = KBN_FIELD_TYPES.STRING; diff --git a/src/plugins/data/common/field_formats/converters/url.ts b/src/plugins/data/common/field_formats/converters/url.ts index 6c00f11a408dc..bd68dedf38a67 100644 --- a/src/plugins/data/common/field_formats/converters/url.ts +++ b/src/plugins/data/common/field_formats/converters/url.ts @@ -22,7 +22,7 @@ import { escape, memoize } from 'lodash'; import { getHighlightHtml } from '../utils'; import { KBN_FIELD_TYPES } from '../../kbn_field_types/types'; import { FieldFormat } from '../field_format'; -import { TextContextTypeConvert, HtmlContextTypeConvert } from '../types'; +import { TextContextTypeConvert, HtmlContextTypeConvert, FIELD_FORMAT_IDS } from '../types'; const templateMatchRE = /{{([\s\S]+?)}}/g; const whitelistUrlSchemes = ['http://', 'https://']; @@ -50,7 +50,7 @@ const URL_TYPES = [ const DEFAULT_URL_TYPE = 'a'; export class UrlFormat extends FieldFormat { - static id = 'url'; + static id = FIELD_FORMAT_IDS.URL; static title = 'Url'; static fieldType = [ KBN_FIELD_TYPES.NUMBER, diff --git a/src/plugins/data/common/field_formats/field_format.test.ts b/src/plugins/data/common/field_formats/field_format.test.ts index d4789f12bdee9..2229601994496 100644 --- a/src/plugins/data/common/field_formats/field_format.test.ts +++ b/src/plugins/data/common/field_formats/field_format.test.ts @@ -32,7 +32,7 @@ const getTestFormat = ( textConvert = textConvert; htmlConvert = htmlConvert; - })(_params); + })(_params, jest.fn()); describe('FieldFormat class', () => { describe('params', () => { diff --git a/src/plugins/data/common/field_formats/field_format.ts b/src/plugins/data/common/field_formats/field_format.ts index e99894ca56167..6b5f665c6e20e 100644 --- a/src/plugins/data/common/field_formats/field_format.ts +++ b/src/plugins/data/common/field_formats/field_format.ts @@ -19,7 +19,12 @@ import { transform, size, cloneDeep, get, defaults } from 'lodash'; import { createCustomFieldFormat } from './converters/custom'; -import { ContentType, FieldFormatConvert, FieldFormatConvertFunction } from './types'; +import { + ContentType, + FIELD_FORMAT_IDS, + FieldFormatConvert, + FieldFormatConvertFunction, +} from './types'; import { htmlContentTypeSetup, textContentTypeSetup, @@ -68,7 +73,16 @@ export abstract class FieldFormat { */ public type: any = this.constructor; - constructor(public _params: any = {}) {} + private readonly _params: any; + protected getConfig: Function | undefined; + + constructor(_params: any = {}, getConfig?: Function) { + this._params = _params; + + if (getConfig) { + this.getConfig = getConfig; + } + } /** * Convert a raw value to a formatted string @@ -170,7 +184,7 @@ export abstract class FieldFormat { }; } - static from(convertFn: FieldFormatConvertFunction): ReturnType { + static from(convertFn: FieldFormatConvertFunction): IFieldFormatType { return createCustomFieldFormat(convertFn); } @@ -183,3 +197,11 @@ export abstract class FieldFormat { } export type IFieldFormat = PublicMethodsOf; +/** + * @string id type is needed for creating custom converters. + */ +export type IFieldFormatId = FIELD_FORMAT_IDS | string; +export type IFieldFormatType = (new (params?: any, getConfig?: Function) => FieldFormat) & { + id: IFieldFormatId; + fieldType: string | string[]; +}; diff --git a/src/plugins/data/common/field_formats/index.ts b/src/plugins/data/common/field_formats/index.ts index 5d04a69e4dc50..b751b097b5ed2 100644 --- a/src/plugins/data/common/field_formats/index.ts +++ b/src/plugins/data/common/field_formats/index.ts @@ -18,7 +18,7 @@ */ export { HTML_CONTEXT_TYPE, TEXT_CONTEXT_TYPE } from './content_types'; -export { FieldFormat } from './field_format'; +export { FieldFormat, IFieldFormatType, IFieldFormatId } from './field_format'; export { getHighlightRequest, asPrettyString, getHighlightHtml } from './utils'; export * from './converters'; export * from './constants'; diff --git a/src/plugins/data/common/field_formats/types.ts b/src/plugins/data/common/field_formats/types.ts index 626bab297392b..fc8e6e20a1a96 100644 --- a/src/plugins/data/common/field_formats/types.ts +++ b/src/plugins/data/common/field_formats/types.ts @@ -42,3 +42,23 @@ export interface FieldFormatConvert { text: TextContextTypeConvert; html: HtmlContextTypeConvert; } + +/** @public **/ +export enum FIELD_FORMAT_IDS { + _SOURCE = '_source', + BOOLEAN = 'boolean', + BYTES = 'bytes', + COLOR = 'color', + CUSTOM = 'custom', + DATE = 'date', + DATE_NANOS = 'date_nanos', + DURATION = 'duration', + IP = 'ip', + NUMBER = 'number', + PERCENT = 'percent', + RELATIVE_DATE = 'relative_date', + STATIC_LOOKUP = 'static_lookup', + STRING = 'string', + TRUNCATE = 'truncate', + URL = 'url', +} diff --git a/src/plugins/data/common/kbn_field_types/types.ts b/src/plugins/data/common/kbn_field_types/types.ts index 21d58bcd0f78c..11c62e8f86dce 100644 --- a/src/plugins/data/common/kbn_field_types/types.ts +++ b/src/plugins/data/common/kbn_field_types/types.ts @@ -27,9 +27,10 @@ export interface KbnFieldTypeOptions { /** @public **/ export enum ES_FIELD_TYPES { - _TYPE = '_type', _ID = '_id', + _INDEX = '_index', _SOURCE = '_source', + _TYPE = '_type', STRING = 'string', TEXT = 'text', diff --git a/src/plugins/data/public/field_formats_provider/field_formats.ts b/src/plugins/data/public/field_formats_provider/field_formats.ts new file mode 100644 index 0000000000000..f46994c209ded --- /dev/null +++ b/src/plugins/data/public/field_formats_provider/field_formats.ts @@ -0,0 +1,226 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { forOwn, isFunction, memoize } from 'lodash'; +import { UiSettingsClientContract } from 'kibana/public'; +import { + ES_FIELD_TYPES, + KBN_FIELD_TYPES, + FIELD_FORMAT_IDS, + IFieldFormatType, + IFieldFormatId, + FieldFormat, +} from '../../common'; +import { FieldType } from './types'; + +export class FieldFormatRegisty { + private fieldFormats: Map; + private uiSettings!: UiSettingsClientContract; + private defaultMap: Record; + + constructor() { + this.fieldFormats = new Map(); + this.defaultMap = {}; + } + + getConfig = (key: string, override?: any) => this.uiSettings.get(key, override); + + init(uiSettings: UiSettingsClientContract) { + this.uiSettings = uiSettings; + + this.parseDefaultTypeMap(this.uiSettings.get('format:defaultTypeMap')); + + this.uiSettings.getUpdate$().subscribe(({ key, newValue }) => { + if (key === 'format:defaultTypeMap') { + this.parseDefaultTypeMap(newValue); + } + }); + } + + /** + * Get the id of the default type for this field type + * using the format:defaultTypeMap config map + * + * @param {KBN_FIELD_TYPES} fieldType - the field type + * @param {ES_FIELD_TYPES[]} esTypes - Array of ES data types + * @return {FieldType} + */ + getDefaultConfig = (fieldType: KBN_FIELD_TYPES, esTypes?: ES_FIELD_TYPES[]): FieldType => { + const type = this.getDefaultTypeName(fieldType, esTypes); + + return ( + (this.defaultMap && this.defaultMap[type]) || { id: FIELD_FORMAT_IDS.STRING, params: {} } + ); + }; + + /** + * Get a derived FieldFormat class by its id. + * + * @param {IFieldFormatId} formatId - the format id + * @return {FieldFormat} + */ + getType = (formatId: IFieldFormatId): IFieldFormatType | undefined => { + return this.fieldFormats.get(formatId); + }; + + /** + * Get the default FieldFormat type (class) for + * a field type, using the format:defaultTypeMap. + * used by the field editor + * + * @param {KBN_FIELD_TYPES} fieldType + * @param {ES_FIELD_TYPES[]} esTypes - Array of ES data types + * @return {FieldFormat} + */ + getDefaultType = ( + fieldType: KBN_FIELD_TYPES, + esTypes: ES_FIELD_TYPES[] + ): IFieldFormatType | undefined => { + const config = this.getDefaultConfig(fieldType, esTypes); + + return this.getType(config.id); + }; + + /** + * Get the name of the default type for ES types like date_nanos + * using the format:defaultTypeMap config map + * + * @param {ES_FIELD_TYPES[]} esTypes - Array of ES data types + * @return {ES_FIELD_TYPES} + */ + getTypeNameByEsTypes = (esTypes: ES_FIELD_TYPES[] | undefined): ES_FIELD_TYPES | undefined => { + if (!Array.isArray(esTypes)) { + return; + } + + return esTypes.find(type => this.defaultMap[type] && this.defaultMap[type].es); + }; + + /** + * Get the default FieldFormat type name for + * a field type, using the format:defaultTypeMap. + * + * @param {KBN_FIELD_TYPES} fieldType + * @param {ES_FIELD_TYPES[]} esTypes + * @return {ES_FIELD_TYPES | String} + */ + getDefaultTypeName = ( + fieldType: KBN_FIELD_TYPES, + esTypes?: ES_FIELD_TYPES[] + ): ES_FIELD_TYPES | KBN_FIELD_TYPES => { + const esType = this.getTypeNameByEsTypes(esTypes); + + return esType || fieldType; + }; + + /** + * Get the singleton instance of the FieldFormat type by its id. + * + * @param {IFieldFormatId} formatId + * @return {FIELD_FORMATS_INSTANCES[number]} + */ + getInstance = memoize( + (formatId: IFieldFormatId): FieldFormat => { + const DerivedFieldFormat = this.getType(formatId); + + if (!DerivedFieldFormat) { + throw new Error(`Field Format '${formatId}' not found!`); + } + + return new DerivedFieldFormat({}, this.getConfig); + } + ); + + /** + * Get the default fieldFormat instance for a field format. + * + * @param {KBN_FIELD_TYPES} fieldType + * @param {ES_FIELD_TYPES[]} esTypes + * @return {FieldFormat} + */ + getDefaultInstancePlain(fieldType: KBN_FIELD_TYPES, esTypes?: ES_FIELD_TYPES[]): FieldFormat { + const conf = this.getDefaultConfig(fieldType, esTypes); + + const DerivedFieldFormat = this.getType(conf.id); + + if (!DerivedFieldFormat) { + throw new Error(`Field Format '${conf.id}' not found!`); + } + + return new DerivedFieldFormat(conf.params, this.getConfig); + } + /** + * Returns a cache key built by the given variables for caching in memoized + * Where esType contains fieldType, fieldType is returned + * -> kibana types have a higher priority in that case + * -> would lead to failing tests that match e.g. date format with/without esTypes + * https://lodash.com/docs#memoize + * + * @param {KBN_FIELD_TYPES} fieldType + * @param {ES_FIELD_TYPES[]} esTypes + * @return {String} + */ + getDefaultInstanceCacheResolver(fieldType: KBN_FIELD_TYPES, esTypes: ES_FIELD_TYPES[]): string { + // @ts-ignore + return Array.isArray(esTypes) && esTypes.indexOf(fieldType) === -1 + ? [fieldType, ...esTypes].join('-') + : fieldType; + } + + /** + * Get filtered list of field formats by format type + * + * @param {KBN_FIELD_TYPES} fieldType + * @return {FieldFormat[]} + */ + getByFieldType(fieldType: KBN_FIELD_TYPES): IFieldFormatType[] { + return [...this.fieldFormats.values()].filter( + (format: IFieldFormatType) => format.fieldType.indexOf(fieldType) !== -1 + ); + } + + /** + * Get the default fieldFormat instance for a field format. + * It's a memoized function that builds and reads a cache + * + * @param {KBN_FIELD_TYPES} fieldType + * @param {ES_FIELD_TYPES[]} esTypes + * @return {FieldFormat} + */ + getDefaultInstance = memoize(this.getDefaultInstancePlain, this.getDefaultInstanceCacheResolver); + + parseDefaultTypeMap(value: any) { + this.defaultMap = value; + forOwn(this, fn => { + if (isFunction(fn) && fn.cache) { + // clear all memoize caches + // @ts-ignore + fn.cache = new memoize.Cache(); + } + }); + } + + register = (fieldFormats: IFieldFormatType[]) => { + fieldFormats.forEach(fieldFormat => { + this.fieldFormats.set(fieldFormat.id, fieldFormat); + }); + + return this; + }; +} diff --git a/src/plugins/data/public/field_formats_provider/field_formats_service.ts b/src/plugins/data/public/field_formats_provider/field_formats_service.ts new file mode 100644 index 0000000000000..b144ea7ec2530 --- /dev/null +++ b/src/plugins/data/public/field_formats_provider/field_formats_service.ts @@ -0,0 +1,87 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { UiSettingsClientContract } from 'src/core/public'; +import { FieldFormatRegisty } from './field_formats'; + +import { + BoolFormat, + BytesFormat, + ColorFormat, + DateFormat, + DateNanosFormat, + DurationFormat, + IpFormat, + NumberFormat, + PercentFormat, + RelativeDateFormat, + SourceFormat, + StaticLookupFormat, + StringFormat, + TruncateFormat, + UrlFormat, +} from '../../common/'; + +/** + * Field Format Service + * @internal + */ +interface FieldFormatsServiceDependencies { + uiSettings: UiSettingsClientContract; +} + +export class FieldFormatsService { + private readonly fieldFormats: FieldFormatRegisty = new FieldFormatRegisty(); + + public setup({ uiSettings }: FieldFormatsServiceDependencies) { + this.fieldFormats.init(uiSettings); + + this.fieldFormats.register([ + BoolFormat, + BytesFormat, + ColorFormat, + DateFormat, + DateNanosFormat, + DurationFormat, + IpFormat, + NumberFormat, + PercentFormat, + RelativeDateFormat, + SourceFormat, + StaticLookupFormat, + StringFormat, + TruncateFormat, + UrlFormat, + ]); + + return this.fieldFormats as FieldFormatsSetup; + } + + public start() { + return this.fieldFormats as FieldFormatsStart; + } + + public stop() { + // nothing to do here yet + } +} + +/** @public */ +export type FieldFormatsSetup = Omit; +export type FieldFormatsStart = Omit; diff --git a/src/legacy/core_plugins/kibana/public/visualize/help_menu/help_menu.js b/src/plugins/data/public/field_formats_provider/index.ts similarity index 50% rename from src/legacy/core_plugins/kibana/public/visualize/help_menu/help_menu.js rename to src/plugins/data/public/field_formats_provider/index.ts index 40a1b79ea3520..442d877c5316a 100644 --- a/src/legacy/core_plugins/kibana/public/visualize/help_menu/help_menu.js +++ b/src/plugins/data/public/field_formats_provider/index.ts @@ -17,29 +17,5 @@ * under the License. */ -import React, { Fragment, PureComponent } from 'react'; -import { EuiButton, EuiHorizontalRule, EuiSpacer } from '@elastic/eui'; -import { FormattedMessage } from '@kbn/i18n/react'; - -import { getServices } from '../kibana_services'; - -const { docLinks } = getServices(); - -export class HelpMenu extends PureComponent { - render() { - return ( - - - - - - - - ); - } -} +export { FieldFormatRegisty } from './field_formats'; // TODO: Try to remove +export { FieldFormatsService, FieldFormatsSetup, FieldFormatsStart } from './field_formats_service'; diff --git a/src/legacy/core_plugins/kibana/public/discover/components/help_menu/help_menu.js b/src/plugins/data/public/field_formats_provider/types.ts similarity index 50% rename from src/legacy/core_plugins/kibana/public/discover/components/help_menu/help_menu.js rename to src/plugins/data/public/field_formats_provider/types.ts index ad68e55e71622..fc33bf4d38f85 100644 --- a/src/legacy/core_plugins/kibana/public/discover/components/help_menu/help_menu.js +++ b/src/plugins/data/public/field_formats_provider/types.ts @@ -17,27 +17,10 @@ * under the License. */ -import React, { Fragment, PureComponent } from 'react'; -import { EuiButton, EuiHorizontalRule, EuiSpacer } from '@elastic/eui'; -import { FormattedMessage } from '@kbn/i18n/react'; -import { getServices } from '../../kibana_services'; -const { docLinks } = getServices(); +import { IFieldFormatId } from '../../common'; -export class HelpMenu extends PureComponent { - render() { - return ( - - - - - - - - ); - } +export interface FieldType { + id: IFieldFormatId; + params: Record; + es?: boolean; } diff --git a/src/plugins/data/public/index.ts b/src/plugins/data/public/index.ts index 4477c6defbc81..6a2df6a61d136 100644 --- a/src/plugins/data/public/index.ts +++ b/src/plugins/data/public/index.ts @@ -29,6 +29,8 @@ export { DataPublicPlugin as Plugin }; export * from '../common'; export * from './autocomplete_provider'; +export * from './field_formats_provider'; + export * from './types'; export { IRequestTypesMap, IResponseTypesMap } from './search'; diff --git a/src/plugins/data/public/mocks.ts b/src/plugins/data/public/mocks.ts index 4aae63c24d7fc..ff5c96c2d89ed 100644 --- a/src/plugins/data/public/mocks.ts +++ b/src/plugins/data/public/mocks.ts @@ -16,7 +16,7 @@ * specific language governing permissions and limitations * under the License. */ -import { Plugin } from '.'; +import { FieldFormatRegisty, Plugin, FieldFormatsStart, FieldFormatsSetup } from '.'; import { searchSetupMock } from './search/mocks'; import { queryServiceMock } from './query/mocks'; @@ -29,11 +29,29 @@ const autocompleteMock: any = { clearProviders: jest.fn(), }; +const fieldFormatsMock: PublicMethodsOf = { + getByFieldType: jest.fn(), + getConfig: jest.fn(), + getDefaultConfig: jest.fn(), + getDefaultInstance: jest.fn() as any, + getDefaultInstanceCacheResolver: jest.fn(), + getDefaultInstancePlain: jest.fn(), + getDefaultType: jest.fn(), + getDefaultTypeName: jest.fn(), + getInstance: jest.fn() as any, + getType: jest.fn(), + getTypeNameByEsTypes: jest.fn(), + init: jest.fn(), + register: jest.fn(), + parseDefaultTypeMap: jest.fn(), +}; + const createSetupContract = (): Setup => { const querySetupMock = queryServiceMock.createSetupContract(); const setupContract = { autocomplete: autocompleteMock, search: searchSetupMock, + fieldFormats: fieldFormatsMock as FieldFormatsSetup, query: querySetupMock, }; @@ -46,6 +64,7 @@ const createStartContract = (): Start => { autocomplete: autocompleteMock, getSuggestions: jest.fn(), search: { search: jest.fn() }, + fieldFormats: fieldFormatsMock as FieldFormatsStart, query: queryStartMock, }; return startContract; diff --git a/src/plugins/data/public/plugin.ts b/src/plugins/data/public/plugin.ts index 79db34c022b39..3aa9cd9a0bcb4 100644 --- a/src/plugins/data/public/plugin.ts +++ b/src/plugins/data/public/plugin.ts @@ -17,29 +17,34 @@ * under the License. */ -import { PluginInitializerContext, CoreSetup, CoreStart, Plugin } from '../../../core/public'; +import { PluginInitializerContext, CoreSetup, CoreStart, Plugin } from 'src/core/public'; import { Storage } from '../../kibana_utils/public'; import { DataPublicPluginSetup, DataPublicPluginStart } from './types'; import { AutocompleteProviderRegister } from './autocomplete_provider'; import { getSuggestionsProvider } from './suggestions_provider'; import { SearchService } from './search/search_service'; +import { FieldFormatsService } from './field_formats_provider'; import { QueryService } from './query'; export class DataPublicPlugin implements Plugin { private readonly autocomplete = new AutocompleteProviderRegister(); private readonly searchService: SearchService; + private readonly fieldFormatsService: FieldFormatsService; private readonly queryService: QueryService; constructor(initializerContext: PluginInitializerContext) { this.searchService = new SearchService(initializerContext); this.queryService = new QueryService(); + this.fieldFormatsService = new FieldFormatsService(); } public setup(core: CoreSetup): DataPublicPluginSetup { const storage = new Storage(window.localStorage); + return { autocomplete: this.autocomplete, search: this.searchService.setup(core), + fieldFormats: this.fieldFormatsService.setup(core), query: this.queryService.setup({ uiSettings: core.uiSettings, storage, @@ -52,6 +57,7 @@ export class DataPublicPlugin implements Plugin { + appName: string; + uiSettings: CoreStart['uiSettings']; + savedObjects: CoreStart['savedObjects']; + notifications: CoreStart['notifications']; + http: CoreStart['http']; + storage: IStorageWrapper; + data: DataPublicPluginStart; +} diff --git a/src/plugins/expressions/public/loader.test.ts b/src/plugins/expressions/public/loader.test.ts index 0b5c62d947564..1a9c878c8808d 100644 --- a/src/plugins/expressions/public/loader.test.ts +++ b/src/plugins/expressions/public/loader.test.ts @@ -17,8 +17,8 @@ * under the License. */ +import { first, skip } from 'rxjs/operators'; import { fromExpression } from '@kbn/interpreter/common'; -import { first } from 'rxjs/operators'; import { loader, ExpressionLoader } from './loader'; import { ExpressionDataHandler } from './execute'; import { IInterpreterRenderHandlers } from './types'; @@ -124,7 +124,7 @@ describe('ExpressionLoader', () => { let response = await expressionLoader.render$.pipe(first()).toPromise(); expect(response).toBe(1); expressionLoader.update('test'); - response = await expressionLoader.render$.pipe(first()).toPromise(); + response = await expressionLoader.render$.pipe(skip(1), first()).toPromise(); expect(response).toBe(2); }); diff --git a/src/plugins/expressions/public/loader.ts b/src/plugins/expressions/public/loader.ts index 1e26c813a8902..200249b60c773 100644 --- a/src/plugins/expressions/public/loader.ts +++ b/src/plugins/expressions/public/loader.ts @@ -39,7 +39,6 @@ export class ExpressionLoader { private loadingSubject: Subject; private data: Data; private params: IExpressionLoaderParams = {}; - private ignoreNextResponse = false; constructor( element: HTMLElement, @@ -134,15 +133,14 @@ export class ExpressionLoader { params: IExpressionLoaderParams ): Promise => { if (this.dataHandler && this.dataHandler.isPending) { - this.ignoreNextResponse = true; this.dataHandler.cancel(); } this.setParams(params); this.dataHandler = new ExpressionDataHandler(expression, params); if (!params.inspectorAdapters) params.inspectorAdapters = this.dataHandler.inspect(); - const data = await this.dataHandler.getData(); - if (this.ignoreNextResponse) { - this.ignoreNextResponse = false; + const prevDataHandler = this.dataHandler; + const data = await prevDataHandler.getData(); + if (this.dataHandler !== prevDataHandler) { return; } this.dataSubject.next(data); diff --git a/src/plugins/expressions/public/render.test.ts b/src/plugins/expressions/public/render.test.ts index 9d555f9760ee7..6b5acc8405fd2 100644 --- a/src/plugins/expressions/public/render.test.ts +++ b/src/plugins/expressions/public/render.test.ts @@ -128,5 +128,19 @@ describe('ExpressionRenderHandler', () => { expressionRenderHandler.render({ type: 'render', as: 'test' }); }); }); + + // in case render$ subscription happen after render() got called + // we still want to be notified about sync render$ updates + it("doesn't swallow sync render errors", async () => { + const expressionRenderHandler = new ExpressionRenderHandler(element); + expressionRenderHandler.render(false); + const promise = expressionRenderHandler.render$.pipe(first()).toPromise(); + await expect(promise).resolves.toEqual({ + type: 'error', + error: { + message: 'invalid data provided to the expression renderer', + }, + }); + }); }); }); diff --git a/src/plugins/expressions/public/render.ts b/src/plugins/expressions/public/render.ts index 8475325a2c625..364d5f587bb6f 100644 --- a/src/plugins/expressions/public/render.ts +++ b/src/plugins/expressions/public/render.ts @@ -19,7 +19,7 @@ import { Observable } from 'rxjs'; import * as Rx from 'rxjs'; -import { share } from 'rxjs/operators'; +import { filter, share } from 'rxjs/operators'; import { event, RenderId, Data, IInterpreterRenderHandlers } from './types'; import { getRenderersRegistry } from './services'; @@ -38,7 +38,7 @@ export class ExpressionRenderHandler { private element: HTMLElement; private destroyFn?: any; private renderCount: number = 0; - private renderSubject: Rx.Subject; + private renderSubject: Rx.BehaviorSubject; private eventsSubject: Rx.Subject; private updateSubject: Rx.Subject; private handlers: IInterpreterRenderHandlers; @@ -49,8 +49,11 @@ export class ExpressionRenderHandler { this.eventsSubject = new Rx.Subject(); this.events$ = this.eventsSubject.asObservable().pipe(share()); - this.renderSubject = new Rx.Subject(); - this.render$ = this.renderSubject.asObservable().pipe(share()); + this.renderSubject = new Rx.BehaviorSubject(null as RenderId | RenderError | null); + this.render$ = this.renderSubject.asObservable().pipe( + share(), + filter(_ => _ !== null) + ) as Observable; this.updateSubject = new Rx.Subject(); this.update$ = this.updateSubject.asObservable().pipe(share()); @@ -75,7 +78,7 @@ export class ExpressionRenderHandler { }; } - render = (data: Data, extraHandlers: IExpressionRendererExtraHandlers = {}) => { + render = async (data: Data, extraHandlers: IExpressionRendererExtraHandlers = {}) => { if (!data || typeof data !== 'object') { this.renderSubject.next({ type: 'error', @@ -108,7 +111,7 @@ export class ExpressionRenderHandler { try { // Rendering is asynchronous, completed by handlers.done() - getRenderersRegistry() + await getRenderersRegistry() .get(data.as)! .render(this.element, data.value, { ...this.handlers, ...extraHandlers }); } catch (e) { diff --git a/src/plugins/testbed/public/index.ts b/src/plugins/testbed/public/index.ts index 44eea308a31d9..601db10f6f8bb 100644 --- a/src/plugins/testbed/public/index.ts +++ b/src/plugins/testbed/public/index.ts @@ -17,8 +17,9 @@ * under the License. */ -import { PluginInitializer } from 'kibana/public'; +import { PluginInitializer, PluginInitializerContext } from 'kibana/public'; import { TestbedPlugin, TestbedPluginSetup, TestbedPluginStart } from './plugin'; -export const plugin: PluginInitializer = () => - new TestbedPlugin(); +export const plugin: PluginInitializer = ( + initializerContext: PluginInitializerContext +) => new TestbedPlugin(initializerContext); diff --git a/src/plugins/testbed/public/plugin.ts b/src/plugins/testbed/public/plugin.ts index bf51dbf0b8e78..8c70485d9ee8b 100644 --- a/src/plugins/testbed/public/plugin.ts +++ b/src/plugins/testbed/public/plugin.ts @@ -17,12 +17,20 @@ * under the License. */ -import { Plugin, CoreSetup } from 'kibana/public'; +import { Plugin, CoreSetup, PluginInitializerContext } from 'kibana/public'; + +interface ConfigType { + uiProp: string; +} export class TestbedPlugin implements Plugin { - public setup(core: CoreSetup, deps: {}) { + constructor(private readonly initializerContext: PluginInitializerContext) {} + + public async setup(core: CoreSetup, deps: {}) { + const config = this.initializerContext.config.get(); + // eslint-disable-next-line no-console - console.log(`Testbed plugin set up`); + console.log(`Testbed plugin set up. uiProp: '${config.uiProp}'`); return { foo: 'bar', }; diff --git a/src/plugins/testbed/server/index.ts b/src/plugins/testbed/server/index.ts index 4dd22d3dce1ef..07fda4eb98727 100644 --- a/src/plugins/testbed/server/index.ts +++ b/src/plugins/testbed/server/index.ts @@ -20,15 +20,28 @@ import { map, mergeMap } from 'rxjs/operators'; import { schema, TypeOf } from '@kbn/config-schema'; -import { CoreSetup, CoreStart, Logger, PluginInitializerContext, PluginName } from 'kibana/server'; +import { + CoreSetup, + CoreStart, + Logger, + PluginInitializerContext, + PluginConfigDescriptor, + PluginName, +} from 'kibana/server'; -export const config = { - schema: schema.object({ - secret: schema.string({ defaultValue: 'Not really a secret :/' }), - }), -}; +const configSchema = schema.object({ + secret: schema.string({ defaultValue: 'Not really a secret :/' }), + uiProp: schema.string({ defaultValue: 'Accessible from client' }), +}); + +type ConfigType = TypeOf; -type ConfigType = TypeOf; +export const config: PluginConfigDescriptor = { + exposeToBrowser: { + uiProp: true, + }, + schema: configSchema, +}; class Plugin { private readonly log: Logger; diff --git a/src/legacy/core_plugins/kibana/public/field_formats/register.js b/src/test_utils/public/stub_field_formats.ts similarity index 60% rename from src/legacy/core_plugins/kibana/public/field_formats/register.js rename to src/test_utils/public/stub_field_formats.ts index 9709b56fc8c3c..39c6fb2f6d10e 100644 --- a/src/legacy/core_plugins/kibana/public/field_formats/register.js +++ b/src/test_utils/public/stub_field_formats.ts @@ -16,38 +16,49 @@ * specific language governing permissions and limitations * under the License. */ +import { UiSettingsClientContract } from 'kibana/public'; -import { fieldFormats } from 'ui/registry/field_formats'; import { - UrlFormat, - StringFormat, - NumberFormat, + FieldFormatRegisty, + BoolFormat, BytesFormat, - TruncateFormat, - RelativeDateFormat, - PercentFormat, - IpFormat, - DurationFormat, - DateNanosFormat, - DateFormat, ColorFormat, - BoolFormat, + DateFormat, + DateNanosFormat, + DurationFormat, + IpFormat, + NumberFormat, + PercentFormat, + RelativeDateFormat, SourceFormat, - StaticLookupFormat -} from '../../../../../plugins/data/public'; + StaticLookupFormat, + StringFormat, + TruncateFormat, + UrlFormat, +} from '../../plugins/data/public/'; + +export const getFieldFormatsRegistry = (uiSettings: UiSettingsClientContract) => { + const fieldFormats = new FieldFormatRegisty(); + + fieldFormats.register([ + BoolFormat, + BytesFormat, + ColorFormat, + DateFormat, + DateNanosFormat, + DurationFormat, + IpFormat, + NumberFormat, + PercentFormat, + RelativeDateFormat, + SourceFormat, + StaticLookupFormat, + StringFormat, + TruncateFormat, + UrlFormat, + ]); + + fieldFormats.init(uiSettings); -fieldFormats.register(UrlFormat); -fieldFormats.register(BytesFormat); -fieldFormats.register(DateFormat); -fieldFormats.register(DateNanosFormat); -fieldFormats.register(RelativeDateFormat); -fieldFormats.register(DurationFormat); -fieldFormats.register(IpFormat); -fieldFormats.register(NumberFormat); -fieldFormats.register(PercentFormat); -fieldFormats.register(StringFormat); -fieldFormats.register(SourceFormat); -fieldFormats.register(ColorFormat); -fieldFormats.register(TruncateFormat); -fieldFormats.register(BoolFormat); -fieldFormats.register(StaticLookupFormat); + return fieldFormats; +}; diff --git a/src/test_utils/public/stub_index_pattern.js b/src/test_utils/public/stub_index_pattern.js index a6a0eb386d32e..b41ebe3e61861 100644 --- a/src/test_utils/public/stub_index_pattern.js +++ b/src/test_utils/public/stub_index_pattern.js @@ -28,9 +28,15 @@ import { formatHitProvider, flattenHitWrapper, } from 'ui/index_patterns'; -import { fieldFormats } from 'ui/registry/field_formats'; +import { + FIELD_FORMAT_IDS, +} from '../../plugins/data/public'; + +import { getFieldFormatsRegistry } from './stub_field_formats'; + +export default function StubIndexPattern(pattern, getConfig, timeField, fields, uiSettings) { + const registeredFieldFormats = getFieldFormatsRegistry(uiSettings); -export default function StubIndexPattern(pattern, getConfig, timeField, fields) { this.id = pattern; this.title = pattern; this.popularizeField = sinon.stub(); @@ -47,7 +53,7 @@ export default function StubIndexPattern(pattern, getConfig, timeField, fields) this.getComputedFields = IndexPattern.prototype.getComputedFields.bind(this); this.flattenHit = flattenHitWrapper(this, this.metaFields); - this.formatHit = formatHitProvider(this, fieldFormats.getDefaultInstance('string')); + this.formatHit = formatHitProvider(this, registeredFieldFormats.getDefaultInstance(FIELD_FORMAT_IDS.STRING)); this.fieldsFetcher = { apiClient: { baseUrl: '' } }; this.formatField = this.formatHit.formatField; @@ -56,7 +62,7 @@ export default function StubIndexPattern(pattern, getConfig, timeField, fields) }; this.stubSetFieldFormat = function (fieldName, id, params) { - const FieldFormat = fieldFormats.getType(id); + const FieldFormat = registeredFieldFormats.getType(id); this.fieldFormatMap[fieldName] = new FieldFormat(params); this._reindexFields(); }; diff --git a/test/accessibility/apps/discover.ts b/test/accessibility/apps/discover.ts index e3f73ad4bcaf8..38ee5b7db39c4 100644 --- a/test/accessibility/apps/discover.ts +++ b/test/accessibility/apps/discover.ts @@ -19,9 +19,6 @@ import { FtrProviderContext } from '../ftr_provider_context'; -const FROM_TIME = '2015-09-19 06:31:44.000'; -const TO_TIME = '2015-09-23 18:31:44.000'; - export default function({ getService, getPageObjects }: FtrProviderContext) { const PageObjects = getPageObjects(['common', 'timePicker']); const a11y = getService('a11y'); @@ -36,7 +33,7 @@ export default function({ getService, getPageObjects }: FtrProviderContext) { defaultIndex: 'logstash-*', }); await PageObjects.common.navigateToApp('discover'); - await PageObjects.timePicker.setAbsoluteRange(FROM_TIME, TO_TIME); + await PageObjects.timePicker.setDefaultAbsoluteRange(); }); it('main view', async () => { diff --git a/test/api_integration/apis/home/sample_data.js b/test/api_integration/apis/home/sample_data.js index 7ca66e87a9325..042f490768af0 100644 --- a/test/api_integration/apis/home/sample_data.js +++ b/test/api_integration/apis/home/sample_data.js @@ -22,7 +22,7 @@ import expect from '@kbn/expect'; export default function ({ getService }) { const supertest = getService('supertest'); - const es = getService('es'); + const es = getService('legacyEs'); const MILLISECOND_IN_WEEK = 1000 * 60 * 60 * 24 * 7; 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 4e50b965211c2..77e024c9d20cc 100644 --- a/test/api_integration/apis/index_patterns/es_errors/errors.js +++ b/test/api_integration/apis/index_patterns/es_errors/errors.js @@ -34,7 +34,7 @@ import { } from './lib'; export default function ({ getService }) { - const es = getService('es'); + const es = getService('legacyEs'); const esArchiver = getService('esArchiver'); describe('index_patterns/* error handler', () => { diff --git a/test/api_integration/apis/kql_telemetry/kql_telemetry.js b/test/api_integration/apis/kql_telemetry/kql_telemetry.js index 87d06ee9458d6..25a68bb4bb2b6 100644 --- a/test/api_integration/apis/kql_telemetry/kql_telemetry.js +++ b/test/api_integration/apis/kql_telemetry/kql_telemetry.js @@ -24,7 +24,7 @@ import { get } from 'lodash'; export default function ({ getService }) { const supertest = getService('supertest'); const esArchiver = getService('esArchiver'); - const es = getService('es'); + const es = getService('legacyEs'); describe('telemetry API', () => { before(() => esArchiver.load('saved_objects/basic')); diff --git a/test/api_integration/apis/management/saved_objects/find.js b/test/api_integration/apis/management/saved_objects/find.js index 0e7cf08fa5c26..6bb3c0cebddbf 100644 --- a/test/api_integration/apis/management/saved_objects/find.js +++ b/test/api_integration/apis/management/saved_objects/find.js @@ -20,7 +20,7 @@ import expect from '@kbn/expect'; export default function ({ getService }) { - const es = getService('es'); + const es = getService('legacyEs'); const supertest = getService('supertest'); const esArchiver = getService('esArchiver'); diff --git a/test/api_integration/apis/saved_objects/bulk_create.js b/test/api_integration/apis/saved_objects/bulk_create.js index e77e08d949f2b..3a520d369120d 100644 --- a/test/api_integration/apis/saved_objects/bulk_create.js +++ b/test/api_integration/apis/saved_objects/bulk_create.js @@ -21,7 +21,7 @@ import expect from '@kbn/expect'; export default function ({ getService }) { const supertest = getService('supertest'); - const es = getService('es'); + const es = getService('legacyEs'); const esArchiver = getService('esArchiver'); const BULK_REQUESTS = [ diff --git a/test/api_integration/apis/saved_objects/bulk_get.js b/test/api_integration/apis/saved_objects/bulk_get.js index 8c5b589a12a2e..52733aa70200b 100644 --- a/test/api_integration/apis/saved_objects/bulk_get.js +++ b/test/api_integration/apis/saved_objects/bulk_get.js @@ -21,7 +21,7 @@ import expect from '@kbn/expect'; export default function ({ getService }) { const supertest = getService('supertest'); - const es = getService('es'); + const es = getService('legacyEs'); const esArchiver = getService('esArchiver'); const BULK_REQUESTS = [ diff --git a/test/api_integration/apis/saved_objects/bulk_update.js b/test/api_integration/apis/saved_objects/bulk_update.js index 4bdf257ceef02..b38934aecd0fb 100644 --- a/test/api_integration/apis/saved_objects/bulk_update.js +++ b/test/api_integration/apis/saved_objects/bulk_update.js @@ -22,7 +22,7 @@ import _ from 'lodash'; export default function ({ getService }) { const supertest = getService('supertest'); - const es = getService('es'); + const es = getService('legacyEs'); const esArchiver = getService('esArchiver'); diff --git a/test/api_integration/apis/saved_objects/create.js b/test/api_integration/apis/saved_objects/create.js index eefd9e8ab1a95..363aa9d30c08d 100644 --- a/test/api_integration/apis/saved_objects/create.js +++ b/test/api_integration/apis/saved_objects/create.js @@ -21,7 +21,7 @@ import expect from '@kbn/expect'; export default function ({ getService }) { const supertest = getService('supertest'); - const es = getService('es'); + const es = getService('legacyEs'); const esArchiver = getService('esArchiver'); describe('create', () => { diff --git a/test/api_integration/apis/saved_objects/delete.js b/test/api_integration/apis/saved_objects/delete.js index a9037bf697406..8aa76e99312b0 100644 --- a/test/api_integration/apis/saved_objects/delete.js +++ b/test/api_integration/apis/saved_objects/delete.js @@ -21,7 +21,7 @@ import expect from '@kbn/expect'; export default function ({ getService }) { const supertest = getService('supertest'); - const es = getService('es'); + const es = getService('legacyEs'); const esArchiver = getService('esArchiver'); describe('delete', () => { diff --git a/test/api_integration/apis/saved_objects/export.js b/test/api_integration/apis/saved_objects/export.js index 9ab7a09309952..59c9afe24b802 100644 --- a/test/api_integration/apis/saved_objects/export.js +++ b/test/api_integration/apis/saved_objects/export.js @@ -21,7 +21,7 @@ import expect from '@kbn/expect'; export default function ({ getService }) { const supertest = getService('supertest'); - const es = getService('es'); + const es = getService('legacyEs'); const esArchiver = getService('esArchiver'); describe('export', () => { diff --git a/test/api_integration/apis/saved_objects/find.js b/test/api_integration/apis/saved_objects/find.js index 7b2b15d298ce0..e1bec19cf8e6a 100644 --- a/test/api_integration/apis/saved_objects/find.js +++ b/test/api_integration/apis/saved_objects/find.js @@ -21,7 +21,7 @@ import expect from '@kbn/expect'; export default function ({ getService }) { const supertest = getService('supertest'); - const es = getService('es'); + const es = getService('legacyEs'); const esArchiver = getService('esArchiver'); describe('find', () => { diff --git a/test/api_integration/apis/saved_objects/get.js b/test/api_integration/apis/saved_objects/get.js index fb4b6f91b8bb8..9034bc5d84a72 100644 --- a/test/api_integration/apis/saved_objects/get.js +++ b/test/api_integration/apis/saved_objects/get.js @@ -21,7 +21,7 @@ import expect from '@kbn/expect'; export default function ({ getService }) { const supertest = getService('supertest'); - const es = getService('es'); + const es = getService('legacyEs'); const esArchiver = getService('esArchiver'); describe('get', () => { diff --git a/test/api_integration/apis/saved_objects/migrations.js b/test/api_integration/apis/saved_objects/migrations.js index 5c492951ec938..c4b258d47e24b 100644 --- a/test/api_integration/apis/saved_objects/migrations.js +++ b/test/api_integration/apis/saved_objects/migrations.js @@ -31,7 +31,7 @@ import { SavedObjectsSerializer } from '../../../../src/core/server/saved_object import { SavedObjectsSchema } from '../../../../src/core/server/saved_objects/schema'; export default ({ getService }) => { - const es = getService('es'); + const es = getService('legacyEs'); const callCluster = (path, ...args) => _.get(es, path).call(es, ...args); describe('Kibana index migration', () => { diff --git a/test/api_integration/apis/saved_objects/update.js b/test/api_integration/apis/saved_objects/update.js index e6ad6b2b781da..c73ed0ecc6424 100644 --- a/test/api_integration/apis/saved_objects/update.js +++ b/test/api_integration/apis/saved_objects/update.js @@ -21,7 +21,7 @@ import expect from '@kbn/expect'; export default function ({ getService }) { const supertest = getService('supertest'); - const es = getService('es'); + const es = getService('legacyEs'); const esArchiver = getService('esArchiver'); describe('update', () => { diff --git a/test/api_integration/apis/ui_metric/ui_metric.js b/test/api_integration/apis/ui_metric/ui_metric.js index f0c86f2904638..51959bf5f7fda 100644 --- a/test/api_integration/apis/ui_metric/ui_metric.js +++ b/test/api_integration/apis/ui_metric/ui_metric.js @@ -22,7 +22,7 @@ import { ReportManager, METRIC_TYPE } from '@kbn/analytics'; export default function ({ getService }) { const supertest = getService('supertest'); - const es = getService('es'); + const es = getService('legacyEs'); const createStatsMetric = (eventName) => ({ key: ReportManager.createMetricKey({ appName: 'myApp', type: METRIC_TYPE.CLICK, eventName }), diff --git a/test/api_integration/services/index.ts b/test/api_integration/services/index.ts index 573450cae534a..782ea271869ba 100644 --- a/test/api_integration/services/index.ts +++ b/test/api_integration/services/index.ts @@ -23,10 +23,7 @@ import { services as commonServices } from '../../common/services'; import { KibanaSupertestProvider, ElasticsearchSupertestProvider } from './supertest'; export const services = { - es: commonServices.es, - esArchiver: commonServices.esArchiver, - retry: commonServices.retry, + ...commonServices, supertest: KibanaSupertestProvider, esSupertest: ElasticsearchSupertestProvider, - randomness: commonServices.randomness, }; diff --git a/src/legacy/core_plugins/data/public/types.ts b/test/common/services/elasticsearch.ts similarity index 61% rename from src/legacy/core_plugins/data/public/types.ts rename to test/common/services/elasticsearch.ts index b6c9c47cc0ae6..63c4bfeeb4ce7 100644 --- a/src/legacy/core_plugins/data/public/types.ts +++ b/test/common/services/elasticsearch.ts @@ -17,16 +17,17 @@ * under the License. */ -import { UiSettingsClientContract, CoreStart } from 'src/core/public'; -import { DataPublicPluginStart } from 'src/plugins/data/public'; -import { IStorageWrapper } from 'src/plugins/kibana_utils/public'; +import { format as formatUrl } from 'url'; -export interface IDataPluginServices extends Partial { - appName: string; - uiSettings: UiSettingsClientContract; - savedObjects: CoreStart['savedObjects']; - notifications: CoreStart['notifications']; - http: CoreStart['http']; - storage: IStorageWrapper; - data: DataPublicPluginStart; +import { Client } from '@elastic/elasticsearch'; + +import { FtrProviderContext } from '../ftr_provider_context'; + +export function ElasticsearchProvider({ getService }: FtrProviderContext) { + const config = getService('config'); + + return new Client({ + nodes: [formatUrl(config.get('servers.elasticsearch'))], + requestTimeout: config.get('timeouts.esRequestTimeout'), + }); } diff --git a/test/common/services/es_archiver.ts b/test/common/services/es_archiver.ts index e72bb49a76c0d..cfe0610414b4f 100644 --- a/test/common/services/es_archiver.ts +++ b/test/common/services/es_archiver.ts @@ -26,7 +26,7 @@ import * as KibanaServer from './kibana_server'; export function EsArchiverProvider({ getService, hasService }: FtrProviderContext): EsArchiver { const config = getService('config'); - const client = getService('es'); + const client = getService('legacyEs'); const log = getService('log'); if (!config.get('esArchiver')) { diff --git a/test/common/services/index.ts b/test/common/services/index.ts index 225aacc1c9895..3454964f35e07 100644 --- a/test/common/services/index.ts +++ b/test/common/services/index.ts @@ -18,13 +18,15 @@ */ import { LegacyEsProvider } from './legacy_es'; +import { ElasticsearchProvider } from './elasticsearch'; import { EsArchiverProvider } from './es_archiver'; import { KibanaServerProvider } from './kibana_server'; import { RetryProvider } from './retry'; import { RandomnessProvider } from './randomness'; export const services = { - es: LegacyEsProvider, + legacyEs: LegacyEsProvider, + es: ElasticsearchProvider, esArchiver: EsArchiverProvider, kibanaServer: KibanaServerProvider, retry: RetryProvider, diff --git a/test/functional/apps/context/_discover_navigation.js b/test/functional/apps/context/_discover_navigation.js index 147d0e74d1c98..cb328dfa98e3e 100644 --- a/test/functional/apps/context/_discover_navigation.js +++ b/test/functional/apps/context/_discover_navigation.js @@ -19,8 +19,6 @@ import expect from '@kbn/expect'; -const TEST_DISCOVER_START_TIME = '2015-09-19 06:31:44.000'; -const TEST_DISCOVER_END_TIME = '2015-09-23 18:31:44.000'; const TEST_COLUMN_NAMES = ['@message']; const TEST_FILTER_COLUMN_NAMES = [['extension', 'jpg'], ['geo.src', 'IN']]; @@ -34,7 +32,7 @@ export default function ({ getService, getPageObjects }) { this.tags('smoke'); before(async function () { await PageObjects.common.navigateToApp('discover'); - await PageObjects.timePicker.setAbsoluteRange(TEST_DISCOVER_START_TIME, TEST_DISCOVER_END_TIME); + await PageObjects.timePicker.setDefaultAbsoluteRange(); await Promise.all(TEST_COLUMN_NAMES.map((columnName) => ( PageObjects.discover.clickFieldListItemAdd(columnName) ))); diff --git a/test/functional/apps/dashboard/dashboard_time.js b/test/functional/apps/dashboard/dashboard_time.js index 917157e54eee0..39ce43e19d751 100644 --- a/test/functional/apps/dashboard/dashboard_time.js +++ b/test/functional/apps/dashboard/dashboard_time.js @@ -21,9 +21,6 @@ import expect from '@kbn/expect'; const dashboardName = 'Dashboard Test Time'; -const fromTime = '2015-09-19 06:31:44.000'; -const toTime = '2015-09-23 18:31:44.000'; - export default function ({ getPageObjects, getService }) { const PageObjects = getPageObjects(['dashboard', 'header', 'timePicker']); const browser = getService('browser'); @@ -46,31 +43,31 @@ export default function ({ getPageObjects, getService }) { }); it('Does not set the time picker on open', async () => { - await PageObjects.timePicker.setAbsoluteRange(fromTime, toTime); + await PageObjects.timePicker.setDefaultAbsoluteRange(); await PageObjects.dashboard.loadSavedDashboard(dashboardName); const time = await PageObjects.timePicker.getTimeConfig(); - expect(time.start).to.equal('Sep 19, 2015 @ 06:31:44.000'); - expect(time.end).to.equal('Sep 23, 2015 @ 18:31:44.000'); + expect(time.start).to.equal(PageObjects.timePicker.defaultStartTime); + expect(time.end).to.equal(PageObjects.timePicker.defaultEndTime); }); }); describe('dashboard with stored timed', function () { it('is saved with time', async function () { await PageObjects.dashboard.switchToEditMode(); - await PageObjects.timePicker.setAbsoluteRange(fromTime, toTime); + await PageObjects.timePicker.setDefaultAbsoluteRange(); await PageObjects.dashboard.saveDashboard(dashboardName, { storeTimeWithDashboard: true }); }); it('sets time on open', async function () { - await PageObjects.timePicker.setAbsoluteRange('2019-01-01 00:00:00.000', '2019-01-02 00:00:00.000'); + await PageObjects.timePicker.setAbsoluteRange('Jan 1, 2019 @ 00:00:00.000', 'Jan 2, 2019 @ 00:00:00.000'); await PageObjects.dashboard.loadSavedDashboard(dashboardName); const time = await PageObjects.timePicker.getTimeConfig(); - expect(time.start).to.equal('Sep 19, 2015 @ 06:31:44.000'); - expect(time.end).to.equal('Sep 23, 2015 @ 18:31:44.000'); + expect(time.start).to.equal(PageObjects.timePicker.defaultStartTime); + expect(time.end).to.equal(PageObjects.timePicker.defaultEndTime); }); // If time is stored with a dashboard, it's supposed to override the current time settings when opened. @@ -99,7 +96,7 @@ export default function ({ getPageObjects, getService }) { it('preserved during navigation', async function () { await PageObjects.dashboard.loadSavedDashboard(dashboardName); - await PageObjects.timePicker.setAbsoluteRange('2019-01-01 00:00:00.000', '2019-01-02 00:00:00.000'); + await PageObjects.timePicker.setAbsoluteRange('Jan 1, 2019 @ 00:00:00.000', 'Jan 2, 2019 @ 00:00:00.000'); await PageObjects.header.clickVisualize(); await PageObjects.header.clickDashboard(); diff --git a/test/functional/apps/dashboard/dashboard_time_picker.js b/test/functional/apps/dashboard/dashboard_time_picker.js index f09f3fc1de2ad..ab1d1ff74168a 100644 --- a/test/functional/apps/dashboard/dashboard_time_picker.js +++ b/test/functional/apps/dashboard/dashboard_time_picker.js @@ -26,6 +26,7 @@ export default function ({ getService, getPageObjects }) { const dashboardVisualizations = getService('dashboardVisualizations'); const PageObjects = getPageObjects(['dashboard', 'header', 'visualize', 'timePicker']); const browser = getService('browser'); + const kibanaServer = getService('kibanaServer'); describe('dashboard time picker', function describeIndexTests() { before(async function () { @@ -33,6 +34,11 @@ export default function ({ getService, getPageObjects }) { await PageObjects.dashboard.preserveCrossAppState(); }); + after(async () => { + await kibanaServer.uiSettings.replace({}); + await browser.refresh(); + }); + it('Visualization updated when time picker changes', async () => { await PageObjects.dashboard.clickNewDashboard(); await PageObjects.dashboard.addVisualizations([PIE_CHART_VIS_NAME]); @@ -49,7 +55,7 @@ export default function ({ getService, getPageObjects }) { await dashboardExpect.docTableFieldCount(150); // Set to time range with no data - await PageObjects.timePicker.setAbsoluteRange('2000-01-01 00:00:00.000', '2000-01-01 01:00:00.000'); + await PageObjects.timePicker.setAbsoluteRange('Jan 1, 2000 @ 00:00:00.000', 'Jan 1, 2000 @ 01:00:00.000'); await dashboardExpect.docTableFieldCount(0); }); @@ -72,5 +78,16 @@ export default function ({ getService, getPageObjects }) { expect(time.end).to.be('Nov 17, 2015 @ 18:01:36.621'); expect(refresh.interval).to.be('2'); }); + + it('Timepicker respects dateFormat from UI settings', async () => { + await kibanaServer.uiSettings.replace({ 'dateFormat': 'YYYY-MM-DD HH:mm:ss.SSS', }); + await browser.refresh(); + await PageObjects.dashboard.gotoDashboardLandingPage(); + await PageObjects.dashboard.clickNewDashboard(); + await PageObjects.dashboard.addVisualizations([PIE_CHART_VIS_NAME]); + // Same date range as `setTimepickerInHistoricalDataRange` + await PageObjects.timePicker.setAbsoluteRange('2015-09-19 06:31:44.000', '2015-09-23 18:31:44.000'); + await pieChart.expectPieSliceCount(10); + }); }); } diff --git a/test/functional/apps/dashboard/embeddable_rendering.js b/test/functional/apps/dashboard/embeddable_rendering.js index d90de4204bc76..bdbfd41b437eb 100644 --- a/test/functional/apps/dashboard/embeddable_rendering.js +++ b/test/functional/apps/dashboard/embeddable_rendering.js @@ -102,8 +102,8 @@ export default function ({ getService, getPageObjects }) { await PageObjects.dashboard.preserveCrossAppState(); await PageObjects.dashboard.clickNewDashboard(); - const fromTime = '2018-01-01 00:00:00.000'; - const toTime = '2018-04-13 00:00:00.000'; + const fromTime = 'Jan 1, 2018 @ 00:00:00.000'; + const toTime = 'Apr 13, 2018 @ 00:00:00.000'; await PageObjects.timePicker.setAbsoluteRange(fromTime, toTime); }); @@ -145,8 +145,8 @@ export default function ({ getService, getPageObjects }) { it('data rendered correctly when dashboard is opened from listing page', async () => { // Change the time to make sure that it's updated when re-opened from the listing page. - const fromTime = '2018-05-10 00:00:00.000'; - const toTime = '2018-05-11 00:00:00.000'; + const fromTime = 'May 10, 2018 @ 00:00:00.000'; + const toTime = 'May 11, 2018 @ 00:00:00.000'; await PageObjects.timePicker.setAbsoluteRange(fromTime, toTime); await PageObjects.dashboard.loadSavedDashboard('embeddable rendering test'); await PageObjects.dashboard.waitForRenderComplete(); @@ -162,16 +162,16 @@ export default function ({ getService, getPageObjects }) { }); it('panels are updated when time changes outside of data', async () => { - const fromTime = '2018-05-11 00:00:00.000'; - const toTime = '2018-05-12 00:00:00.000'; + const fromTime = 'May 11, 2018 @ 00:00:00.000'; + const toTime = 'May 12, 2018 @ 00:00:00.000'; await PageObjects.timePicker.setAbsoluteRange(fromTime, toTime); await PageObjects.dashboard.waitForRenderComplete(); await expectNoDataRenders(); }); it('panels are updated when time changes inside of data', async () => { - const fromTime = '2018-01-01 00:00:00.000'; - const toTime = '2018-04-13 00:00:00.000'; + const fromTime = 'Jan 1, 2018 @ 00:00:00.000'; + const toTime = 'Apr 13, 2018 @ 00:00:00.000'; await PageObjects.timePicker.setAbsoluteRange(fromTime, toTime); await PageObjects.dashboard.waitForRenderComplete(); await expectAllDataRenders(); diff --git a/test/functional/apps/dashboard/time_zones.js b/test/functional/apps/dashboard/time_zones.js index 19516e5092c1c..30031882ae09e 100644 --- a/test/functional/apps/dashboard/time_zones.js +++ b/test/functional/apps/dashboard/time_zones.js @@ -51,8 +51,8 @@ export default function ({ getService, getPageObjects }) { it('Exported dashboard adjusts EST time to UTC', async () => { const time = await PageObjects.timePicker.getTimeConfigAsAbsoluteTimes(); - expect(time.start).to.be('2018-04-10 03:00:00.000'); - expect(time.end).to.be('2018-04-10 04:00:00.000'); + expect(time.start).to.be('Apr 10, 2018 @ 03:00:00.000'); + expect(time.end).to.be('Apr 10, 2018 @ 04:00:00.000'); await pieChart.expectPieSliceCount(4); }); @@ -63,8 +63,8 @@ export default function ({ getService, getPageObjects }) { await PageObjects.common.navigateToApp('dashboard'); await PageObjects.dashboard.loadSavedDashboard('time zone test'); const time = await PageObjects.timePicker.getTimeConfigAsAbsoluteTimes(); - expect(time.start).to.be('2018-04-09 22:00:00.000'); - expect(time.end).to.be('2018-04-09 23:00:00.000'); + expect(time.start).to.be('Apr 9, 2018 @ 22:00:00.000'); + expect(time.end).to.be('Apr 9, 2018 @ 23:00:00.000'); await pieChart.expectPieSliceCount(4); }); }); diff --git a/test/functional/apps/dashboard/view_edit.js b/test/functional/apps/dashboard/view_edit.js index 958a889271b61..74ddb476064c5 100644 --- a/test/functional/apps/dashboard/view_edit.js +++ b/test/functional/apps/dashboard/view_edit.js @@ -75,7 +75,7 @@ export default function ({ getService, getPageObjects }) { await PageObjects.dashboard.saveDashboard(dashboardName, { storeTimeWithDashboard: true }); await PageObjects.dashboard.switchToEditMode(); - await PageObjects.timePicker.setAbsoluteRange('2013-09-19 06:31:44.000', '2013-09-19 06:31:44.000'); + await PageObjects.timePicker.setAbsoluteRange('Sep 19, 2013 @ 06:31:44.000', 'Sep 19, 2013 @ 06:31:44.000'); await PageObjects.dashboard.clickCancelOutOfEditMode(); // confirm lose changes @@ -161,10 +161,10 @@ export default function ({ getService, getPageObjects }) { describe('and preserves edits on cancel', function () { it('when time changed is stored with dashboard', async function () { await PageObjects.dashboard.gotoDashboardEditMode(dashboardName); - await PageObjects.timePicker.setAbsoluteRange('2013-09-19 06:31:44.000', '2013-09-19 06:31:44.000'); + await PageObjects.timePicker.setAbsoluteRange('Sep 19, 2013 @ 06:31:44.000', 'Sep 19, 2013 @ 06:31:44.000'); await PageObjects.dashboard.saveDashboard(dashboardName, true); await PageObjects.dashboard.switchToEditMode(); - await PageObjects.timePicker.setAbsoluteRange('2015-09-19 06:31:44.000', '2015-09-19 06:31:44.000'); + await PageObjects.timePicker.setAbsoluteRange('Sep 19, 2015 @ 06:31:44.000', 'Sep 19, 2015 @ 06:31:44.000'); await PageObjects.dashboard.clickCancelOutOfEditMode(); await PageObjects.common.clickCancelOnModal(); @@ -186,7 +186,7 @@ export default function ({ getService, getPageObjects }) { await PageObjects.dashboard.setTimepickerInDataRange(); await PageObjects.dashboard.saveDashboard(dashboardName, true); await PageObjects.dashboard.switchToEditMode(); - await PageObjects.timePicker.setAbsoluteRange('2013-09-19 06:31:44.000', '2013-09-19 06:31:44.000'); + await PageObjects.timePicker.setAbsoluteRange('Sep 19, 2013 @ 06:31:44.000', 'Sep 19, 2013 @ 06:31:44.000'); const newTime = await PageObjects.timePicker.getTimeConfig(); await PageObjects.dashboard.clickCancelOutOfEditMode(); @@ -208,7 +208,7 @@ export default function ({ getService, getPageObjects }) { await PageObjects.dashboard.gotoDashboardEditMode(dashboardName); await PageObjects.dashboard.saveDashboard(dashboardName, { storeTimeWithDashboard: false }); await PageObjects.dashboard.switchToEditMode(); - await PageObjects.timePicker.setAbsoluteRange('2014-10-19 06:31:44.000', '2014-12-19 06:31:44.000'); + await PageObjects.timePicker.setAbsoluteRange('Oct 19, 2014 @ 06:31:44.000', 'Dec 19, 2014 @ 06:31:44.000'); await PageObjects.dashboard.clickCancelOutOfEditMode(); await PageObjects.common.expectConfirmModalOpenState(false); diff --git a/test/functional/apps/discover/_date_nanos.js b/test/functional/apps/discover/_date_nanos.js index 6876c8eb6daa4..d9eb40c16c2d4 100644 --- a/test/functional/apps/discover/_date_nanos.js +++ b/test/functional/apps/discover/_date_nanos.js @@ -23,8 +23,8 @@ export default function ({ getService, getPageObjects }) { const esArchiver = getService('esArchiver'); const PageObjects = getPageObjects(['common', 'timePicker', 'discover']); const kibanaServer = getService('kibanaServer'); - const fromTime = '2019-09-22 20:31:44.000'; - const toTime = '2019-09-23 03:31:44.000'; + const fromTime = 'Sep 22, 2019 @ 20:31:44.000'; + const toTime = 'Sep 23, 2019 @ 03:31:44.000'; describe('date_nanos', function () { @@ -41,8 +41,8 @@ export default function ({ getService, getPageObjects }) { it('should show a timestamp with nanoseconds in the first result row', async function () { const time = await PageObjects.timePicker.getTimeConfig(); - expect(time.start).to.be('Sep 22, 2019 @ 20:31:44.000'); - expect(time.end).to.be('Sep 23, 2019 @ 03:31:44.000'); + expect(time.start).to.be(fromTime); + expect(time.end).to.be(toTime); const rowData = await PageObjects.discover.getDocTableIndex(1); expect(rowData.startsWith('Sep 22, 2019 @ 23:50:13.253123345')).to.be.ok(); }); diff --git a/test/functional/apps/discover/_date_nanos_mixed.js b/test/functional/apps/discover/_date_nanos_mixed.js index 8c9a7eb4d5f13..c77ea3b2915e1 100644 --- a/test/functional/apps/discover/_date_nanos_mixed.js +++ b/test/functional/apps/discover/_date_nanos_mixed.js @@ -23,8 +23,8 @@ export default function ({ getService, getPageObjects }) { const esArchiver = getService('esArchiver'); const PageObjects = getPageObjects(['common', 'timePicker', 'discover']); const kibanaServer = getService('kibanaServer'); - const fromTime = '2019-01-01 00:00:00.000'; - const toTime = '2019-01-01 23:59:59.999'; + const fromTime = 'Jan 1, 2019 @ 00:00:00.000'; + const toTime = 'Jan 1, 2019 @ 23:59:59.999'; describe('date_nanos_mixed', function () { diff --git a/test/functional/apps/discover/_discover.js b/test/functional/apps/discover/_discover.js index 9d3f95e28942a..94b2941ecd3d1 100644 --- a/test/functional/apps/discover/_discover.js +++ b/test/functional/apps/discover/_discover.js @@ -33,8 +33,6 @@ export default function ({ getService, getPageObjects }) { }; describe('discover test', function describeIndexTests() { - const fromTime = '2015-09-19 06:31:44.000'; - const toTime = '2015-09-23 18:31:44.000'; before(async function () { log.debug('load kibana index with default index pattern'); @@ -45,7 +43,7 @@ export default function ({ getService, getPageObjects }) { await kibanaServer.uiSettings.replace(defaultSettings); log.debug('discover'); await PageObjects.common.navigateToApp('discover'); - await PageObjects.timePicker.setAbsoluteRange(fromTime, toTime); + await PageObjects.timePicker.setDefaultAbsoluteRange(); }); describe('query', function () { @@ -54,8 +52,8 @@ export default function ({ getService, getPageObjects }) { it('should show correct time range string by timepicker', async function () { const time = await PageObjects.timePicker.getTimeConfig(); - expect(time.start).to.be('Sep 19, 2015 @ 06:31:44.000'); - expect(time.end).to.be('Sep 23, 2015 @ 18:31:44.000'); + expect(time.start).to.be(PageObjects.timePicker.defaultStartTime); + expect(time.end).to.be(PageObjects.timePicker.defaultEndTime); const rowData = await PageObjects.discover.getDocTableIndex(1); log.debug('check the newest doc timestamp in UTC (check diff timezone in last test)'); expect(rowData.startsWith('Sep 22, 2015 @ 23:50:13.253')).to.be.ok(); @@ -88,12 +86,12 @@ export default function ({ getService, getPageObjects }) { it('should show correct time range string in chart', async function () { const actualTimeString = await PageObjects.discover.getChartTimespan(); - const expectedTimeString = `Sep 19, 2015 @ 06:31:44.000 - Sep 23, 2015 @ 18:31:44.000`; + const expectedTimeString = `${PageObjects.timePicker.defaultStartTime} - ${PageObjects.timePicker.defaultEndTime}`; expect(actualTimeString).to.be(expectedTimeString); }); it('should modify the time range when a bar is clicked', async function () { - await PageObjects.timePicker.setAbsoluteRange(fromTime, toTime); + await PageObjects.timePicker.setDefaultAbsoluteRange(); await PageObjects.discover.clickHistogramBar(); const time = await PageObjects.timePicker.getTimeConfig(); expect(time.start).to.be('Sep 21, 2015 @ 09:00:00.000'); @@ -103,7 +101,7 @@ export default function ({ getService, getPageObjects }) { }); it('should modify the time range when the histogram is brushed', async function () { - await PageObjects.timePicker.setAbsoluteRange(fromTime, toTime); + await PageObjects.timePicker.setDefaultAbsoluteRange(); await PageObjects.discover.brushHistogram(); const newDurationHours = await PageObjects.timePicker.getTimeDurationInHours(); @@ -113,7 +111,7 @@ export default function ({ getService, getPageObjects }) { }); it('should show correct initial chart interval of Auto', async function () { - await PageObjects.timePicker.setAbsoluteRange(fromTime, toTime); + await PageObjects.timePicker.setDefaultAbsoluteRange(); await PageObjects.discover.waitUntilSearchingHasFinished(); const actualInterval = await PageObjects.discover.getChartInterval(); @@ -135,8 +133,8 @@ export default function ({ getService, getPageObjects }) { }); describe('query #2, which has an empty time range', () => { - const fromTime = '1999-06-11 09:22:11.000'; - const toTime = '1999-06-12 11:21:04.000'; + const fromTime = 'Jun 11, 1999 @ 09:22:11.000'; + const toTime = 'Jun 12, 1999 @ 11:21:04.000'; before(async () => { log.debug('setAbsoluteRangeForAnotherQuery'); @@ -159,7 +157,7 @@ export default function ({ getService, getPageObjects }) { before(async () => { log.debug('setAbsoluteRangeForAnotherQuery'); - await PageObjects.timePicker.setAbsoluteRange(fromTime, toTime); + await PageObjects.timePicker.setDefaultAbsoluteRange(); await PageObjects.discover.waitUntilSearchingHasFinished(); }); @@ -213,7 +211,7 @@ export default function ({ getService, getPageObjects }) { await kibanaServer.uiSettings.replace({ 'dateFormat:tz': 'America/Phoenix' }); await browser.refresh(); await PageObjects.header.awaitKibanaChrome(); - await PageObjects.timePicker.setAbsoluteRange(fromTime, toTime); + await PageObjects.timePicker.setDefaultAbsoluteRange(); log.debug('check that the newest doc timestamp is now -7 hours from the UTC time in the first test'); const rowData = await PageObjects.discover.getDocTableIndex(1); diff --git a/test/functional/apps/discover/_doc_navigation.js b/test/functional/apps/discover/_doc_navigation.js index e9afa7c9b4c19..dc9f6c3517464 100644 --- a/test/functional/apps/discover/_doc_navigation.js +++ b/test/functional/apps/discover/_doc_navigation.js @@ -19,8 +19,6 @@ import expect from '@kbn/expect'; -const TEST_DOC_START_TIME = '2015-09-19 06:31:44.000'; -const TEST_DOC_END_TIME = '2015-09-23 18:31:44.000'; const TEST_COLUMN_NAMES = ['@message']; const TEST_FILTER_COLUMN_NAMES = [['extension', 'jpg'], ['geo.src', 'IN']]; @@ -35,7 +33,7 @@ export default function ({ getService, getPageObjects }) { before(async function () { await esArchiver.loadIfNeeded('logstash_functional'); await PageObjects.common.navigateToApp('discover'); - await PageObjects.timePicker.setAbsoluteRange(TEST_DOC_START_TIME, TEST_DOC_END_TIME); + await PageObjects.timePicker.setDefaultAbsoluteRange(); await Promise.all(TEST_COLUMN_NAMES.map((columnName) => ( PageObjects.discover.clickFieldListItemAdd(columnName) ))); diff --git a/test/functional/apps/discover/_field_data.js b/test/functional/apps/discover/_field_data.js index 828975445e1ef..38d9a89eecbf3 100644 --- a/test/functional/apps/discover/_field_data.js +++ b/test/functional/apps/discover/_field_data.js @@ -30,8 +30,6 @@ export default function ({ getService, getPageObjects }) { describe('discover tab', function describeIndexTests() { this.tags('smoke'); before(async function () { - const fromTime = '2015-09-19 06:31:44.000'; - const toTime = '2015-09-23 18:31:44.000'; await esArchiver.loadIfNeeded('logstash_functional'); await esArchiver.load('discover'); @@ -41,7 +39,7 @@ export default function ({ getService, getPageObjects }) { }); await PageObjects.common.navigateToApp('discover'); - await PageObjects.timePicker.setAbsoluteRange(fromTime, toTime); + await PageObjects.timePicker.setDefaultAbsoluteRange(); }); describe('field data', function () { diff --git a/test/functional/apps/discover/_inspector.js b/test/functional/apps/discover/_inspector.js index 6a2144e829920..bd04cd6d1bd64 100644 --- a/test/functional/apps/discover/_inspector.js +++ b/test/functional/apps/discover/_inspector.js @@ -58,7 +58,7 @@ export default function ({ getService, getPageObjects }) { }); it('should display request stats with results', async () => { - await PageObjects.timePicker.setAbsoluteRange('2015-09-19 06:31:44.000', '2015-09-23 18:31:44.000'); + await PageObjects.timePicker.setDefaultAbsoluteRange(); await inspector.open(); const requestStats = await inspector.getTableData(); diff --git a/test/functional/apps/discover/_saved_queries.js b/test/functional/apps/discover/_saved_queries.js index 54b026135025c..8fbc40f86e8dc 100644 --- a/test/functional/apps/discover/_saved_queries.js +++ b/test/functional/apps/discover/_saved_queries.js @@ -34,8 +34,6 @@ export default function ({ getService, getPageObjects }) { const testSubjects = getService('testSubjects'); describe('saved queries saved objects', function describeIndexTests() { - const fromTime = '2015-09-19 06:31:44.000'; - const toTime = '2015-09-23 18:31:44.000'; before(async function () { log.debug('load kibana index with default index pattern'); @@ -46,7 +44,7 @@ export default function ({ getService, getPageObjects }) { await kibanaServer.uiSettings.replace(defaultSettings); log.debug('discover'); await PageObjects.common.navigateToApp('discover'); - await PageObjects.timePicker.setAbsoluteRange(fromTime, toTime); + await PageObjects.timePicker.setDefaultAbsoluteRange(); }); describe('saved query management component functionality', function () { @@ -55,8 +53,8 @@ export default function ({ getService, getPageObjects }) { log.debug('set up a query with filters to save'); await queryBar.setQuery('response:200'); await filterBar.addFilter('extension.raw', 'is one of', 'jpg'); - const fromTime = '2015-09-20 08:00:00.000'; - const toTime = '2015-09-21 08:00:00.000'; + const fromTime = 'Sep 20, 2015 @ 08:00:00.000'; + const toTime = 'Sep 21, 2015 @ 08:00:00.000'; await PageObjects.timePicker.setAbsoluteRange(fromTime, toTime); }); @@ -79,15 +77,13 @@ export default function ({ getService, getPageObjects }) { }); it('reinstates filters and the time filter when a saved query has filters and a time filter included', async () => { - const fromTime = '2015-09-19 06:31:44.000'; - const toTime = '2015-09-23 18:31:44.000'; - await PageObjects.timePicker.setAbsoluteRange(fromTime, toTime); + await PageObjects.timePicker.setDefaultAbsoluteRange(); await savedQueryManagementComponent.clearCurrentlyLoadedQuery(); await savedQueryManagementComponent.loadSavedQuery('OkResponse'); const timePickerValues = await PageObjects.timePicker.getTimeConfigAsAbsoluteTimes(); expect(await filterBar.hasFilter('extension.raw', 'jpg')).to.be(true); - expect(timePickerValues.start).to.not.eql(fromTime); - expect(timePickerValues.end).to.not.eql(toTime); + expect(timePickerValues.start).to.not.eql(PageObjects.timePicker.defaultStartTime); + expect(timePickerValues.end).to.not.eql(PageObjects.timePicker.defaultEndTime); }); it('allows saving changes to a currently loaded query via the saved query management component', async () => { diff --git a/test/functional/apps/discover/_shared_links.js b/test/functional/apps/discover/_shared_links.js index 0b2b4f14f126d..8381d9bc7caea 100644 --- a/test/functional/apps/discover/_shared_links.js +++ b/test/functional/apps/discover/_shared_links.js @@ -38,9 +38,6 @@ export default function ({ getService, getPageObjects }) { baseUrl = baseUrl.replace(':80', '').replace(':443', ''); log.debug('New baseUrl = ' + baseUrl); - const fromTime = '2015-09-19 06:31:44.000'; - const toTime = '2015-09-23 18:31:44.000'; - // delete .kibana index and update configDoc await kibanaServer.uiSettings.replace({ defaultIndex: 'logstash-*', @@ -57,7 +54,7 @@ export default function ({ getService, getPageObjects }) { log.debug('discover'); await PageObjects.common.navigateToApp('discover'); - await PageObjects.timePicker.setAbsoluteRange(fromTime, toTime); + await PageObjects.timePicker.setDefaultAbsoluteRange(); //After hiding the time picker, we need to wait for //the refresh button to hide before clicking the share button diff --git a/test/functional/apps/discover/_sidebar.js b/test/functional/apps/discover/_sidebar.js index 26a47b0a12422..4cf8fd44da239 100644 --- a/test/functional/apps/discover/_sidebar.js +++ b/test/functional/apps/discover/_sidebar.js @@ -27,8 +27,6 @@ export default function ({ getService, getPageObjects }) { describe('discover sidebar', function describeIndexTests() { before(async function () { - const fromTime = '2015-09-19 06:31:44.000'; - const toTime = '2015-09-23 18:31:44.000'; // delete .kibana index and update configDoc await kibanaServer.uiSettings.replace({ @@ -44,7 +42,7 @@ export default function ({ getService, getPageObjects }) { log.debug('discover'); await PageObjects.common.navigateToApp('discover'); - await PageObjects.timePicker.setAbsoluteRange(fromTime, toTime); + await PageObjects.timePicker.setDefaultAbsoluteRange(); }); describe('field filtering', function () { diff --git a/test/functional/apps/discover/_source_filters.js b/test/functional/apps/discover/_source_filters.js index 14ecde383fd44..06c81acbd5d43 100644 --- a/test/functional/apps/discover/_source_filters.js +++ b/test/functional/apps/discover/_source_filters.js @@ -27,8 +27,6 @@ export default function ({ getService, getPageObjects }) { describe('source filters', function describeIndexTests() { before(async function () { - const fromTime = '2015-09-19 06:31:44.000'; - const toTime = '2015-09-23 18:31:44.000'; // delete .kibana index and update configDoc await kibanaServer.uiSettings.replace({ @@ -44,7 +42,7 @@ export default function ({ getService, getPageObjects }) { log.debug('discover'); await PageObjects.common.navigateToApp('discover'); - await PageObjects.timePicker.setAbsoluteRange(fromTime, toTime); + await PageObjects.timePicker.setDefaultAbsoluteRange(); //After hiding the time picker, we need to wait for //the refresh button to hide before clicking the share button diff --git a/test/functional/apps/home/_navigation.ts b/test/functional/apps/home/_navigation.ts index c60788b64b2a7..58e0793b2d547 100644 --- a/test/functional/apps/home/_navigation.ts +++ b/test/functional/apps/home/_navigation.ts @@ -28,8 +28,6 @@ export default function({ getService, getPageObjects }: FtrProviderContext) { const esArchiver = getService('esArchiver'); const retry = getService('retry'); const kibanaServer = getService('kibanaServer'); - const fromTime = '2015-09-19 06:31:44.000'; - const toTime = '2015-09-23 18:31:44.000'; const getHost = () => { if (process.env.TEST_KIBANA_HOSTNAME) { @@ -77,7 +75,7 @@ export default function({ getService, getPageObjects }: FtrProviderContext) { // Navigate to discover app await appsMenu.clickLink('Discover'); const discoverUrl = await browser.getCurrentUrl(); - await PageObjects.timePicker.setAbsoluteRange(fromTime, toTime); + await PageObjects.timePicker.setDefaultAbsoluteRange(); const modifiedTimeDiscoverUrl = await browser.getCurrentUrl(); // Navigate to dashboard app diff --git a/test/functional/apps/home/_sample_data.js b/test/functional/apps/home/_sample_data.js index 954c2dd110585..44cb7c36a7f28 100644 --- a/test/functional/apps/home/_sample_data.js +++ b/test/functional/apps/home/_sample_data.js @@ -18,6 +18,7 @@ */ import expect from '@kbn/expect'; +import moment from 'moment'; export default function ({ getService, getPageObjects }) { const retry = getService('retry'); @@ -85,10 +86,9 @@ export default function ({ getService, getPageObjects }) { await PageObjects.home.launchSampleDataSet('flights'); await PageObjects.header.waitUntilLoadingHasFinished(); await renderable.waitForRender(); - 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`; + const todayYearMonthDay = moment().format('MMM D, YYYY'); + const fromTime = `${todayYearMonthDay} @ 00:00:00.000`; + const toTime = `${todayYearMonthDay} @ 23:59:59.999`; await PageObjects.timePicker.setAbsoluteRange(fromTime, toTime); const panelCount = await PageObjects.dashboard.getPanelCount(); expect(panelCount).to.be(18); @@ -119,10 +119,9 @@ export default function ({ getService, getPageObjects }) { await PageObjects.home.launchSampleDataSet('logs'); await PageObjects.header.waitUntilLoadingHasFinished(); await renderable.waitForRender(); - 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`; + const todayYearMonthDay = moment().format('MMM D, YYYY'); + const fromTime = `${todayYearMonthDay} @ 00:00:00.000`; + const toTime = `${todayYearMonthDay} @ 23:59:59.999`; await PageObjects.timePicker.setAbsoluteRange(fromTime, toTime); const panelCount = await PageObjects.dashboard.getPanelCount(); expect(panelCount).to.be(11); @@ -132,10 +131,9 @@ export default function ({ getService, getPageObjects }) { await PageObjects.home.launchSampleDataSet('ecommerce'); await PageObjects.header.waitUntilLoadingHasFinished(); await renderable.waitForRender(); - 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`; + const todayYearMonthDay = moment().format('MMM D, YYYY'); + const fromTime = `${todayYearMonthDay} @ 00:00:00.000`; + const toTime = `${todayYearMonthDay} @ 23:59:59.999`; await PageObjects.timePicker.setAbsoluteRange(fromTime, toTime); const panelCount = await PageObjects.dashboard.getPanelCount(); expect(panelCount).to.be(12); diff --git a/test/functional/apps/management/_handle_alias.js b/test/functional/apps/management/_handle_alias.js index 1556897d69387..99941d37df9e7 100644 --- a/test/functional/apps/management/_handle_alias.js +++ b/test/functional/apps/management/_handle_alias.js @@ -21,7 +21,7 @@ import expect from '@kbn/expect'; export default function ({ getService, getPageObjects }) { const esArchiver = getService('esArchiver'); - const es = getService('es'); + const es = getService('legacyEs'); const retry = getService('retry'); const PageObjects = getPageObjects(['common', 'home', 'settings', 'discover', 'timePicker']); @@ -72,8 +72,8 @@ export default function ({ getService, getPageObjects }) { it('should be able to discover and verify no of hits for alias2', async function () { const expectedHitCount = '5'; - const fromTime = '2016-11-12 05:00:00.000'; - const toTime = '2016-11-19 05:00:00.000'; + const fromTime = 'Nov 12, 2016 @ 05:00:00.000'; + const toTime = 'Nov 19, 2016 @ 05:00:00.000'; await PageObjects.common.navigateToApp('discover'); await PageObjects.discover.selectIndexPattern('alias2'); diff --git a/test/functional/apps/management/_handle_version_conflict.js b/test/functional/apps/management/_handle_version_conflict.js index 217e6d4c1a8d3..e6c0825136ba1 100644 --- a/test/functional/apps/management/_handle_version_conflict.js +++ b/test/functional/apps/management/_handle_version_conflict.js @@ -32,7 +32,7 @@ import expect from '@kbn/expect'; export default function ({ getService, getPageObjects }) { const esArchiver = getService('esArchiver'); const browser = getService('browser'); - const es = getService('es'); + const es = getService('legacyEs'); const retry = getService('retry'); const scriptedFiledName = 'versionConflictScript'; const PageObjects = getPageObjects(['common', 'home', 'settings', 'discover', 'header']); diff --git a/test/functional/apps/management/_kibana_settings.js b/test/functional/apps/management/_kibana_settings.js index 9fb302cdba00a..e5ae709b34d6d 100644 --- a/test/functional/apps/management/_kibana_settings.js +++ b/test/functional/apps/management/_kibana_settings.js @@ -55,7 +55,7 @@ export default function ({ getService, getPageObjects }) { it('when false, dashboard state is unhashed', async function () { await PageObjects.common.navigateToApp('dashboard'); await PageObjects.dashboard.clickNewDashboard(); - await PageObjects.timePicker.setAbsoluteRange('2015-09-19 06:31:44.000', '2015-09-23 18:31:44.000'); + await PageObjects.timePicker.setDefaultAbsoluteRange(); const currentUrl = await browser.getCurrentUrl(); const urlPieces = currentUrl.match(/(.*)?_g=(.*)&_a=(.*)/); const globalState = urlPieces[2]; @@ -78,7 +78,7 @@ export default function ({ getService, getPageObjects }) { it('when true, dashboard state is hashed', async function () { await PageObjects.common.navigateToApp('dashboard'); await PageObjects.dashboard.clickNewDashboard(); - await PageObjects.timePicker.setAbsoluteRange('2015-09-19 06:31:44.000', '2015-09-23 18:31:44.000'); + await PageObjects.timePicker.setDefaultAbsoluteRange(); const currentUrl = await browser.getCurrentUrl(); const urlPieces = currentUrl.match(/(.*)?_g=(.*)&_a=(.*)/); const globalState = urlPieces[2]; diff --git a/test/functional/apps/management/_scripted_fields.js b/test/functional/apps/management/_scripted_fields.js index 94e38402deebe..7a21e5171595f 100644 --- a/test/functional/apps/management/_scripted_fields.js +++ b/test/functional/apps/management/_scripted_fields.js @@ -124,8 +124,8 @@ export default function ({ getService, getPageObjects }) { }); it('should see scripted field value in Discover', async function () { - const fromTime = '2015-09-17 06:31:44.000'; - const toTime = '2015-09-18 18:31:44.000'; + const fromTime = 'Sep 17, 2015 @ 06:31:44.000'; + const toTime = 'Sep 18, 2015 @ 18:31:44.000'; await PageObjects.common.navigateToApp('discover'); await PageObjects.timePicker.setAbsoluteRange(fromTime, toTime); @@ -186,8 +186,8 @@ export default function ({ getService, getPageObjects }) { }); it('should see scripted field value in Discover', async function () { - const fromTime = '2015-09-17 06:31:44.000'; - const toTime = '2015-09-18 18:31:44.000'; + const fromTime = 'Sep 17, 2015 @ 06:31:44.000'; + const toTime = 'Sep 18, 2015 @ 18:31:44.000'; await PageObjects.common.navigateToApp('discover'); await PageObjects.timePicker.setAbsoluteRange(fromTime, toTime); @@ -246,8 +246,8 @@ export default function ({ getService, getPageObjects }) { }); it('should see scripted field value in Discover', async function () { - const fromTime = '2015-09-17 06:31:44.000'; - const toTime = '2015-09-18 18:31:44.000'; + const fromTime = 'Sep 17, 2015 @ 06:31:44.000'; + const toTime = 'Sep 18, 2015 @ 18:31:44.000'; await PageObjects.common.navigateToApp('discover'); await PageObjects.timePicker.setAbsoluteRange(fromTime, toTime); @@ -307,8 +307,8 @@ export default function ({ getService, getPageObjects }) { }); it('should see scripted field value in Discover', async function () { - const fromTime = '2015-09-17 19:22:00.000'; - const toTime = '2015-09-18 07:00:00.000'; + const fromTime = 'Sep 17, 2015 @ 19:22:00.000'; + const toTime = 'Sep 18, 2015 @ 07:00:00.000'; await PageObjects.common.navigateToApp('discover'); await PageObjects.timePicker.setAbsoluteRange(fromTime, toTime); @@ -326,7 +326,7 @@ export default function ({ getService, getPageObjects }) { it('should filter by scripted field value in Discover', async function () { await PageObjects.discover.clickFieldListItem(scriptedPainlessFieldName2); - await log.debug('filter by "2015-09-17 23:00" in the expanded scripted field list'); + await log.debug('filter by "Sep 17, 2015 @ 23:00" in the expanded scripted field list'); await PageObjects.discover.clickFieldListPlusFilter(scriptedPainlessFieldName2, '2015-09-17 23:00'); await PageObjects.header.waitUntilLoadingHasFinished(); diff --git a/test/functional/apps/timelion/_expression_typeahead.js b/test/functional/apps/timelion/_expression_typeahead.js index 7cc0740823f3c..55297c6810497 100644 --- a/test/functional/apps/timelion/_expression_typeahead.js +++ b/test/functional/apps/timelion/_expression_typeahead.js @@ -24,11 +24,9 @@ export default function ({ getPageObjects }) { describe('expression typeahead', () => { before(async () => { - const fromTime = '2015-09-19 06:31:44.000'; - const toTime = '2015-09-23 18:31:44.000'; await PageObjects.timelion.initTests(); - await PageObjects.timePicker.setAbsoluteRange(fromTime, toTime); + await PageObjects.timePicker.setDefaultAbsoluteRange(); }); it('should display function suggestions filtered by function name', async () => { diff --git a/test/functional/apps/visualize/_area_chart.js b/test/functional/apps/visualize/_area_chart.js index 963b7f25bc1c9..c6b33886a2456 100644 --- a/test/functional/apps/visualize/_area_chart.js +++ b/test/functional/apps/visualize/_area_chart.js @@ -30,8 +30,6 @@ export default function ({ getService, getPageObjects }) { const vizName1 = 'Visualization AreaChart Name Test'; const initAreaChart = async () => { - const fromTime = '2015-09-19 06:31:44.000'; - const toTime = '2015-09-23 18:31:44.000'; log.debug('navigateToApp visualize'); await PageObjects.visualize.navigateToNewVisualization(); @@ -39,7 +37,7 @@ export default function ({ getService, getPageObjects }) { await PageObjects.visualize.clickAreaChart(); log.debug('clickNewSearch'); await PageObjects.visualize.clickNewSearch(); - await PageObjects.timePicker.setAbsoluteRange(fromTime, toTime); + await PageObjects.timePicker.setDefaultAbsoluteRange(); log.debug('Click X-axis'); await PageObjects.visualize.clickBucket('X-axis'); log.debug('Click Date Histogram'); @@ -327,8 +325,8 @@ export default function ({ getService, getPageObjects }) { }); describe('date histogram with long time range', () => { // that dataset spans from Oct 26, 2013 @ 06:10:17.855 to Apr 18, 2019 @ 11:38:12.790 - const fromTime = '2013-01-01 00:00:00.000'; - const toTime = '2020-01-01 00:00:00.000'; + const fromTime = 'Jan 1, 2013 @ 00:00:00.000'; + const toTime = 'Jan 1, 2020 @ 00:00:00.000'; it('should render a yearly area with 12 svg paths', async () => { log.debug('navigateToApp visualize'); await PageObjects.visualize.navigateToNewVisualization(); diff --git a/test/functional/apps/visualize/_data_table.js b/test/functional/apps/visualize/_data_table.js index b540c1e949fbc..51c0984c89fed 100644 --- a/test/functional/apps/visualize/_data_table.js +++ b/test/functional/apps/visualize/_data_table.js @@ -26,9 +26,6 @@ export default function ({ getService, getPageObjects }) { const filterBar = getService('filterBar'); const PageObjects = getPageObjects(['common', 'visualize', 'header', 'timePicker']); - const fromTime = '2015-09-19 06:31:44.000'; - const toTime = '2015-09-23 18:31:44.000'; - describe('data table', function indexPatternCreation() { const vizName1 = 'Visualization DataTable'; @@ -39,7 +36,7 @@ export default function ({ getService, getPageObjects }) { await PageObjects.visualize.clickDataTable(); log.debug('clickNewSearch'); await PageObjects.visualize.clickNewSearch(); - await PageObjects.timePicker.setAbsoluteRange(fromTime, toTime); + await PageObjects.timePicker.setDefaultAbsoluteRange(); log.debug('Bucket = Split rows'); await PageObjects.visualize.clickBucket('Split rows'); log.debug('Aggregation = Histogram'); @@ -112,7 +109,7 @@ export default function ({ getService, getPageObjects }) { await PageObjects.visualize.navigateToNewVisualization(); await PageObjects.visualize.clickDataTable(); await PageObjects.visualize.clickNewSearch(); - await PageObjects.timePicker.setAbsoluteRange(fromTime, toTime); + await PageObjects.timePicker.setDefaultAbsoluteRange(); await PageObjects.visualize.clickBucket('Split rows'); await PageObjects.visualize.selectAggregation('Range'); await PageObjects.visualize.selectField('bytes'); @@ -157,7 +154,7 @@ export default function ({ getService, getPageObjects }) { await PageObjects.visualize.navigateToNewVisualization(); await PageObjects.visualize.clickDataTable(); await PageObjects.visualize.clickNewSearch(); - await PageObjects.timePicker.setAbsoluteRange(fromTime, toTime); + await PageObjects.timePicker.setDefaultAbsoluteRange(); await PageObjects.visualize.clickBucket('Metric', 'metrics'); await PageObjects.visualize.selectAggregation('Average Bucket', 'metrics'); await PageObjects.visualize.selectAggregation('Terms', 'metrics', 'buckets'); @@ -172,7 +169,7 @@ export default function ({ getService, getPageObjects }) { await PageObjects.visualize.navigateToNewVisualization(); await PageObjects.visualize.clickDataTable(); await PageObjects.visualize.clickNewSearch(); - await PageObjects.timePicker.setAbsoluteRange(fromTime, toTime); + await PageObjects.timePicker.setDefaultAbsoluteRange(); await PageObjects.visualize.clickBucket('Split rows'); await PageObjects.visualize.selectAggregation('Date Histogram'); await PageObjects.visualize.selectField('@timestamp'); @@ -191,7 +188,7 @@ export default function ({ getService, getPageObjects }) { await PageObjects.visualize.navigateToNewVisualization(); await PageObjects.visualize.clickDataTable(); await PageObjects.visualize.clickNewSearch(); - await PageObjects.timePicker.setAbsoluteRange(fromTime, toTime); + await PageObjects.timePicker.setDefaultAbsoluteRange(); await PageObjects.visualize.clickBucket('Split rows'); await PageObjects.visualize.selectAggregation('Date Histogram'); await PageObjects.visualize.selectField('@timestamp'); @@ -227,7 +224,7 @@ export default function ({ getService, getPageObjects }) { await PageObjects.visualize.navigateToNewVisualization(); await PageObjects.visualize.clickDataTable(); await PageObjects.visualize.clickNewSearch(); - await PageObjects.timePicker.setAbsoluteRange(fromTime, toTime); + await PageObjects.timePicker.setDefaultAbsoluteRange(); await PageObjects.visualize.clickMetricEditor(); await PageObjects.visualize.selectAggregation('Top Hit', 'metrics'); await PageObjects.visualize.selectField('agent.raw', 'metrics'); @@ -241,7 +238,7 @@ export default function ({ getService, getPageObjects }) { await PageObjects.visualize.navigateToNewVisualization(); await PageObjects.visualize.clickDataTable(); await PageObjects.visualize.clickNewSearch(); - await PageObjects.timePicker.setAbsoluteRange(fromTime, toTime); + await PageObjects.timePicker.setDefaultAbsoluteRange(); await PageObjects.visualize.clickBucket('Split rows'); await PageObjects.visualize.selectAggregation('Range'); await PageObjects.visualize.selectField('bytes'); @@ -259,7 +256,7 @@ export default function ({ getService, getPageObjects }) { await PageObjects.visualize.navigateToNewVisualization(); await PageObjects.visualize.clickDataTable(); await PageObjects.visualize.clickNewSearch(); - await PageObjects.timePicker.setAbsoluteRange(fromTime, toTime); + await PageObjects.timePicker.setDefaultAbsoluteRange(); await PageObjects.visualize.clickBucket('Split rows'); await PageObjects.visualize.selectAggregation('Terms'); await PageObjects.visualize.selectField('extension.raw'); @@ -297,7 +294,7 @@ export default function ({ getService, getPageObjects }) { await PageObjects.visualize.navigateToNewVisualization(); await PageObjects.visualize.clickDataTable(); await PageObjects.visualize.clickNewSearch(); - await PageObjects.timePicker.setAbsoluteRange(fromTime, toTime); + await PageObjects.timePicker.setDefaultAbsoluteRange(); await PageObjects.visualize.clickBucket('Split rows'); await PageObjects.visualize.selectAggregation('Terms'); await PageObjects.visualize.selectField('extension.raw'); @@ -392,7 +389,7 @@ export default function ({ getService, getPageObjects }) { await PageObjects.visualize.navigateToNewVisualization(); await PageObjects.visualize.clickDataTable(); await PageObjects.visualize.clickNewSearch(); - await PageObjects.timePicker.setAbsoluteRange(fromTime, toTime); + await PageObjects.timePicker.setDefaultAbsoluteRange(); await PageObjects.visualize.clickBucket('Split table'); await PageObjects.visualize.selectAggregation('Terms'); await PageObjects.visualize.selectField('extension.raw'); diff --git a/test/functional/apps/visualize/_embedding_chart.js b/test/functional/apps/visualize/_embedding_chart.js index 12bc53ec26507..fcf5e54954347 100644 --- a/test/functional/apps/visualize/_embedding_chart.js +++ b/test/functional/apps/visualize/_embedding_chart.js @@ -26,9 +26,6 @@ export default function ({ getService, getPageObjects }) { const embedding = getService('embedding'); const PageObjects = getPageObjects(['common', 'visualize', 'header', 'timePicker']); - const fromTime = '2015-09-19 06:31:44.000'; - const toTime = '2015-09-23 18:31:44.000'; - describe('embedding', () => { describe('a data table', () => { @@ -36,7 +33,7 @@ export default function ({ getService, getPageObjects }) { await PageObjects.visualize.navigateToNewVisualization(); await PageObjects.visualize.clickDataTable(); await PageObjects.visualize.clickNewSearch(); - await PageObjects.timePicker.setAbsoluteRange(fromTime, toTime); + await PageObjects.timePicker.setDefaultAbsoluteRange(); await PageObjects.visualize.clickBucket('Split rows'); await PageObjects.visualize.selectAggregation('Date Histogram'); await PageObjects.visualize.selectField('@timestamp'); diff --git a/test/functional/apps/visualize/_gauge_chart.js b/test/functional/apps/visualize/_gauge_chart.js index 0d0383ba91aa7..2125717247e9e 100644 --- a/test/functional/apps/visualize/_gauge_chart.js +++ b/test/functional/apps/visualize/_gauge_chart.js @@ -29,8 +29,6 @@ export default function ({ getService, getPageObjects }) { // FLAKY: https://github.com/elastic/kibana/issues/45089 describe('gauge chart', function indexPatternCreation() { this.tags('smoke'); - const fromTime = '2015-09-19 06:31:44.000'; - const toTime = '2015-09-23 18:31:44.000'; async function initGaugeVis() { log.debug('navigateToApp visualize'); @@ -38,7 +36,7 @@ export default function ({ getService, getPageObjects }) { log.debug('clickGauge'); await PageObjects.visualize.clickGauge(); await PageObjects.visualize.clickNewSearch(); - await PageObjects.timePicker.setAbsoluteRange(fromTime, toTime); + await PageObjects.timePicker.setDefaultAbsoluteRange(); } before(initGaugeVis); diff --git a/test/functional/apps/visualize/_heatmap_chart.js b/test/functional/apps/visualize/_heatmap_chart.js index ac48f78b5dde7..547ecdd598811 100644 --- a/test/functional/apps/visualize/_heatmap_chart.js +++ b/test/functional/apps/visualize/_heatmap_chart.js @@ -27,8 +27,6 @@ export default function ({ getService, getPageObjects }) { describe('heatmap chart', function indexPatternCreation() { this.tags('smoke'); const vizName1 = 'Visualization HeatmapChart'; - const fromTime = '2015-09-19 06:31:44.000'; - const toTime = '2015-09-23 18:31:44.000'; before(async function () { log.debug('navigateToApp visualize'); @@ -36,7 +34,7 @@ export default function ({ getService, getPageObjects }) { log.debug('clickHeatmapChart'); await PageObjects.visualize.clickHeatmapChart(); await PageObjects.visualize.clickNewSearch(); - await PageObjects.timePicker.setAbsoluteRange(fromTime, toTime); + await PageObjects.timePicker.setDefaultAbsoluteRange(); log.debug('Bucket = X-Axis'); await PageObjects.visualize.clickBucket('X-axis'); log.debug('Aggregation = Date Histogram'); diff --git a/test/functional/apps/visualize/_histogram_request_start.js b/test/functional/apps/visualize/_histogram_request_start.js index 76709e3ed968f..10b87d204d862 100644 --- a/test/functional/apps/visualize/_histogram_request_start.js +++ b/test/functional/apps/visualize/_histogram_request_start.js @@ -26,15 +26,13 @@ export default function ({ getService, getPageObjects }) { describe('histogram agg onSearchRequestStart', function () { 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.visualize.navigateToNewVisualization(); log.debug('clickDataTable'); await PageObjects.visualize.clickDataTable(); await PageObjects.visualize.clickNewSearch(); - await PageObjects.timePicker.setAbsoluteRange(fromTime, toTime); + await PageObjects.timePicker.setDefaultAbsoluteRange(); log.debug('Bucket = Split Rows'); await PageObjects.visualize.clickBucket('Split rows'); log.debug('Aggregation = Histogram'); diff --git a/test/functional/apps/visualize/_inspector.js b/test/functional/apps/visualize/_inspector.js index 3c45063a1a16d..5917216cad40f 100644 --- a/test/functional/apps/visualize/_inspector.js +++ b/test/functional/apps/visualize/_inspector.js @@ -27,14 +27,12 @@ export default function ({ getService, getPageObjects }) { describe('inspector', function describeIndexTests() { this.tags('smoke'); before(async function () { - const fromTime = '2015-09-19 06:31:44.000'; - const toTime = '2015-09-23 18:31:44.000'; await PageObjects.visualize.navigateToNewVisualization(); await PageObjects.visualize.clickVerticalBarChart(); await PageObjects.visualize.clickNewSearch(); - await PageObjects.timePicker.setAbsoluteRange(fromTime, toTime); + await PageObjects.timePicker.setDefaultAbsoluteRange(); }); describe('inspector table', function indexPatternCreation() { diff --git a/test/functional/apps/visualize/_line_chart.js b/test/functional/apps/visualize/_line_chart.js index 29116b0ca56c4..cbadb7408f985 100644 --- a/test/functional/apps/visualize/_line_chart.js +++ b/test/functional/apps/visualize/_line_chart.js @@ -30,15 +30,13 @@ export default function ({ getService, getPageObjects }) { const vizName1 = 'Visualization LineChart'; const initLineChart = 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.visualize.navigateToNewVisualization(); log.debug('clickLineChart'); await PageObjects.visualize.clickLineChart(); await PageObjects.visualize.clickNewSearch(); - await PageObjects.timePicker.setAbsoluteRange(fromTime, toTime); + await PageObjects.timePicker.setDefaultAbsoluteRange(); log.debug('Bucket = Split chart'); await PageObjects.visualize.clickBucket('Split chart'); log.debug('Aggregation = Terms'); diff --git a/test/functional/apps/visualize/_linked_saved_searches.js b/test/functional/apps/visualize/_linked_saved_searches.js index 5343873e9e0a5..4d9553b4d9262 100644 --- a/test/functional/apps/visualize/_linked_saved_searches.js +++ b/test/functional/apps/visualize/_linked_saved_searches.js @@ -25,8 +25,6 @@ export default function ({ getService, getPageObjects }) { const PageObjects = getPageObjects(['common', 'discover', 'visualize', 'header', 'timePicker']); describe('visualize app', function describeIndexTests() { - const fromTime = '2015-09-19 06:31:44.000'; - const toTime = '2015-09-23 18:31:44.000'; describe('linked saved searched', () => { @@ -45,7 +43,7 @@ export default function ({ getService, getPageObjects }) { await PageObjects.visualize.navigateToNewVisualization(); await PageObjects.visualize.clickDataTable(); await PageObjects.visualize.clickSavedSearch(savedSearchName); - await PageObjects.timePicker.setAbsoluteRange(fromTime, toTime); + await PageObjects.timePicker.setDefaultAbsoluteRange(); await retry.waitFor('wait for count to equal 9,109', async () => { const data = await PageObjects.visualize.getTableVisData(); return data.trim() === '9,109'; @@ -53,7 +51,7 @@ export default function ({ getService, getPageObjects }) { }); it('should respect the time filter when linked to a saved search', async () => { - await PageObjects.timePicker.setAbsoluteRange('2015-09-19 06:31:44.000', '2015-09-21 10:00:00.000'); + await PageObjects.timePicker.setAbsoluteRange('Sep 19, 2015 @ 06:31:44.000', 'Sep 21, 2015 @ 10:00:00.000'); await retry.waitFor('wait for count to equal 3,950', async () => { const data = await PageObjects.visualize.getTableVisData(); return data.trim() === '3,950'; diff --git a/test/functional/apps/visualize/_metric_chart.js b/test/functional/apps/visualize/_metric_chart.js index 237ee1ef50b1e..1a4f5683f65c6 100644 --- a/test/functional/apps/visualize/_metric_chart.js +++ b/test/functional/apps/visualize/_metric_chart.js @@ -27,8 +27,6 @@ export default function ({ getService, getPageObjects }) { const PageObjects = getPageObjects(['common', 'visualize', 'timePicker']); describe('metric chart', function () { - const fromTime = '2015-09-19 06:31:44.000'; - const toTime = '2015-09-23 18:31:44.000'; before(async function () { log.debug('navigateToApp visualize'); @@ -36,7 +34,7 @@ export default function ({ getService, getPageObjects }) { log.debug('clickMetric'); await PageObjects.visualize.clickMetric(); await PageObjects.visualize.clickNewSearch(); - await PageObjects.timePicker.setAbsoluteRange(fromTime, toTime); + await PageObjects.timePicker.setDefaultAbsoluteRange(); }); it('should have inspector enabled', async function () { diff --git a/test/functional/apps/visualize/_pie_chart.js b/test/functional/apps/visualize/_pie_chart.js index b9c10aaf578bf..fc040c038afd0 100644 --- a/test/functional/apps/visualize/_pie_chart.js +++ b/test/functional/apps/visualize/_pie_chart.js @@ -25,8 +25,6 @@ export default function ({ getService, getPageObjects }) { const pieChart = getService('pieChart'); const inspector = getService('inspector'); const PageObjects = getPageObjects(['common', 'visualize', 'header', 'settings', 'timePicker']); - const fromTime = '2015-09-19 06:31:44.000'; - const toTime = '2015-09-23 18:31:44.000'; describe('pie chart', function () { const vizName1 = 'Visualization PieChart'; @@ -36,7 +34,7 @@ export default function ({ getService, getPageObjects }) { log.debug('clickPieChart'); await PageObjects.visualize.clickPieChart(); await PageObjects.visualize.clickNewSearch(); - await PageObjects.timePicker.setAbsoluteRange(fromTime, toTime); + await PageObjects.timePicker.setDefaultAbsoluteRange(); log.debug('select bucket Split slices'); await PageObjects.visualize.clickBucket('Split slices'); log.debug('Click aggregation Histogram'); @@ -85,7 +83,7 @@ export default function ({ getService, getPageObjects }) { log.debug('clickPieChart'); await PageObjects.visualize.clickPieChart(); await PageObjects.visualize.clickNewSearch(); - await PageObjects.timePicker.setAbsoluteRange(fromTime, toTime); + await PageObjects.timePicker.setDefaultAbsoluteRange(); log.debug('select bucket Split slices'); await PageObjects.visualize.clickBucket('Split slices'); log.debug('Click aggregation Terms'); @@ -187,7 +185,7 @@ export default function ({ getService, getPageObjects }) { log.debug('clickPieChart'); await PageObjects.visualize.clickPieChart(); await PageObjects.visualize.clickNewSearch(); - await PageObjects.timePicker.setAbsoluteRange(fromTime, toTime); + await PageObjects.timePicker.setDefaultAbsoluteRange(); log.debug('select bucket Split slices'); await PageObjects.visualize.clickBucket('Split slices'); log.debug('Click aggregation Filters'); @@ -199,8 +197,8 @@ export default function ({ getService, getPageObjects }) { log.debug('Set the 2nd filter value'); await PageObjects.visualize.setFilterAggregationValue('geo.dest:"CN"', 1); await PageObjects.visualize.clickGo(); - const emptyFromTime = '2016-09-19 06:31:44.000'; - const emptyToTime = '2016-09-23 18:31:44.000'; + const emptyFromTime = 'Sep 19, 2016 @ 06:31:44.000'; + const emptyToTime = 'Sep 23, 2016 @ 18:31:44.000'; log.debug('Switch to a different time range from \"' + emptyFromTime + '\" to \"' + emptyToTime + '\"'); await PageObjects.timePicker.setAbsoluteRange(emptyFromTime, emptyToTime); await PageObjects.visualize.waitForVisualization(); @@ -214,8 +212,10 @@ export default function ({ getService, getPageObjects }) { log.debug('clickPieChart'); await PageObjects.visualize.clickPieChart(); await PageObjects.visualize.clickNewSearch(); - log.debug('Set absolute time range from \"' + fromTime + '\" to \"' + toTime + '\"'); - await PageObjects.timePicker.setAbsoluteRange(fromTime, toTime); + log.debug('Set absolute time range from \"' + + PageObjects.timePicker.defaultStartTime + '\" to \"' + + PageObjects.timePicker.defaultEndTime + '\"'); + await PageObjects.timePicker.setDefaultAbsoluteRange(); log.debug('select bucket Split slices'); await PageObjects.visualize.clickBucket('Split slices'); log.debug('Click aggregation Histogram'); @@ -275,7 +275,7 @@ export default function ({ getService, getPageObjects }) { log.debug('clickPieChart'); await PageObjects.visualize.clickPieChart(); await PageObjects.visualize.clickNewSearch(); - await PageObjects.timePicker.setAbsoluteRange(fromTime, toTime); + await PageObjects.timePicker.setDefaultAbsoluteRange(); log.debug('select bucket Split slices'); await PageObjects.visualize.clickBucket('Split slices'); log.debug('Click aggregation Filters'); @@ -302,7 +302,7 @@ export default function ({ getService, getPageObjects }) { await PageObjects.visualize.navigateToNewVisualization(); await PageObjects.visualize.clickPieChart(); await PageObjects.visualize.clickNewSearch(); - await PageObjects.timePicker.setAbsoluteRange(fromTime, toTime); + await PageObjects.timePicker.setDefaultAbsoluteRange(); log.debug('select bucket Split chart'); await PageObjects.visualize.clickBucket('Split chart'); await PageObjects.visualize.selectAggregation('Terms'); diff --git a/test/functional/apps/visualize/_point_series_options.js b/test/functional/apps/visualize/_point_series_options.js index d175acbd6c02e..9bbe140d22f9b 100644 --- a/test/functional/apps/visualize/_point_series_options.js +++ b/test/functional/apps/visualize/_point_series_options.js @@ -29,15 +29,13 @@ export default function ({ getService, getPageObjects }) { const inspector = getService('inspector'); async function initChart() { - const fromTime = '2015-09-19 06:31:44.000'; - const toTime = '2015-09-23 18:31:44.000'; log.debug('navigateToApp visualize'); await PageObjects.visualize.navigateToNewVisualization(); log.debug('clickLineChart'); await PageObjects.visualize.clickLineChart(); await PageObjects.visualize.clickNewSearch(); - await PageObjects.timePicker.setAbsoluteRange(fromTime, toTime); + await PageObjects.timePicker.setDefaultAbsoluteRange(); log.debug('Bucket = X-axis'); await PageObjects.visualize.clickBucket('X-axis'); log.debug('Aggregation = Date Histogram'); @@ -208,8 +206,8 @@ export default function ({ getService, getPageObjects }) { }); it('should show different labels in different timezone', async function () { - const fromTime = '2015-09-22 09:05:47.415'; - const toTime = '2015-09-22 16:08:34.554'; + const fromTime = 'Sep 22, 2015 @ 09:05:47.415'; + const toTime = 'Sep 22, 2015 @ 16:08:34.554'; // note that we're setting the absolute time range while we're in 'America/Phoenix' tz await PageObjects.timePicker.setAbsoluteRange(fromTime, toTime); await PageObjects.visualize.waitForRenderingCount(); diff --git a/test/functional/apps/visualize/_region_map.js b/test/functional/apps/visualize/_region_map.js index 11eb2e3f0ca83..e94867f903f07 100644 --- a/test/functional/apps/visualize/_region_map.js +++ b/test/functional/apps/visualize/_region_map.js @@ -23,8 +23,6 @@ import expect from '@kbn/expect'; export default function ({ getService, getPageObjects }) { describe('vector map', function () { - const fromTime = '2015-09-19 06:31:44.000'; - const toTime = '2015-09-23 18:31:44.000'; const inspector = getService('inspector'); const log = getService('log'); @@ -38,7 +36,7 @@ export default function ({ getService, getPageObjects }) { log.debug('clickRegionMap'); await PageObjects.visualize.clickRegionMap(); await PageObjects.visualize.clickNewSearch(); - await PageObjects.timePicker.setAbsoluteRange(fromTime, toTime); + await PageObjects.timePicker.setDefaultAbsoluteRange(); log.debug('Bucket = Shape field'); await PageObjects.visualize.clickBucket('Shape field'); log.debug('Aggregation = Terms'); diff --git a/test/functional/apps/visualize/_tag_cloud.js b/test/functional/apps/visualize/_tag_cloud.js index 4ed95214550c1..5b435ef29a268 100644 --- a/test/functional/apps/visualize/_tag_cloud.js +++ b/test/functional/apps/visualize/_tag_cloud.js @@ -30,8 +30,6 @@ export default function ({ getService, getPageObjects }) { describe('tag cloud chart', function () { const vizName1 = 'Visualization tagCloud'; - const fromTime = '2015-09-19 06:31:44.000'; - const toTime = '2015-09-23 18:31:44.000'; const termsField = 'machine.ram'; before(async function () { @@ -40,7 +38,7 @@ export default function ({ getService, getPageObjects }) { log.debug('clickTagCloud'); await PageObjects.visualize.clickTagCloud(); await PageObjects.visualize.clickNewSearch(); - await PageObjects.timePicker.setAbsoluteRange(fromTime, toTime); + await PageObjects.timePicker.setDefaultAbsoluteRange(); log.debug('select Tags'); await PageObjects.visualize.clickBucket('Tags'); log.debug('Click aggregation Terms'); @@ -140,7 +138,7 @@ export default function ({ getService, getPageObjects }) { await PageObjects.common.navigateToApp('visualize'); await PageObjects.visualize.loadSavedVisualization(vizName1, { navigateToVisualize: false }); await PageObjects.header.waitUntilLoadingHasFinished(); - await PageObjects.timePicker.setAbsoluteRange(fromTime, toTime); + await PageObjects.timePicker.setDefaultAbsoluteRange(); await PageObjects.visualize.waitForVisualization(); }); diff --git a/test/functional/apps/visualize/_tile_map.js b/test/functional/apps/visualize/_tile_map.js index 0e580f6a7ab3f..f25e7e649a427 100644 --- a/test/functional/apps/visualize/_tile_map.js +++ b/test/functional/apps/visualize/_tile_map.js @@ -37,15 +37,12 @@ export default function ({ getService, getPageObjects }) { before(async function () { await browser.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.visualize.navigateToNewVisualization(); log.debug('clickTileMap'); await PageObjects.visualize.clickTileMap(); await PageObjects.visualize.clickNewSearch(); - await PageObjects.timePicker.setAbsoluteRange(fromTime, toTime); + await PageObjects.timePicker.setDefaultAbsoluteRange(); //do not configure aggs }); @@ -62,15 +59,12 @@ export default function ({ getService, getPageObjects }) { before(async function () { await browser.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.visualize.navigateToNewVisualization(); log.debug('clickTileMap'); await PageObjects.visualize.clickTileMap(); await PageObjects.visualize.clickNewSearch(); - await PageObjects.timePicker.setAbsoluteRange(fromTime, toTime); + await PageObjects.timePicker.setDefaultAbsoluteRange(); log.debug('select bucket Geo Coordinates'); await PageObjects.visualize.clickBucket('Geo coordinates'); log.debug('Click aggregation Geohash'); diff --git a/test/functional/apps/visualize/_tsvb_chart.ts b/test/functional/apps/visualize/_tsvb_chart.ts index d4896d0a0fd71..dc4b9a786eaa4 100644 --- a/test/functional/apps/visualize/_tsvb_chart.ts +++ b/test/functional/apps/visualize/_tsvb_chart.ts @@ -121,8 +121,8 @@ export default function({ getService, getPageObjects }: FtrProviderContext) { const value = await PageObjects.visualBuilder.getMetricValue(); expect(value).to.eql('156'); await PageObjects.visualBuilder.clickPanelOptions('metric'); - const fromTime = '2018-10-22 00:00:00.000'; - const toTime = '2018-10-28 23:59:59.999'; + const fromTime = 'Oct 22, 2018 @ 00:00:00.000'; + const toTime = 'Oct 28, 2018 @ 23:59:59.999'; await PageObjects.timePicker.setAbsoluteRange(fromTime, toTime); await PageObjects.visualBuilder.setIndexPatternValue('kibana_sample_data_flights'); await PageObjects.visualBuilder.selectIndexPatternTimeField('timestamp'); diff --git a/test/functional/apps/visualize/_tsvb_markdown.ts b/test/functional/apps/visualize/_tsvb_markdown.ts index f7b8415583a39..b7307ac9c6cab 100644 --- a/test/functional/apps/visualize/_tsvb_markdown.ts +++ b/test/functional/apps/visualize/_tsvb_markdown.ts @@ -43,7 +43,10 @@ export default function({ getPageObjects, getService }: FtrProviderContext) { before(async () => { await visualBuilder.resetPage(); await visualBuilder.clickMarkdown(); - await timePicker.setAbsoluteRange('2015-09-22 06:00:00.000', '2015-09-22 11:00:00.000'); + await timePicker.setAbsoluteRange( + 'Sep 22, 2015 @ 06:00:00.000', + 'Sep 22, 2015 @ 11:00:00.000' + ); }); it('should render subtabs and table variables markdown components', async () => { diff --git a/test/functional/apps/visualize/_tsvb_table.ts b/test/functional/apps/visualize/_tsvb_table.ts index 0b3541d798950..c096c28f7b804 100644 --- a/test/functional/apps/visualize/_tsvb_table.ts +++ b/test/functional/apps/visualize/_tsvb_table.ts @@ -27,7 +27,7 @@ export default function({ getPageObjects }: FtrProviderContext) { describe('visual builder', function describeIndexTests() { describe('table', () => { beforeEach(async () => { - await visualBuilder.resetPage('2015-09-22 06:00:00.000', '2015-09-22 11:00:00.000'); + await visualBuilder.resetPage('Sep 22, 2015 @ 06:00:00.000', 'Sep 22, 2015 @ 11:00:00.000'); await visualBuilder.clickTable(); await visualBuilder.checkTableTabIsPresent(); diff --git a/test/functional/apps/visualize/_vega_chart.js b/test/functional/apps/visualize/_vega_chart.js index 186318ebe6325..f4fb9f13d83bd 100644 --- a/test/functional/apps/visualize/_vega_chart.js +++ b/test/functional/apps/visualize/_vega_chart.js @@ -25,9 +25,6 @@ export default function ({ getService, getPageObjects }) { const inspector = getService('inspector'); const log = getService('log'); - const fromTime = '2015-09-19 06:31:44.000'; - const toTime = '2015-09-23 18:31:44.000'; - describe('visualize app', () => { before(async () => { log.debug('navigateToApp visualize'); @@ -64,7 +61,7 @@ export default function ({ getService, getPageObjects }) { describe('with filters', () => { before(async () => { log.debug('setAbsoluteRange'); - await PageObjects.timePicker.setAbsoluteRange(fromTime, toTime); + await PageObjects.timePicker.setDefaultAbsoluteRange(); }); afterEach(async () => { diff --git a/test/functional/apps/visualize/_vertical_bar_chart.js b/test/functional/apps/visualize/_vertical_bar_chart.js index 3a704ab0a2026..fb08cfa898237 100644 --- a/test/functional/apps/visualize/_vertical_bar_chart.js +++ b/test/functional/apps/visualize/_vertical_bar_chart.js @@ -28,8 +28,6 @@ export default function ({ getService, getPageObjects }) { // FLAKY: https://github.com/elastic/kibana/issues/22322 describe('vertical bar chart', function () { - const fromTime = '2015-09-19 06:31:44.000'; - const toTime = '2015-09-23 18:31:44.000'; const vizName1 = 'Visualization VerticalBarChart'; const initBarChart = async () => { @@ -38,7 +36,7 @@ export default function ({ getService, getPageObjects }) { log.debug('clickVerticalBarChart'); await PageObjects.visualize.clickVerticalBarChart(); await PageObjects.visualize.clickNewSearch(); - await PageObjects.timePicker.setAbsoluteRange(fromTime, toTime); + await PageObjects.timePicker.setDefaultAbsoluteRange(); log.debug('Bucket = X-Axis'); await PageObjects.visualize.clickBucket('X-axis'); log.debug('Aggregation = Date Histogram'); @@ -110,8 +108,8 @@ export default function ({ getService, getPageObjects }) { }); it('should have `drop partial buckets` option', async () => { - const fromTime = '2015-09-20 06:31:44.000'; - const toTime = '2015-09-22 18:31:44.000'; + const fromTime = 'Sep 20, 2015 @ 06:31:44.000'; + const toTime = 'Sep 22, 2015 @ 18:31:44.000'; await PageObjects.timePicker.setAbsoluteRange(fromTime, toTime); diff --git a/test/functional/apps/visualize/input_control_vis/input_control_options.js b/test/functional/apps/visualize/input_control_vis/input_control_options.js index 4088ab6193a59..ef58f0da4c8f4 100644 --- a/test/functional/apps/visualize/input_control_vis/input_control_options.js +++ b/test/functional/apps/visualize/input_control_vis/input_control_options.js @@ -35,7 +35,7 @@ export default function ({ getService, getPageObjects }) { await PageObjects.visualize.navigateToNewVisualization(); await PageObjects.visualize.clickInputControlVis(); // set time range to time with no documents - input controls do not use time filter be default - await PageObjects.timePicker.setAbsoluteRange('2017-01-01 00:00:00.000', '2017-01-02 00:00:00.000'); + await PageObjects.timePicker.setAbsoluteRange('Jan 1, 2017 @ 00:00:00.000', 'Jan 1, 2017 @ 00:00:00.000'); await PageObjects.visualize.clickVisEditorTab('controls'); await PageObjects.visualize.addInputControl(); await comboBox.set('indexPatternSelect-0', 'logstash- '); @@ -176,7 +176,7 @@ export default function ({ getService, getPageObjects }) { }); it('should re-create control when global time filter is updated', async () => { - await PageObjects.timePicker.setAbsoluteRange('2015-01-01 00:00:00.000', '2016-01-01 00:00:00.000'); + await PageObjects.timePicker.setAbsoluteRange('Jan 1, 2015 @ 00:00:00.000', 'Jan 1, 2016 @ 00:00:00.000'); // Expect control to have values for selected time filter const menu = await comboBox.getOptionsList('listControlSelect0'); diff --git a/test/functional/page_objects/dashboard_page.js b/test/functional/page_objects/dashboard_page.js index 2460422722835..49e6bd02d681f 100644 --- a/test/functional/page_objects/dashboard_page.js +++ b/test/functional/page_objects/dashboard_page.js @@ -527,20 +527,18 @@ export function DashboardPageProvider({ getService, getPageObjects }) { } async setTimepickerInHistoricalDataRange() { - const fromTime = '2015-09-19 06:31:44.000'; - const toTime = '2015-09-23 18:31:44.000'; - await PageObjects.timePicker.setAbsoluteRange(fromTime, toTime); + await PageObjects.timePicker.setDefaultAbsoluteRange(); } async setTimepickerInDataRange() { - const fromTime = '2018-01-01 00:00:00.000'; - const toTime = '2018-04-13 00:00:00.000'; + const fromTime = 'Jan 1, 2018 @ 00:00:00.000'; + const toTime = 'Apr 13, 2018 @ 00:00:00.000'; await PageObjects.timePicker.setAbsoluteRange(fromTime, toTime); } async setTimepickerInLogstashDataRange() { - const fromTime = '2018-04-09 00:00:00.000'; - const toTime = '2018-04-13 00:00:00.000'; + const fromTime = 'Apr 9, 2018 @ 00:00:00.000'; + const toTime = 'Apr 13, 2018 @ 00:00:00.000'; await PageObjects.timePicker.setAbsoluteRange(fromTime, toTime); } diff --git a/test/functional/page_objects/time_picker.js b/test/functional/page_objects/time_picker.js index 2b4147908559a..75628c9c452c7 100644 --- a/test/functional/page_objects/time_picker.js +++ b/test/functional/page_objects/time_picker.js @@ -36,8 +36,8 @@ export function TimePickerPageProvider({ getService, getPageObjects }) { formatDateToAbsoluteTimeString(date) { // toISOString returns dates in format 'YYYY-MM-DDTHH:mm:ss.sssZ' // Need to replace T with space and remove timezone - const dateString = date.toISOString().replace('T', ' '); - return dateString.substring(0, 23); + const DEFAULT_DATE_FORMAT = 'MMM D, YYYY @ HH:mm:ss.SSS'; + return moment(date).format(DEFAULT_DATE_FORMAT); } async getTimePickerPanel() { @@ -74,8 +74,8 @@ export function TimePickerPageProvider({ getService, getPageObjects }) { } /** - * @param {String} fromTime YYYY-MM-DD HH:mm:ss.SSS - * @param {String} fromTime YYYY-MM-DD HH:mm:ss.SSS + * @param {String} fromTime MMM D, YYYY @ HH:mm:ss.SSS + * @param {String} toTime MMM D, YYYY @ HH:mm:ss.SSS */ async setAbsoluteRange(fromTime, toTime) { log.debug(`Setting absolute range to ${fromTime} to ${toTime}`); @@ -112,6 +112,13 @@ export function TimePickerPageProvider({ getService, getPageObjects }) { await PageObjects.header.awaitGlobalLoadingIndicatorHidden(); } + get defaultStartTime() { return 'Sep 19, 2015 @ 06:31:44.000'; } + get defaultEndTime() { return 'Sep 23, 2015 @ 18:31:44.000'; } + + async setDefaultAbsoluteRange() { + await this.setAbsoluteRange(this.defaultStartTime, this.defaultEndTime); + } + async isQuickSelectMenuOpen() { return await testSubjects.exists('superDatePickerQuickMenu'); } @@ -214,7 +221,7 @@ export function TimePickerPageProvider({ getService, getPageObjects }) { } async getTimeDurationInHours() { - const DEFAULT_DATE_FORMAT = 'YYYY-MM-DD HH:mm:ss.SSS'; + const DEFAULT_DATE_FORMAT = 'MMM D, YYYY @ HH:mm:ss.SSS'; const { start, end } = await this.getTimeConfigAsAbsoluteTimes(); const startMoment = moment(start, DEFAULT_DATE_FORMAT); diff --git a/test/functional/page_objects/visual_builder_page.ts b/test/functional/page_objects/visual_builder_page.ts index 4b65de57f12d8..97d5787350376 100644 --- a/test/functional/page_objects/visual_builder_page.ts +++ b/test/functional/page_objects/visual_builder_page.ts @@ -43,8 +43,8 @@ export function VisualBuilderPageProvider({ getService, getPageObjects }: FtrPro class VisualBuilderPage { public async resetPage( - fromTime = '2015-09-19 06:31:44.000', - toTime = '2015-09-22 18:31:44.000' + fromTime = 'Sep 19, 2015 @ 06:31:44.000', + toTime = 'Sep 22, 2015 @ 18:31:44.000' ) { await PageObjects.common.navigateToUrl('visualize', 'create?type=metrics'); log.debug('Set absolute time range from "' + fromTime + '" to "' + toTime + '"'); diff --git a/test/interpreter_functional/plugins/kbn_tp_run_pipeline/package.json b/test/interpreter_functional/plugins/kbn_tp_run_pipeline/package.json index 552c33b9e39d2..51b9a5c5f1786 100644 --- a/test/interpreter_functional/plugins/kbn_tp_run_pipeline/package.json +++ b/test/interpreter_functional/plugins/kbn_tp_run_pipeline/package.json @@ -7,8 +7,8 @@ }, "license": "Apache-2.0", "dependencies": { - "@elastic/eui": "14.9.0", + "@elastic/eui": "16.0.0", "react": "^16.12.0", - "react-dom": "^16.8.0" + "react-dom": "^16.12.0" } } diff --git a/test/interpreter_functional/plugins/kbn_tp_run_pipeline/public/app.js b/test/interpreter_functional/plugins/kbn_tp_run_pipeline/public/app.js index b0db26c0c6743..e9ab2a4169915 100644 --- a/test/interpreter_functional/plugins/kbn_tp_run_pipeline/public/app.js +++ b/test/interpreter_functional/plugins/kbn_tp_run_pipeline/public/app.js @@ -25,6 +25,7 @@ import chrome from 'ui/chrome'; import { RequestAdapter, DataAdapter } from 'ui/inspector/adapters'; import { registries } from 'plugins/interpreter/registries'; +import { npStart } from 'ui/new_platform'; // This is required so some default styles and required scripts/Angular modules are loaded, // or the timezone setting is correctly applied. @@ -37,8 +38,8 @@ import 'uiExports/visRequestHandlers'; import 'uiExports/visEditorTypes'; import 'uiExports/visualize'; import 'uiExports/savedObjectTypes'; -import 'uiExports/fieldFormats'; import 'uiExports/search'; +import 'uiExports/interpreter'; import { Main } from './components/main'; @@ -55,17 +56,6 @@ app.config(stateManagementConfigProvider => stateManagementConfigProvider.disable() ); -import { fromExpression } from '@kbn/interpreter/common'; -import { getInterpreter } from '../../../../../src/legacy/core_plugins/interpreter/public/interpreter'; - -const runPipeline = async (expression, context, handlers) => { - const ast = fromExpression(expression); - const { interpreter } = await getInterpreter(); - const pipelineResponse = await interpreter.interpretAst(ast, context, handlers); - return pipelineResponse; -}; - - function RootController($scope, $element) { const domNode = $element[0]; @@ -73,7 +63,7 @@ function RootController($scope, $element) { render(
, domNode); diff --git a/test/interpreter_functional/plugins/kbn_tp_run_pipeline/public/components/main.js b/test/interpreter_functional/plugins/kbn_tp_run_pipeline/public/components/main.js index 62ba8dd16fef4..3e19d3a4d78ec 100644 --- a/test/interpreter_functional/plugins/kbn_tp_run_pipeline/public/components/main.js +++ b/test/interpreter_functional/plugins/kbn_tp_run_pipeline/public/components/main.js @@ -24,11 +24,10 @@ import { EuiPageContent, EuiPageContentHeader, } from '@elastic/eui'; +import { first } from 'rxjs/operators'; class Main extends React.Component { - chartDiv = React.createRef(); - exprDiv = React.createRef(); constructor(props) { super(props); @@ -43,37 +42,26 @@ class Main extends React.Component { requests: new props.RequestAdapter(), data: new props.DataAdapter(), }; - return await props.runPipeline(expression, context, { + return await props.expressions.execute(expression, { inspectorAdapters: adapters, - getInitialContext: () => initialContext, - }); - }; - - const handlers = { - onDestroy: () => { return; }, + context, + searchContext: initialContext, + }).getData(); }; + let lastRenderHandler; window.renderPipelineResponse = async (context = {}) => { - return new Promise(resolve => { - if (context.type !== 'render') { - this.setState({ expression: 'Expression did not return render type!\n\n' + JSON.stringify(context) }); - return resolve(); - } - const renderer = props.registries.renderers.get(context.as); - if (!renderer) { - this.setState({ expression: 'Renderer was not found in registry!\n\n' + JSON.stringify(context) }); - return resolve(); - } - const renderCompleteHandler = () => { - resolve('render complete'); - this.chartDiv.removeEventListener('renderComplete', renderCompleteHandler); - }; - this.chartDiv.addEventListener('renderComplete', renderCompleteHandler); - renderer.render(this.chartDiv, context.value, handlers); - }); + if (lastRenderHandler) { + lastRenderHandler.destroy(); + } - }; + lastRenderHandler = props.expressions.render(this.chartDiv, context); + const renderResult = await lastRenderHandler.render$.pipe(first()).toPromise(); + if (typeof renderResult === 'object' && renderResult.type === 'error') { + return this.setState({ expression: 'Render error!\n\n' + JSON.stringify(renderResult.error) }); + } + }; } diff --git a/test/interpreter_functional/screenshots/baseline/combined_test.png b/test/interpreter_functional/screenshots/baseline/combined_test.png index 376d2b54bd08d..87f3173d56024 100644 Binary files a/test/interpreter_functional/screenshots/baseline/combined_test.png and b/test/interpreter_functional/screenshots/baseline/combined_test.png differ diff --git a/test/interpreter_functional/screenshots/baseline/final_screenshot_test.png b/test/interpreter_functional/screenshots/baseline/final_screenshot_test.png index 073952ac6c969..d860bb73521ce 100644 Binary files a/test/interpreter_functional/screenshots/baseline/final_screenshot_test.png and b/test/interpreter_functional/screenshots/baseline/final_screenshot_test.png differ diff --git a/test/interpreter_functional/screenshots/baseline/metric_all_data.png b/test/interpreter_functional/screenshots/baseline/metric_all_data.png index f62967f95a2fa..43943b1e6c46c 100644 Binary files a/test/interpreter_functional/screenshots/baseline/metric_all_data.png and b/test/interpreter_functional/screenshots/baseline/metric_all_data.png differ diff --git a/test/interpreter_functional/screenshots/baseline/metric_invalid_data.png b/test/interpreter_functional/screenshots/baseline/metric_invalid_data.png new file mode 100644 index 0000000000000..795f2f7c832f3 Binary files /dev/null and b/test/interpreter_functional/screenshots/baseline/metric_invalid_data.png differ diff --git a/test/interpreter_functional/screenshots/baseline/metric_multi_metric_data.png b/test/interpreter_functional/screenshots/baseline/metric_multi_metric_data.png index 1db494849a23d..6578f8e30415d 100644 Binary files a/test/interpreter_functional/screenshots/baseline/metric_multi_metric_data.png and b/test/interpreter_functional/screenshots/baseline/metric_multi_metric_data.png differ diff --git a/test/interpreter_functional/screenshots/baseline/metric_percentage.png b/test/interpreter_functional/screenshots/baseline/metric_percentage.png index 8e2a52bf44c1b..580889bb7deaf 100644 Binary files a/test/interpreter_functional/screenshots/baseline/metric_percentage.png and b/test/interpreter_functional/screenshots/baseline/metric_percentage.png differ diff --git a/test/interpreter_functional/screenshots/baseline/metric_single_metric_data.png b/test/interpreter_functional/screenshots/baseline/metric_single_metric_data.png index b5bd2e1dd8839..916a284433874 100644 Binary files a/test/interpreter_functional/screenshots/baseline/metric_single_metric_data.png and b/test/interpreter_functional/screenshots/baseline/metric_single_metric_data.png differ diff --git a/test/interpreter_functional/screenshots/baseline/partial_test_1.png b/test/interpreter_functional/screenshots/baseline/partial_test_1.png index f9367ffefdf13..9815f25d00b16 100644 Binary files a/test/interpreter_functional/screenshots/baseline/partial_test_1.png and b/test/interpreter_functional/screenshots/baseline/partial_test_1.png differ diff --git a/test/interpreter_functional/screenshots/baseline/partial_test_2.png b/test/interpreter_functional/screenshots/baseline/partial_test_2.png index 376d2b54bd08d..87f3173d56024 100644 Binary files a/test/interpreter_functional/screenshots/baseline/partial_test_2.png and b/test/interpreter_functional/screenshots/baseline/partial_test_2.png differ diff --git a/test/interpreter_functional/screenshots/baseline/tagcloud_all_data.png b/test/interpreter_functional/screenshots/baseline/tagcloud_all_data.png index 36c7d6c5e1013..03ffc7ac7b1a5 100644 Binary files a/test/interpreter_functional/screenshots/baseline/tagcloud_all_data.png and b/test/interpreter_functional/screenshots/baseline/tagcloud_all_data.png differ diff --git a/test/interpreter_functional/screenshots/baseline/tagcloud_fontsize.png b/test/interpreter_functional/screenshots/baseline/tagcloud_fontsize.png index 7b8288a8bf908..3a7315df405df 100644 Binary files a/test/interpreter_functional/screenshots/baseline/tagcloud_fontsize.png and b/test/interpreter_functional/screenshots/baseline/tagcloud_fontsize.png differ diff --git a/test/interpreter_functional/screenshots/baseline/tagcloud_invalid_data.png b/test/interpreter_functional/screenshots/baseline/tagcloud_invalid_data.png index e40c1840d29ca..795f2f7c832f3 100644 Binary files a/test/interpreter_functional/screenshots/baseline/tagcloud_invalid_data.png and b/test/interpreter_functional/screenshots/baseline/tagcloud_invalid_data.png differ diff --git a/test/interpreter_functional/screenshots/baseline/tagcloud_metric_data.png b/test/interpreter_functional/screenshots/baseline/tagcloud_metric_data.png index 7cca731c267ba..5cdce69296673 100644 Binary files a/test/interpreter_functional/screenshots/baseline/tagcloud_metric_data.png and b/test/interpreter_functional/screenshots/baseline/tagcloud_metric_data.png differ diff --git a/test/interpreter_functional/screenshots/baseline/tagcloud_options.png b/test/interpreter_functional/screenshots/baseline/tagcloud_options.png index af5eaba74b219..394b5585097a2 100644 Binary files a/test/interpreter_functional/screenshots/baseline/tagcloud_options.png and b/test/interpreter_functional/screenshots/baseline/tagcloud_options.png differ diff --git a/test/interpreter_functional/snapshots/baseline/combined_test0.json b/test/interpreter_functional/snapshots/baseline/combined_test0.json index 83aea519a9771..2af0407f0d521 100644 --- a/test/interpreter_functional/snapshots/baseline/combined_test0.json +++ b/test/interpreter_functional/snapshots/baseline/combined_test0.json @@ -1 +1 @@ -{"type":"kibana_context"} \ No newline at end of file +{"filters":null,"query":null,"timeRange":null,"type":"kibana_context"} \ No newline at end of file diff --git a/test/interpreter_functional/snapshots/baseline/combined_test1.json b/test/interpreter_functional/snapshots/baseline/combined_test1.json index 7c8ad34057894..8f00d72df8ab3 100644 --- a/test/interpreter_functional/snapshots/baseline/combined_test1.json +++ b/test/interpreter_functional/snapshots/baseline/combined_test1.json @@ -1 +1 @@ -{"filters":[],"query":[],"type":"kibana_context"} \ No newline at end of file +{"filters":[],"query":[],"timeRange":null,"type":"kibana_context"} \ No newline at end of file diff --git a/test/interpreter_functional/snapshots/baseline/combined_test3.json b/test/interpreter_functional/snapshots/baseline/combined_test3.json index 2a2d8dff98b8f..310377eadd165 100644 --- a/test/interpreter_functional/snapshots/baseline/combined_test3.json +++ b/test/interpreter_functional/snapshots/baseline/combined_test3.json @@ -1 +1 @@ -{"as":"visualization","type":"render","value":{"params":{"listenOnChange":true},"visConfig":{"dimensions":{"bucket":{"accessor":0,"format":{"id":"string","params":{}},"type":"vis_dimension"},"metrics":[{"accessor":1,"format":{"id":"number","params":{}},"type":"vis_dimension"}]},"metric":{"colorSchema":"Green to Red","invertColors":false,"labels":{"show":true},"metricColorMode":"None","percentageMode":false,"style":{"bgColor":false,"bgFill":"#000","fontSize":60,"labelColor":false,"subText":""},"useRanges":false}},"visData":{"columns":[{"id":"col-0-2","name":"response.raw: Descending"},{"id":"col-1-1","name":"Count"}],"rows":[{"col-0-2":"200","col-1-1":12891},{"col-0-2":"404","col-1-1":696},{"col-0-2":"503","col-1-1":417}],"type":"kibana_datatable"},"visType":"metric"}} \ No newline at end of file +{"as":"visualization","type":"render","value":{"params":{"listenOnChange":true},"visConfig":{"dimensions":{"bucket":{"accessor":0,"format":{"id":"string","params":{}},"type":"vis_dimension"},"metrics":[{"accessor":1,"format":{"id":"number","params":{}},"type":"vis_dimension"}]},"metric":{"colorSchema":"Green to Red","colorsRange":[{"from":0,"to":10000,"type":"range"}],"invertColors":false,"labels":{"show":true},"metricColorMode":"None","percentageMode":false,"style":{"bgColor":false,"bgFill":"#000","fontSize":60,"labelColor":false,"subText":""},"useRanges":false}},"visData":{"columns":[{"id":"col-0-2","name":"response.raw: Descending"},{"id":"col-1-1","name":"Count"}],"rows":[{"col-0-2":"200","col-1-1":12891},{"col-0-2":"404","col-1-1":696},{"col-0-2":"503","col-1-1":417}],"type":"kibana_datatable"},"visType":"metric"}} \ No newline at end of file diff --git a/test/interpreter_functional/snapshots/baseline/final_output_test.json b/test/interpreter_functional/snapshots/baseline/final_output_test.json index 2a2d8dff98b8f..310377eadd165 100644 --- a/test/interpreter_functional/snapshots/baseline/final_output_test.json +++ b/test/interpreter_functional/snapshots/baseline/final_output_test.json @@ -1 +1 @@ -{"as":"visualization","type":"render","value":{"params":{"listenOnChange":true},"visConfig":{"dimensions":{"bucket":{"accessor":0,"format":{"id":"string","params":{}},"type":"vis_dimension"},"metrics":[{"accessor":1,"format":{"id":"number","params":{}},"type":"vis_dimension"}]},"metric":{"colorSchema":"Green to Red","invertColors":false,"labels":{"show":true},"metricColorMode":"None","percentageMode":false,"style":{"bgColor":false,"bgFill":"#000","fontSize":60,"labelColor":false,"subText":""},"useRanges":false}},"visData":{"columns":[{"id":"col-0-2","name":"response.raw: Descending"},{"id":"col-1-1","name":"Count"}],"rows":[{"col-0-2":"200","col-1-1":12891},{"col-0-2":"404","col-1-1":696},{"col-0-2":"503","col-1-1":417}],"type":"kibana_datatable"},"visType":"metric"}} \ No newline at end of file +{"as":"visualization","type":"render","value":{"params":{"listenOnChange":true},"visConfig":{"dimensions":{"bucket":{"accessor":0,"format":{"id":"string","params":{}},"type":"vis_dimension"},"metrics":[{"accessor":1,"format":{"id":"number","params":{}},"type":"vis_dimension"}]},"metric":{"colorSchema":"Green to Red","colorsRange":[{"from":0,"to":10000,"type":"range"}],"invertColors":false,"labels":{"show":true},"metricColorMode":"None","percentageMode":false,"style":{"bgColor":false,"bgFill":"#000","fontSize":60,"labelColor":false,"subText":""},"useRanges":false}},"visData":{"columns":[{"id":"col-0-2","name":"response.raw: Descending"},{"id":"col-1-1","name":"Count"}],"rows":[{"col-0-2":"200","col-1-1":12891},{"col-0-2":"404","col-1-1":696},{"col-0-2":"503","col-1-1":417}],"type":"kibana_datatable"},"visType":"metric"}} \ No newline at end of file diff --git a/test/interpreter_functional/snapshots/baseline/metric_all_data.json b/test/interpreter_functional/snapshots/baseline/metric_all_data.json index ebed9f8e47435..26f111e9edcf9 100644 --- a/test/interpreter_functional/snapshots/baseline/metric_all_data.json +++ b/test/interpreter_functional/snapshots/baseline/metric_all_data.json @@ -1 +1 @@ -{"as":"visualization","type":"render","value":{"params":{"listenOnChange":true},"visConfig":{"dimensions":{"bucket":{"accessor":2,"format":{"id":"string","params":{}},"type":"vis_dimension"},"metrics":[{"accessor":0,"format":{"id":"string","params":{}},"type":"vis_dimension"}]},"metric":{"colorSchema":"Green to Red","invertColors":false,"labels":{"show":true},"metricColorMode":"None","percentageMode":false,"style":{"bgColor":false,"bgFill":"#000","fontSize":60,"labelColor":false,"subText":""},"useRanges":false}},"visData":{"columns":[{"id":"col-0-2","name":"response.raw: Descending"},{"id":"col-1-1","name":"Count"},{"id":"col-2-1","name":"Max bytes"}],"rows":[{"col-0-2":"200","col-1-1":12891,"col-2-1":19986},{"col-0-2":"404","col-1-1":696,"col-2-1":19881},{"col-0-2":"503","col-1-1":417,"col-2-1":0}],"type":"kibana_datatable"},"visType":"metric"}} \ No newline at end of file +{"as":"visualization","type":"render","value":{"params":{"listenOnChange":true},"visConfig":{"dimensions":{"bucket":{"accessor":2,"format":{"id":"string","params":{}},"type":"vis_dimension"},"metrics":[{"accessor":0,"format":{"id":"string","params":{}},"type":"vis_dimension"}]},"metric":{"colorSchema":"Green to Red","colorsRange":[{"from":0,"to":10000,"type":"range"}],"invertColors":false,"labels":{"show":true},"metricColorMode":"None","percentageMode":false,"style":{"bgColor":false,"bgFill":"#000","fontSize":60,"labelColor":false,"subText":""},"useRanges":false}},"visData":{"columns":[{"id":"col-0-2","name":"response.raw: Descending"},{"id":"col-1-1","name":"Count"},{"id":"col-2-1","name":"Max bytes"}],"rows":[{"col-0-2":"200","col-1-1":12891,"col-2-1":19986},{"col-0-2":"404","col-1-1":696,"col-2-1":19881},{"col-0-2":"503","col-1-1":417,"col-2-1":0}],"type":"kibana_datatable"},"visType":"metric"}} \ No newline at end of file diff --git a/test/interpreter_functional/snapshots/baseline/metric_invalid_data.json b/test/interpreter_functional/snapshots/baseline/metric_invalid_data.json new file mode 100644 index 0000000000000..fa5892190e5ba --- /dev/null +++ b/test/interpreter_functional/snapshots/baseline/metric_invalid_data.json @@ -0,0 +1 @@ +"[metricVis] > [visdimension] > Can not cast 'null' to any of 'kibana_datatable'" \ No newline at end of file diff --git a/test/interpreter_functional/snapshots/baseline/metric_multi_metric_data.json b/test/interpreter_functional/snapshots/baseline/metric_multi_metric_data.json index ac4860c6735bf..7f64f97845191 100644 --- a/test/interpreter_functional/snapshots/baseline/metric_multi_metric_data.json +++ b/test/interpreter_functional/snapshots/baseline/metric_multi_metric_data.json @@ -1 +1 @@ -{"as":"visualization","type":"render","value":{"params":{"listenOnChange":true},"visConfig":{"dimensions":{"metrics":[{"accessor":0,"format":{"id":"string","params":{}},"type":"vis_dimension"},{"accessor":1,"format":{"id":"string","params":{}},"type":"vis_dimension"}]},"metric":{"colorSchema":"Green to Red","invertColors":false,"labels":{"show":true},"metricColorMode":"None","percentageMode":false,"style":{"bgColor":false,"bgFill":"#000","fontSize":60,"labelColor":false,"subText":""},"useRanges":false}},"visData":{"columns":[{"id":"col-0-2","name":"response.raw: Descending"},{"id":"col-1-1","name":"Count"},{"id":"col-2-1","name":"Max bytes"}],"rows":[{"col-0-2":"200","col-1-1":12891,"col-2-1":19986},{"col-0-2":"404","col-1-1":696,"col-2-1":19881},{"col-0-2":"503","col-1-1":417,"col-2-1":0}],"type":"kibana_datatable"},"visType":"metric"}} \ No newline at end of file +{"as":"visualization","type":"render","value":{"params":{"listenOnChange":true},"visConfig":{"dimensions":{"metrics":[{"accessor":0,"format":{"id":"string","params":{}},"type":"vis_dimension"},{"accessor":1,"format":{"id":"string","params":{}},"type":"vis_dimension"}]},"metric":{"colorSchema":"Green to Red","colorsRange":[{"from":0,"to":10000,"type":"range"}],"invertColors":false,"labels":{"show":true},"metricColorMode":"None","percentageMode":false,"style":{"bgColor":false,"bgFill":"#000","fontSize":60,"labelColor":false,"subText":""},"useRanges":false}},"visData":{"columns":[{"id":"col-0-2","name":"response.raw: Descending"},{"id":"col-1-1","name":"Count"},{"id":"col-2-1","name":"Max bytes"}],"rows":[{"col-0-2":"200","col-1-1":12891,"col-2-1":19986},{"col-0-2":"404","col-1-1":696,"col-2-1":19881},{"col-0-2":"503","col-1-1":417,"col-2-1":0}],"type":"kibana_datatable"},"visType":"metric"}} \ No newline at end of file diff --git a/test/interpreter_functional/snapshots/baseline/metric_single_metric_data.json b/test/interpreter_functional/snapshots/baseline/metric_single_metric_data.json index ae27e624df5bb..ed8b0b258fd90 100644 --- a/test/interpreter_functional/snapshots/baseline/metric_single_metric_data.json +++ b/test/interpreter_functional/snapshots/baseline/metric_single_metric_data.json @@ -1 +1 @@ -{"as":"visualization","type":"render","value":{"params":{"listenOnChange":true},"visConfig":{"dimensions":{"metrics":[{"accessor":0,"format":{"id":"string","params":{}},"type":"vis_dimension"}]},"metric":{"colorSchema":"Green to Red","invertColors":false,"labels":{"show":true},"metricColorMode":"None","percentageMode":false,"style":{"bgColor":false,"bgFill":"#000","fontSize":60,"labelColor":false,"subText":""},"useRanges":false}},"visData":{"columns":[{"id":"col-0-2","name":"response.raw: Descending"},{"id":"col-1-1","name":"Count"},{"id":"col-2-1","name":"Max bytes"}],"rows":[{"col-0-2":"200","col-1-1":12891,"col-2-1":19986},{"col-0-2":"404","col-1-1":696,"col-2-1":19881},{"col-0-2":"503","col-1-1":417,"col-2-1":0}],"type":"kibana_datatable"},"visType":"metric"}} \ No newline at end of file +{"as":"visualization","type":"render","value":{"params":{"listenOnChange":true},"visConfig":{"dimensions":{"metrics":[{"accessor":0,"format":{"id":"string","params":{}},"type":"vis_dimension"}]},"metric":{"colorSchema":"Green to Red","colorsRange":[{"from":0,"to":10000,"type":"range"}],"invertColors":false,"labels":{"show":true},"metricColorMode":"None","percentageMode":false,"style":{"bgColor":false,"bgFill":"#000","fontSize":60,"labelColor":false,"subText":""},"useRanges":false}},"visData":{"columns":[{"id":"col-0-2","name":"response.raw: Descending"},{"id":"col-1-1","name":"Count"},{"id":"col-2-1","name":"Max bytes"}],"rows":[{"col-0-2":"200","col-1-1":12891,"col-2-1":19986},{"col-0-2":"404","col-1-1":696,"col-2-1":19881},{"col-0-2":"503","col-1-1":417,"col-2-1":0}],"type":"kibana_datatable"},"visType":"metric"}} \ No newline at end of file diff --git a/test/interpreter_functional/snapshots/baseline/partial_test_1.json b/test/interpreter_functional/snapshots/baseline/partial_test_1.json new file mode 100644 index 0000000000000..8a349aa5df060 --- /dev/null +++ b/test/interpreter_functional/snapshots/baseline/partial_test_1.json @@ -0,0 +1 @@ +{"as":"visualization","type":"render","value":{"params":{"listenOnChange":true},"visConfig":{"bucket":{"accessor":0,"format":{"id":"string","params":{}},"type":"vis_dimension"},"maxFontSize":72,"metric":{"accessor":1,"format":{"id":"number","params":{}},"type":"vis_dimension"},"minFontSize":18,"orientation":"single","scale":"linear","showLabel":true},"visData":{"columns":[{"id":"col-0-2","name":"response.raw: Descending"},{"id":"col-1-1","name":"Count"}],"rows":[{"col-0-2":"200","col-1-1":12891},{"col-0-2":"404","col-1-1":696},{"col-0-2":"503","col-1-1":417}],"type":"kibana_datatable"},"visType":"tagcloud"}} \ No newline at end of file diff --git a/test/interpreter_functional/snapshots/baseline/partial_test_2.json b/test/interpreter_functional/snapshots/baseline/partial_test_2.json new file mode 100644 index 0000000000000..310377eadd165 --- /dev/null +++ b/test/interpreter_functional/snapshots/baseline/partial_test_2.json @@ -0,0 +1 @@ +{"as":"visualization","type":"render","value":{"params":{"listenOnChange":true},"visConfig":{"dimensions":{"bucket":{"accessor":0,"format":{"id":"string","params":{}},"type":"vis_dimension"},"metrics":[{"accessor":1,"format":{"id":"number","params":{}},"type":"vis_dimension"}]},"metric":{"colorSchema":"Green to Red","colorsRange":[{"from":0,"to":10000,"type":"range"}],"invertColors":false,"labels":{"show":true},"metricColorMode":"None","percentageMode":false,"style":{"bgColor":false,"bgFill":"#000","fontSize":60,"labelColor":false,"subText":""},"useRanges":false}},"visData":{"columns":[{"id":"col-0-2","name":"response.raw: Descending"},{"id":"col-1-1","name":"Count"}],"rows":[{"col-0-2":"200","col-1-1":12891},{"col-0-2":"404","col-1-1":696},{"col-0-2":"503","col-1-1":417}],"type":"kibana_datatable"},"visType":"metric"}} \ No newline at end of file diff --git a/test/interpreter_functional/snapshots/baseline/partial_test_3.json b/test/interpreter_functional/snapshots/baseline/partial_test_3.json new file mode 100644 index 0000000000000..c1e429508c37f --- /dev/null +++ b/test/interpreter_functional/snapshots/baseline/partial_test_3.json @@ -0,0 +1 @@ +{"as":"visualization","type":"render","value":{"params":{"listenOnChange":true},"visConfig":{"bucket":{"accessor":0},"metric":{"accessor":1,"format":{"id":"number"}}},"visData":{"columns":[{"id":"col-0-2","name":"response.raw: Descending"},{"id":"col-1-1","name":"Count"}],"rows":[{"col-0-2":"200","col-1-1":12891},{"col-0-2":"404","col-1-1":696},{"col-0-2":"503","col-1-1":417}],"type":"kibana_datatable"},"visType":"region_map"}} \ No newline at end of file diff --git a/test/interpreter_functional/snapshots/baseline/step_output_test0.json b/test/interpreter_functional/snapshots/baseline/step_output_test0.json index 83aea519a9771..2af0407f0d521 100644 --- a/test/interpreter_functional/snapshots/baseline/step_output_test0.json +++ b/test/interpreter_functional/snapshots/baseline/step_output_test0.json @@ -1 +1 @@ -{"type":"kibana_context"} \ No newline at end of file +{"filters":null,"query":null,"timeRange":null,"type":"kibana_context"} \ No newline at end of file diff --git a/test/interpreter_functional/snapshots/baseline/step_output_test1.json b/test/interpreter_functional/snapshots/baseline/step_output_test1.json index 7c8ad34057894..8f00d72df8ab3 100644 --- a/test/interpreter_functional/snapshots/baseline/step_output_test1.json +++ b/test/interpreter_functional/snapshots/baseline/step_output_test1.json @@ -1 +1 @@ -{"filters":[],"query":[],"type":"kibana_context"} \ No newline at end of file +{"filters":[],"query":[],"timeRange":null,"type":"kibana_context"} \ No newline at end of file diff --git a/test/interpreter_functional/snapshots/baseline/step_output_test3.json b/test/interpreter_functional/snapshots/baseline/step_output_test3.json index 2a2d8dff98b8f..310377eadd165 100644 --- a/test/interpreter_functional/snapshots/baseline/step_output_test3.json +++ b/test/interpreter_functional/snapshots/baseline/step_output_test3.json @@ -1 +1 @@ -{"as":"visualization","type":"render","value":{"params":{"listenOnChange":true},"visConfig":{"dimensions":{"bucket":{"accessor":0,"format":{"id":"string","params":{}},"type":"vis_dimension"},"metrics":[{"accessor":1,"format":{"id":"number","params":{}},"type":"vis_dimension"}]},"metric":{"colorSchema":"Green to Red","invertColors":false,"labels":{"show":true},"metricColorMode":"None","percentageMode":false,"style":{"bgColor":false,"bgFill":"#000","fontSize":60,"labelColor":false,"subText":""},"useRanges":false}},"visData":{"columns":[{"id":"col-0-2","name":"response.raw: Descending"},{"id":"col-1-1","name":"Count"}],"rows":[{"col-0-2":"200","col-1-1":12891},{"col-0-2":"404","col-1-1":696},{"col-0-2":"503","col-1-1":417}],"type":"kibana_datatable"},"visType":"metric"}} \ No newline at end of file +{"as":"visualization","type":"render","value":{"params":{"listenOnChange":true},"visConfig":{"dimensions":{"bucket":{"accessor":0,"format":{"id":"string","params":{}},"type":"vis_dimension"},"metrics":[{"accessor":1,"format":{"id":"number","params":{}},"type":"vis_dimension"}]},"metric":{"colorSchema":"Green to Red","colorsRange":[{"from":0,"to":10000,"type":"range"}],"invertColors":false,"labels":{"show":true},"metricColorMode":"None","percentageMode":false,"style":{"bgColor":false,"bgFill":"#000","fontSize":60,"labelColor":false,"subText":""},"useRanges":false}},"visData":{"columns":[{"id":"col-0-2","name":"response.raw: Descending"},{"id":"col-1-1","name":"Count"}],"rows":[{"col-0-2":"200","col-1-1":12891},{"col-0-2":"404","col-1-1":696},{"col-0-2":"503","col-1-1":417}],"type":"kibana_datatable"},"visType":"metric"}} \ No newline at end of file diff --git a/test/interpreter_functional/snapshots/baseline/tagcloud_invalid_data.json b/test/interpreter_functional/snapshots/baseline/tagcloud_invalid_data.json index ae78b3321f0be..46b52a7b3eaae 100644 --- a/test/interpreter_functional/snapshots/baseline/tagcloud_invalid_data.json +++ b/test/interpreter_functional/snapshots/baseline/tagcloud_invalid_data.json @@ -1 +1 @@ -{"error":{"message":"[tagcloud] > [vis_dimension] > Objects must have a type property","stack":"Error: [vis_dimension] > Objects must have a type property\n at getType (http://localhost:5620/bundles/commons.bundle.js:15876:27)\n at cast (http://localhost:5620/bundles/commons.bundle.js:15683:46)\n at _callee3$ (http://localhost:5620/bundles/commons.bundle.js:31552:35)\n at tryCatch (webpack://%5Bname%5D/./node_modules/regenerator-runtime/runtime.js?:62:40)\n at Generator.invoke [as _invoke] (webpack://%5Bname%5D/./node_modules/regenerator-runtime/runtime.js?:288:22)\n at Generator.prototype.(anonymous function) [as next] (webpack://%5Bname%5D/./node_modules/regenerator-runtime/runtime.js?:114:21)\n at asyncGeneratorStep (http://localhost:5620/bundles/commons.bundle.js:31397:103)\n at _next (http://localhost:5620/bundles/commons.bundle.js:31399:194)\n at http://localhost:5620/bundles/commons.bundle.js:31399:364\n at new Promise ()"},"type":"error"} \ No newline at end of file +"[tagcloud] > [visdimension] > Can not cast 'null' to any of 'kibana_datatable'" \ No newline at end of file diff --git a/test/interpreter_functional/snapshots/session/combined_test0.json b/test/interpreter_functional/snapshots/session/combined_test0.json new file mode 100644 index 0000000000000..2af0407f0d521 --- /dev/null +++ b/test/interpreter_functional/snapshots/session/combined_test0.json @@ -0,0 +1 @@ +{"filters":null,"query":null,"timeRange":null,"type":"kibana_context"} \ No newline at end of file diff --git a/test/interpreter_functional/snapshots/session/combined_test1.json b/test/interpreter_functional/snapshots/session/combined_test1.json new file mode 100644 index 0000000000000..8f00d72df8ab3 --- /dev/null +++ b/test/interpreter_functional/snapshots/session/combined_test1.json @@ -0,0 +1 @@ +{"filters":[],"query":[],"timeRange":null,"type":"kibana_context"} \ No newline at end of file diff --git a/test/interpreter_functional/snapshots/session/combined_test2.json b/test/interpreter_functional/snapshots/session/combined_test2.json new file mode 100644 index 0000000000000..98c7844e41f19 --- /dev/null +++ b/test/interpreter_functional/snapshots/session/combined_test2.json @@ -0,0 +1 @@ +{"columns":[{"id":"col-0-2","name":"response.raw: Descending"},{"id":"col-1-1","name":"Count"}],"rows":[{"col-0-2":"200","col-1-1":12891},{"col-0-2":"404","col-1-1":696},{"col-0-2":"503","col-1-1":417}],"type":"kibana_datatable"} \ No newline at end of file diff --git a/test/interpreter_functional/snapshots/session/combined_test3.json b/test/interpreter_functional/snapshots/session/combined_test3.json new file mode 100644 index 0000000000000..310377eadd165 --- /dev/null +++ b/test/interpreter_functional/snapshots/session/combined_test3.json @@ -0,0 +1 @@ +{"as":"visualization","type":"render","value":{"params":{"listenOnChange":true},"visConfig":{"dimensions":{"bucket":{"accessor":0,"format":{"id":"string","params":{}},"type":"vis_dimension"},"metrics":[{"accessor":1,"format":{"id":"number","params":{}},"type":"vis_dimension"}]},"metric":{"colorSchema":"Green to Red","colorsRange":[{"from":0,"to":10000,"type":"range"}],"invertColors":false,"labels":{"show":true},"metricColorMode":"None","percentageMode":false,"style":{"bgColor":false,"bgFill":"#000","fontSize":60,"labelColor":false,"subText":""},"useRanges":false}},"visData":{"columns":[{"id":"col-0-2","name":"response.raw: Descending"},{"id":"col-1-1","name":"Count"}],"rows":[{"col-0-2":"200","col-1-1":12891},{"col-0-2":"404","col-1-1":696},{"col-0-2":"503","col-1-1":417}],"type":"kibana_datatable"},"visType":"metric"}} \ No newline at end of file diff --git a/test/interpreter_functional/snapshots/session/final_output_test.json b/test/interpreter_functional/snapshots/session/final_output_test.json new file mode 100644 index 0000000000000..310377eadd165 --- /dev/null +++ b/test/interpreter_functional/snapshots/session/final_output_test.json @@ -0,0 +1 @@ +{"as":"visualization","type":"render","value":{"params":{"listenOnChange":true},"visConfig":{"dimensions":{"bucket":{"accessor":0,"format":{"id":"string","params":{}},"type":"vis_dimension"},"metrics":[{"accessor":1,"format":{"id":"number","params":{}},"type":"vis_dimension"}]},"metric":{"colorSchema":"Green to Red","colorsRange":[{"from":0,"to":10000,"type":"range"}],"invertColors":false,"labels":{"show":true},"metricColorMode":"None","percentageMode":false,"style":{"bgColor":false,"bgFill":"#000","fontSize":60,"labelColor":false,"subText":""},"useRanges":false}},"visData":{"columns":[{"id":"col-0-2","name":"response.raw: Descending"},{"id":"col-1-1","name":"Count"}],"rows":[{"col-0-2":"200","col-1-1":12891},{"col-0-2":"404","col-1-1":696},{"col-0-2":"503","col-1-1":417}],"type":"kibana_datatable"},"visType":"metric"}} \ No newline at end of file diff --git a/test/interpreter_functional/snapshots/session/metric_all_data.json b/test/interpreter_functional/snapshots/session/metric_all_data.json new file mode 100644 index 0000000000000..26f111e9edcf9 --- /dev/null +++ b/test/interpreter_functional/snapshots/session/metric_all_data.json @@ -0,0 +1 @@ +{"as":"visualization","type":"render","value":{"params":{"listenOnChange":true},"visConfig":{"dimensions":{"bucket":{"accessor":2,"format":{"id":"string","params":{}},"type":"vis_dimension"},"metrics":[{"accessor":0,"format":{"id":"string","params":{}},"type":"vis_dimension"}]},"metric":{"colorSchema":"Green to Red","colorsRange":[{"from":0,"to":10000,"type":"range"}],"invertColors":false,"labels":{"show":true},"metricColorMode":"None","percentageMode":false,"style":{"bgColor":false,"bgFill":"#000","fontSize":60,"labelColor":false,"subText":""},"useRanges":false}},"visData":{"columns":[{"id":"col-0-2","name":"response.raw: Descending"},{"id":"col-1-1","name":"Count"},{"id":"col-2-1","name":"Max bytes"}],"rows":[{"col-0-2":"200","col-1-1":12891,"col-2-1":19986},{"col-0-2":"404","col-1-1":696,"col-2-1":19881},{"col-0-2":"503","col-1-1":417,"col-2-1":0}],"type":"kibana_datatable"},"visType":"metric"}} \ No newline at end of file diff --git a/test/interpreter_functional/snapshots/session/metric_invalid_data.json b/test/interpreter_functional/snapshots/session/metric_invalid_data.json new file mode 100644 index 0000000000000..fa5892190e5ba --- /dev/null +++ b/test/interpreter_functional/snapshots/session/metric_invalid_data.json @@ -0,0 +1 @@ +"[metricVis] > [visdimension] > Can not cast 'null' to any of 'kibana_datatable'" \ No newline at end of file diff --git a/test/interpreter_functional/snapshots/session/metric_multi_metric_data.json b/test/interpreter_functional/snapshots/session/metric_multi_metric_data.json new file mode 100644 index 0000000000000..7f64f97845191 --- /dev/null +++ b/test/interpreter_functional/snapshots/session/metric_multi_metric_data.json @@ -0,0 +1 @@ +{"as":"visualization","type":"render","value":{"params":{"listenOnChange":true},"visConfig":{"dimensions":{"metrics":[{"accessor":0,"format":{"id":"string","params":{}},"type":"vis_dimension"},{"accessor":1,"format":{"id":"string","params":{}},"type":"vis_dimension"}]},"metric":{"colorSchema":"Green to Red","colorsRange":[{"from":0,"to":10000,"type":"range"}],"invertColors":false,"labels":{"show":true},"metricColorMode":"None","percentageMode":false,"style":{"bgColor":false,"bgFill":"#000","fontSize":60,"labelColor":false,"subText":""},"useRanges":false}},"visData":{"columns":[{"id":"col-0-2","name":"response.raw: Descending"},{"id":"col-1-1","name":"Count"},{"id":"col-2-1","name":"Max bytes"}],"rows":[{"col-0-2":"200","col-1-1":12891,"col-2-1":19986},{"col-0-2":"404","col-1-1":696,"col-2-1":19881},{"col-0-2":"503","col-1-1":417,"col-2-1":0}],"type":"kibana_datatable"},"visType":"metric"}} \ No newline at end of file diff --git a/test/interpreter_functional/snapshots/session/metric_percentage.json b/test/interpreter_functional/snapshots/session/metric_percentage.json new file mode 100644 index 0000000000000..e171a65be8bab --- /dev/null +++ b/test/interpreter_functional/snapshots/session/metric_percentage.json @@ -0,0 +1 @@ +{"as":"visualization","type":"render","value":{"params":{"listenOnChange":true},"visConfig":{"dimensions":{"metrics":[{"accessor":0,"format":{"id":"string","params":{}},"type":"vis_dimension"}]},"metric":{"colorSchema":"Green to Red","colorsRange":[{"from":0,"to":1000,"type":"range"}],"invertColors":false,"labels":{"show":true},"metricColorMode":"None","percentageMode":true,"style":{"bgColor":false,"bgFill":"#000","fontSize":60,"labelColor":false,"subText":""},"useRanges":false}},"visData":{"columns":[{"id":"col-0-2","name":"response.raw: Descending"},{"id":"col-1-1","name":"Count"},{"id":"col-2-1","name":"Max bytes"}],"rows":[{"col-0-2":"200","col-1-1":12891,"col-2-1":19986},{"col-0-2":"404","col-1-1":696,"col-2-1":19881},{"col-0-2":"503","col-1-1":417,"col-2-1":0}],"type":"kibana_datatable"},"visType":"metric"}} \ No newline at end of file diff --git a/test/interpreter_functional/snapshots/session/metric_single_metric_data.json b/test/interpreter_functional/snapshots/session/metric_single_metric_data.json new file mode 100644 index 0000000000000..ed8b0b258fd90 --- /dev/null +++ b/test/interpreter_functional/snapshots/session/metric_single_metric_data.json @@ -0,0 +1 @@ +{"as":"visualization","type":"render","value":{"params":{"listenOnChange":true},"visConfig":{"dimensions":{"metrics":[{"accessor":0,"format":{"id":"string","params":{}},"type":"vis_dimension"}]},"metric":{"colorSchema":"Green to Red","colorsRange":[{"from":0,"to":10000,"type":"range"}],"invertColors":false,"labels":{"show":true},"metricColorMode":"None","percentageMode":false,"style":{"bgColor":false,"bgFill":"#000","fontSize":60,"labelColor":false,"subText":""},"useRanges":false}},"visData":{"columns":[{"id":"col-0-2","name":"response.raw: Descending"},{"id":"col-1-1","name":"Count"},{"id":"col-2-1","name":"Max bytes"}],"rows":[{"col-0-2":"200","col-1-1":12891,"col-2-1":19986},{"col-0-2":"404","col-1-1":696,"col-2-1":19881},{"col-0-2":"503","col-1-1":417,"col-2-1":0}],"type":"kibana_datatable"},"visType":"metric"}} \ No newline at end of file diff --git a/test/interpreter_functional/snapshots/session/partial_test_1.json b/test/interpreter_functional/snapshots/session/partial_test_1.json new file mode 100644 index 0000000000000..8a349aa5df060 --- /dev/null +++ b/test/interpreter_functional/snapshots/session/partial_test_1.json @@ -0,0 +1 @@ +{"as":"visualization","type":"render","value":{"params":{"listenOnChange":true},"visConfig":{"bucket":{"accessor":0,"format":{"id":"string","params":{}},"type":"vis_dimension"},"maxFontSize":72,"metric":{"accessor":1,"format":{"id":"number","params":{}},"type":"vis_dimension"},"minFontSize":18,"orientation":"single","scale":"linear","showLabel":true},"visData":{"columns":[{"id":"col-0-2","name":"response.raw: Descending"},{"id":"col-1-1","name":"Count"}],"rows":[{"col-0-2":"200","col-1-1":12891},{"col-0-2":"404","col-1-1":696},{"col-0-2":"503","col-1-1":417}],"type":"kibana_datatable"},"visType":"tagcloud"}} \ No newline at end of file diff --git a/test/interpreter_functional/snapshots/session/partial_test_2.json b/test/interpreter_functional/snapshots/session/partial_test_2.json new file mode 100644 index 0000000000000..310377eadd165 --- /dev/null +++ b/test/interpreter_functional/snapshots/session/partial_test_2.json @@ -0,0 +1 @@ +{"as":"visualization","type":"render","value":{"params":{"listenOnChange":true},"visConfig":{"dimensions":{"bucket":{"accessor":0,"format":{"id":"string","params":{}},"type":"vis_dimension"},"metrics":[{"accessor":1,"format":{"id":"number","params":{}},"type":"vis_dimension"}]},"metric":{"colorSchema":"Green to Red","colorsRange":[{"from":0,"to":10000,"type":"range"}],"invertColors":false,"labels":{"show":true},"metricColorMode":"None","percentageMode":false,"style":{"bgColor":false,"bgFill":"#000","fontSize":60,"labelColor":false,"subText":""},"useRanges":false}},"visData":{"columns":[{"id":"col-0-2","name":"response.raw: Descending"},{"id":"col-1-1","name":"Count"}],"rows":[{"col-0-2":"200","col-1-1":12891},{"col-0-2":"404","col-1-1":696},{"col-0-2":"503","col-1-1":417}],"type":"kibana_datatable"},"visType":"metric"}} \ No newline at end of file diff --git a/test/interpreter_functional/snapshots/session/partial_test_3.json b/test/interpreter_functional/snapshots/session/partial_test_3.json new file mode 100644 index 0000000000000..c1e429508c37f --- /dev/null +++ b/test/interpreter_functional/snapshots/session/partial_test_3.json @@ -0,0 +1 @@ +{"as":"visualization","type":"render","value":{"params":{"listenOnChange":true},"visConfig":{"bucket":{"accessor":0},"metric":{"accessor":1,"format":{"id":"number"}}},"visData":{"columns":[{"id":"col-0-2","name":"response.raw: Descending"},{"id":"col-1-1","name":"Count"}],"rows":[{"col-0-2":"200","col-1-1":12891},{"col-0-2":"404","col-1-1":696},{"col-0-2":"503","col-1-1":417}],"type":"kibana_datatable"},"visType":"region_map"}} \ No newline at end of file diff --git a/test/interpreter_functional/snapshots/session/step_output_test0.json b/test/interpreter_functional/snapshots/session/step_output_test0.json new file mode 100644 index 0000000000000..2af0407f0d521 --- /dev/null +++ b/test/interpreter_functional/snapshots/session/step_output_test0.json @@ -0,0 +1 @@ +{"filters":null,"query":null,"timeRange":null,"type":"kibana_context"} \ No newline at end of file diff --git a/test/interpreter_functional/snapshots/session/step_output_test1.json b/test/interpreter_functional/snapshots/session/step_output_test1.json new file mode 100644 index 0000000000000..8f00d72df8ab3 --- /dev/null +++ b/test/interpreter_functional/snapshots/session/step_output_test1.json @@ -0,0 +1 @@ +{"filters":[],"query":[],"timeRange":null,"type":"kibana_context"} \ No newline at end of file diff --git a/test/interpreter_functional/snapshots/session/step_output_test2.json b/test/interpreter_functional/snapshots/session/step_output_test2.json new file mode 100644 index 0000000000000..98c7844e41f19 --- /dev/null +++ b/test/interpreter_functional/snapshots/session/step_output_test2.json @@ -0,0 +1 @@ +{"columns":[{"id":"col-0-2","name":"response.raw: Descending"},{"id":"col-1-1","name":"Count"}],"rows":[{"col-0-2":"200","col-1-1":12891},{"col-0-2":"404","col-1-1":696},{"col-0-2":"503","col-1-1":417}],"type":"kibana_datatable"} \ No newline at end of file diff --git a/test/interpreter_functional/snapshots/session/step_output_test3.json b/test/interpreter_functional/snapshots/session/step_output_test3.json new file mode 100644 index 0000000000000..310377eadd165 --- /dev/null +++ b/test/interpreter_functional/snapshots/session/step_output_test3.json @@ -0,0 +1 @@ +{"as":"visualization","type":"render","value":{"params":{"listenOnChange":true},"visConfig":{"dimensions":{"bucket":{"accessor":0,"format":{"id":"string","params":{}},"type":"vis_dimension"},"metrics":[{"accessor":1,"format":{"id":"number","params":{}},"type":"vis_dimension"}]},"metric":{"colorSchema":"Green to Red","colorsRange":[{"from":0,"to":10000,"type":"range"}],"invertColors":false,"labels":{"show":true},"metricColorMode":"None","percentageMode":false,"style":{"bgColor":false,"bgFill":"#000","fontSize":60,"labelColor":false,"subText":""},"useRanges":false}},"visData":{"columns":[{"id":"col-0-2","name":"response.raw: Descending"},{"id":"col-1-1","name":"Count"}],"rows":[{"col-0-2":"200","col-1-1":12891},{"col-0-2":"404","col-1-1":696},{"col-0-2":"503","col-1-1":417}],"type":"kibana_datatable"},"visType":"metric"}} \ No newline at end of file diff --git a/test/interpreter_functional/snapshots/session/tagcloud_all_data.json b/test/interpreter_functional/snapshots/session/tagcloud_all_data.json new file mode 100644 index 0000000000000..1325c7fbed03e --- /dev/null +++ b/test/interpreter_functional/snapshots/session/tagcloud_all_data.json @@ -0,0 +1 @@ +{"as":"visualization","type":"render","value":{"params":{"listenOnChange":true},"visConfig":{"bucket":{"accessor":1,"format":{"id":"string","params":{}},"type":"vis_dimension"},"maxFontSize":72,"metric":{"accessor":0,"format":{"id":"string","params":{}},"type":"vis_dimension"},"minFontSize":18,"orientation":"single","scale":"linear","showLabel":true},"visData":{"columns":[{"id":"col-0-2","name":"response.raw: Descending"},{"id":"col-1-1","name":"Count"}],"rows":[{"col-0-2":"200","col-1-1":12891},{"col-0-2":"404","col-1-1":696},{"col-0-2":"503","col-1-1":417}],"type":"kibana_datatable"},"visType":"tagcloud"}} \ No newline at end of file diff --git a/test/interpreter_functional/snapshots/session/tagcloud_fontsize.json b/test/interpreter_functional/snapshots/session/tagcloud_fontsize.json new file mode 100644 index 0000000000000..2b063b518665a --- /dev/null +++ b/test/interpreter_functional/snapshots/session/tagcloud_fontsize.json @@ -0,0 +1 @@ +{"as":"visualization","type":"render","value":{"params":{"listenOnChange":true},"visConfig":{"bucket":{"accessor":1,"format":{"id":"string","params":{}},"type":"vis_dimension"},"maxFontSize":40,"metric":{"accessor":0,"format":{"id":"string","params":{}},"type":"vis_dimension"},"minFontSize":20,"orientation":"single","scale":"linear","showLabel":true},"visData":{"columns":[{"id":"col-0-2","name":"response.raw: Descending"},{"id":"col-1-1","name":"Count"}],"rows":[{"col-0-2":"200","col-1-1":12891},{"col-0-2":"404","col-1-1":696},{"col-0-2":"503","col-1-1":417}],"type":"kibana_datatable"},"visType":"tagcloud"}} \ No newline at end of file diff --git a/test/interpreter_functional/snapshots/session/tagcloud_invalid_data.json b/test/interpreter_functional/snapshots/session/tagcloud_invalid_data.json new file mode 100644 index 0000000000000..46b52a7b3eaae --- /dev/null +++ b/test/interpreter_functional/snapshots/session/tagcloud_invalid_data.json @@ -0,0 +1 @@ +"[tagcloud] > [visdimension] > Can not cast 'null' to any of 'kibana_datatable'" \ No newline at end of file diff --git a/test/interpreter_functional/snapshots/session/tagcloud_metric_data.json b/test/interpreter_functional/snapshots/session/tagcloud_metric_data.json new file mode 100644 index 0000000000000..6152fd406961f --- /dev/null +++ b/test/interpreter_functional/snapshots/session/tagcloud_metric_data.json @@ -0,0 +1 @@ +{"as":"visualization","type":"render","value":{"params":{"listenOnChange":true},"visConfig":{"maxFontSize":72,"metric":{"accessor":0,"format":{"id":"string","params":{}},"type":"vis_dimension"},"minFontSize":18,"orientation":"single","scale":"linear","showLabel":true},"visData":{"columns":[{"id":"col-0-2","name":"response.raw: Descending"},{"id":"col-1-1","name":"Count"}],"rows":[{"col-0-2":"200","col-1-1":12891},{"col-0-2":"404","col-1-1":696},{"col-0-2":"503","col-1-1":417}],"type":"kibana_datatable"},"visType":"tagcloud"}} \ No newline at end of file diff --git a/test/interpreter_functional/snapshots/session/tagcloud_options.json b/test/interpreter_functional/snapshots/session/tagcloud_options.json new file mode 100644 index 0000000000000..e4c6b09a264dd --- /dev/null +++ b/test/interpreter_functional/snapshots/session/tagcloud_options.json @@ -0,0 +1 @@ +{"as":"visualization","type":"render","value":{"params":{"listenOnChange":true},"visConfig":{"bucket":{"accessor":1,"format":{"id":"string","params":{}},"type":"vis_dimension"},"maxFontSize":72,"metric":{"accessor":0,"format":{"id":"string","params":{}},"type":"vis_dimension"},"minFontSize":18,"orientation":"multiple","scale":"log","showLabel":true},"visData":{"columns":[{"id":"col-0-2","name":"response.raw: Descending"},{"id":"col-1-1","name":"Count"}],"rows":[{"col-0-2":"200","col-1-1":12891},{"col-0-2":"404","col-1-1":696},{"col-0-2":"503","col-1-1":417}],"type":"kibana_datatable"},"visType":"tagcloud"}} \ No newline at end of file diff --git a/test/interpreter_functional/test_suites/run_pipeline/basic.js b/test/interpreter_functional/test_suites/run_pipeline/basic.js index 1cb064c2f5e56..893a79956093c 100644 --- a/test/interpreter_functional/test_suites/run_pipeline/basic.js +++ b/test/interpreter_functional/test_suites/run_pipeline/basic.js @@ -45,9 +45,7 @@ export default function ({ getService, updateBaselines }) { }); // rather we want to use this to do integration tests. - // Failing on chromedriver 76 - // https://github.com/elastic/kibana/issues/42842 - describe.skip('full expression', () => { + describe('full expression', () => { const expression = `kibana | kibana_context | esaggs index='logstash-*' aggConfigs='[ {"id":"1","enabled":true,"type":"count","schema":"metric","params":{}}, {"id":"2","enabled":true,"type":"terms","schema":"segment","params": @@ -84,7 +82,7 @@ export default function ({ getService, updateBaselines }) { // if we want to do multiple different tests using the same data, or reusing a part of expression its // possible to retrieve the intermediate result and reuse it in later expressions - describe.skip('reusing partial results', () => { + describe('reusing partial results', () => { it ('does some screenshot comparisons', async () => { const expression = `kibana | kibana_context | esaggs index='logstash-*' aggConfigs='[ {"id":"1","enabled":true,"type":"count","schema":"metric","params":{}}, @@ -97,16 +95,15 @@ export default function ({ getService, updateBaselines }) { // we reuse that response to render 3 different charts and compare screenshots with baselines const tagCloudExpr = `tagcloud metric={visdimension 1 format="number"} bucket={visdimension 0}`; - await expectExpression('partial_test_1', tagCloudExpr, context).toMatchScreenshot(); + await (await expectExpression('partial_test_1', tagCloudExpr, context).toMatchSnapshot()).toMatchScreenshot(); const metricExpr = `metricVis metric={visdimension 1 format="number"} bucket={visdimension 0}`; - await expectExpression('partial_test_2', metricExpr, context).toMatchScreenshot(); + await (await expectExpression('partial_test_2', metricExpr, context).toMatchSnapshot()).toMatchScreenshot(); - // todo: regionmap doesn't correctly signal when its done rendering (base layer might not yet be loaded) - // const regionMapExpr = - // `regionmap visConfig='{"metric":{"accessor":1,"format":{"id":"number"}},"bucket":{"accessor":0}}'`; - // await expectExpression('partial_test_3', regionMapExpr, context).toMatchScreenshot(); + const regionMapExpr = + `regionmap visConfig='{"metric":{"accessor":1,"format":{"id":"number"}},"bucket":{"accessor":0}}'`; + await (await expectExpression('partial_test_3', regionMapExpr, context).toMatchSnapshot()).toMatchScreenshot(); }); }); }); diff --git a/test/interpreter_functional/test_suites/run_pipeline/helpers.js b/test/interpreter_functional/test_suites/run_pipeline/helpers.js index 6186720b617af..4df86d3418f1f 100644 --- a/test/interpreter_functional/test_suites/run_pipeline/helpers.js +++ b/test/interpreter_functional/test_suites/run_pipeline/helpers.js @@ -84,7 +84,7 @@ export const expectExpressionProvider = ({ getService, updateBaselines }) => { for (let i = 0; i < steps.length; i++) { const step = steps[i]; lastResponse = await handler.runExpression(step, lastResponse); - const diff = await snapshots.compareAgainstBaseline(name + i, lastResponse, updateBaselines); + const diff = await snapshots.compareAgainstBaseline(name + i, toSerializable(lastResponse), updateBaselines); expect(diff).to.be.lessThan(0.05); } if (!responsePromise) { @@ -101,7 +101,7 @@ export const expectExpressionProvider = ({ getService, updateBaselines }) => { */ toMatchSnapshot: async () => { const pipelineResponse = await handler.getResponse(); - await snapshots.compareAgainstBaseline(name, pipelineResponse, updateBaselines); + await snapshots.compareAgainstBaseline(name, toSerializable(pipelineResponse), updateBaselines); return handler; }, /** @@ -110,6 +110,7 @@ export const expectExpressionProvider = ({ getService, updateBaselines }) => { */ toMatchScreenshot: async () => { const pipelineResponse = await handler.getResponse(); + log.debug('starting to render'); const result = await browser.executeAsync((context, done) => { window.renderPipelineResponse(context).then(result => { done(result); @@ -126,4 +127,13 @@ export const expectExpressionProvider = ({ getService, updateBaselines }) => { return handler; }; + + function toSerializable(response) { + if (response.error) { + // in case of error, pass through only message to the snapshot + // as error could be expected and stack trace shouldn't be part of the snapshot + return response.error.message; + } + return response; + } }; diff --git a/test/interpreter_functional/test_suites/run_pipeline/index.js b/test/interpreter_functional/test_suites/run_pipeline/index.js index ebc0568ebb955..3c1ce2314f55f 100644 --- a/test/interpreter_functional/test_suites/run_pipeline/index.js +++ b/test/interpreter_functional/test_suites/run_pipeline/index.js @@ -25,7 +25,7 @@ export default function ({ getService, getPageObjects, loadTestFile }) { const testSubjects = getService('testSubjects'); const PageObjects = getPageObjects(['common', 'header']); - describe.skip('runPipeline', function () { + describe('runPipeline', function () { this.tags(['skipFirefox']); before(async () => { diff --git a/test/interpreter_functional/test_suites/run_pipeline/metric.js b/test/interpreter_functional/test_suites/run_pipeline/metric.js index b772617b53bff..78d571b3583be 100644 --- a/test/interpreter_functional/test_suites/run_pipeline/metric.js +++ b/test/interpreter_functional/test_suites/run_pipeline/metric.js @@ -19,8 +19,6 @@ import { expectExpressionProvider } from './helpers'; -// this file showcases how to use testing utilities defined in helpers.js together with the kbn_tp_run_pipeline -// test plugin to write autmated tests for interprete export default function ({ getService, updateBaselines }) { let expectExpression; @@ -29,8 +27,6 @@ export default function ({ getService, updateBaselines }) { expectExpression = expectExpressionProvider({ getService, updateBaselines }); }); - // we should not use this for tests like the ones below. this should be unit tested. - // - tests against a single function could easily be written as unit tests (and should be) describe('correctly renders metric', () => { let dataContext; before(async () => { @@ -46,35 +42,29 @@ export default function ({ getService, updateBaselines }) { dataContext = await expectExpression('partial_metric_test', expression).getResponse(); }); - it.skip('with invalid data', async () => { + it('with invalid data', async () => { const expression = 'metricVis metric={visdimension 0}'; await (await expectExpression('metric_invalid_data', expression).toMatchSnapshot()).toMatchScreenshot(); }); - // Test fails on chromedriver 76 - // https://github.com/elastic/kibana/issues/42842 - it.skip('with single metric data', async () => { + it('with single metric data', async () => { const expression = 'metricVis metric={visdimension 0}'; await (await expectExpression('metric_single_metric_data', expression, dataContext).toMatchSnapshot()).toMatchScreenshot(); }); - // Test fails on chromedriver 76 - // https://github.com/elastic/kibana/issues/42842 - it.skip('with multiple metric data', async () => { + it('with multiple metric data', async () => { const expression = 'metricVis metric={visdimension 0} metric={visdimension 1}'; - await expectExpression('metric_multi_metric_data', expression, dataContext).toMatchSnapshot(); + await (await expectExpression('metric_multi_metric_data', expression, dataContext).toMatchSnapshot()).toMatchScreenshot(); }); - // Test fails on chromedriver 76 - // https://github.com/elastic/kibana/issues/42842 - it.skip('with metric and bucket data', async () => { + it('with metric and bucket data', async () => { const expression = 'metricVis metric={visdimension 0} bucket={visdimension 2}'; await (await expectExpression('metric_all_data', expression, dataContext).toMatchSnapshot()).toMatchScreenshot(); }); it('with percentage option', async () => { const expression = 'metricVis metric={visdimension 0} percentage=true colorRange={range from=0 to=1000}'; - await expectExpression('metric_percentage', expression, dataContext).toMatchSnapshot(); + await (await expectExpression('metric_percentage', expression, dataContext).toMatchSnapshot()).toMatchScreenshot(); }); }); }); diff --git a/test/interpreter_functional/test_suites/run_pipeline/tag_cloud.js b/test/interpreter_functional/test_suites/run_pipeline/tag_cloud.js index 3bcbf8f2075ad..7c0e2d7190703 100644 --- a/test/interpreter_functional/test_suites/run_pipeline/tag_cloud.js +++ b/test/interpreter_functional/test_suites/run_pipeline/tag_cloud.js @@ -19,8 +19,6 @@ import { expectExpressionProvider } from './helpers'; -// this file showcases how to use testing utilities defined in helpers.js together with the kbn_tp_run_pipeline -// test plugin to write autmated tests for interprete export default function ({ getService, updateBaselines }) { let expectExpression; @@ -29,8 +27,6 @@ export default function ({ getService, updateBaselines }) { expectExpression = expectExpressionProvider({ getService, updateBaselines }); }); - // we should not use this for tests like the ones below. this should be unit tested. - // - tests against a single function could easily be written as unit tests (and should be) describe('correctly renders tagcloud', () => { let dataContext; before(async () => { @@ -43,7 +39,7 @@ export default function ({ getService, updateBaselines }) { dataContext = await expectExpression('partial_tagcloud_test', expression).getResponse(); }); - it.skip('with invalid data', async () => { + it('with invalid data', async () => { const expression = 'tagcloud metric={visdimension 0}'; await (await expectExpression('tagcloud_invalid_data', expression).toMatchSnapshot()).toMatchScreenshot(); }); diff --git a/test/plugin_functional/plugins/kbn_tp_custom_visualizations/package.json b/test/plugin_functional/plugins/kbn_tp_custom_visualizations/package.json index 6a2221fa6f6d5..fd0ce478eb6fb 100644 --- a/test/plugin_functional/plugins/kbn_tp_custom_visualizations/package.json +++ b/test/plugin_functional/plugins/kbn_tp_custom_visualizations/package.json @@ -7,7 +7,7 @@ }, "license": "Apache-2.0", "dependencies": { - "@elastic/eui": "14.9.0", + "@elastic/eui": "16.0.0", "react": "^16.12.0" } } diff --git a/test/plugin_functional/plugins/kbn_tp_embeddable_explorer/package.json b/test/plugin_functional/plugins/kbn_tp_embeddable_explorer/package.json index ed78d8c4a5fa9..98df7f4b246dc 100644 --- a/test/plugin_functional/plugins/kbn_tp_embeddable_explorer/package.json +++ b/test/plugin_functional/plugins/kbn_tp_embeddable_explorer/package.json @@ -8,7 +8,7 @@ }, "license": "Apache-2.0", "dependencies": { - "@elastic/eui": "14.9.0", + "@elastic/eui": "16.0.0", "react": "^16.12.0" }, "scripts": { diff --git a/test/plugin_functional/plugins/kbn_tp_sample_panel_action/package.json b/test/plugin_functional/plugins/kbn_tp_sample_panel_action/package.json index b1cdd3c20a9eb..32f441ba6ccda 100644 --- a/test/plugin_functional/plugins/kbn_tp_sample_panel_action/package.json +++ b/test/plugin_functional/plugins/kbn_tp_sample_panel_action/package.json @@ -8,7 +8,7 @@ }, "license": "Apache-2.0", "dependencies": { - "@elastic/eui": "14.9.0", + "@elastic/eui": "16.0.0", "react": "^16.12.0" }, "scripts": { diff --git a/test/server_integration/config.js b/test/server_integration/config.js index 18575fcb5fcff..77aeaa8af3b9f 100644 --- a/test/server_integration/config.js +++ b/test/server_integration/config.js @@ -29,9 +29,7 @@ export default async function ({ readConfigFile }) { return { services: { - es: commonConfig.get('services.es'), - esArchiver: commonConfig.get('services.esArchiver'), - retry: commonConfig.get('services.retry'), + ...commonConfig.get('services'), supertest: KibanaSupertestProvider, supertestWithoutAuth: KibanaSupertestWithoutAuthProvider, esSupertest: ElasticsearchSupertestProvider, diff --git a/test/visual_regression/tests/discover/chart_visualization.js b/test/visual_regression/tests/discover/chart_visualization.js index 4e1d9bf643cf6..540d95973b547 100644 --- a/test/visual_regression/tests/discover/chart_visualization.js +++ b/test/visual_regression/tests/discover/chart_visualization.js @@ -33,8 +33,6 @@ export default function ({ getService, getPageObjects }) { }; describe('discover', function describeIndexTests() { - const fromTime = '2015-09-19 06:31:44.000'; - const toTime = '2015-09-23 18:31:44.000'; before(async function () { log.debug('load kibana index with default index pattern'); @@ -45,7 +43,7 @@ export default function ({ getService, getPageObjects }) { await kibanaServer.uiSettings.replace(defaultSettings); log.debug('discover'); await PageObjects.common.navigateToApp('discover'); - await PageObjects.timePicker.setAbsoluteRange(fromTime, toTime); + await PageObjects.timePicker.setDefaultAbsoluteRange(); }); describe('query', function () { @@ -132,7 +130,7 @@ export default function ({ getService, getPageObjects }) { await kibanaServer.uiSettings.replace({ 'dateFormat:tz': 'America/Phoenix' }); await browser.refresh(); await PageObjects.header.awaitKibanaChrome(); - await PageObjects.timePicker.setAbsoluteRange(fromTime, toTime); + await PageObjects.timePicker.setDefaultAbsoluteRange(); await PageObjects.header.awaitGlobalLoadingIndicatorHidden(); await PageObjects.discover.waitUntilSearchingHasFinished(); await visualTesting.snapshot({ diff --git a/x-pack/dev-tools/jest/create_jest_config.js b/x-pack/dev-tools/jest/create_jest_config.js index 9d601e680cf87..199232262773d 100644 --- a/x-pack/dev-tools/jest/create_jest_config.js +++ b/x-pack/dev-tools/jest/create_jest_config.js @@ -36,7 +36,10 @@ export function createJestConfig({ kibanaDirectory, xPackKibanaDirectory }) { `/dev-tools/jest/setup/polyfills.js`, `/dev-tools/jest/setup/enzyme.js`, ], - setupFilesAfterEnv: [`${kibanaDirectory}/src/dev/jest/setup/mocks.js`], + setupFilesAfterEnv: [ + `/dev-tools/jest/setup/setup_test.js`, + `${kibanaDirectory}/src/dev/jest/setup/mocks.js`, + ], testMatch: ['**/*.test.{js,ts,tsx}'], transform: { '^.+\\.(js|tsx?)$': `${kibanaDirectory}/src/dev/jest/babel_transform.js`, @@ -49,7 +52,7 @@ export function createJestConfig({ kibanaDirectory, xPackKibanaDirectory }) { ], snapshotSerializers: [ `${kibanaDirectory}/node_modules/enzyme-to-json/serializer`, - `${kibanaDirectory}/src/plugins/kibana_react/public/util/test_helpers/react_mount_serializer.ts` + `${kibanaDirectory}/src/plugins/kibana_react/public/util/test_helpers/react_mount_serializer.ts`, ], reporters: [ 'default', diff --git a/x-pack/dev-tools/jest/setup/setup_test.js b/x-pack/dev-tools/jest/setup/setup_test.js new file mode 100644 index 0000000000000..533ea58a561ac --- /dev/null +++ b/x-pack/dev-tools/jest/setup/setup_test.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. + */ + +/* + Global import, so we don't need to remember to import the lib in each file + https://www.npmjs.com/package/jest-styled-components#global-installation +*/ + +import 'jest-styled-components'; diff --git a/x-pack/legacy/common/eui_styled_components/eui_styled_components.tsx b/x-pack/legacy/common/eui_styled_components/eui_styled_components.tsx index 8becf6892ff92..aab16f9d79c4b 100644 --- a/x-pack/legacy/common/eui_styled_components/eui_styled_components.tsx +++ b/x-pack/legacy/common/eui_styled_components/eui_styled_components.tsx @@ -16,16 +16,18 @@ export interface EuiTheme { darkMode: boolean; } -const EuiThemeProvider = ({ +const EuiThemeProvider = < + OuterTheme extends styledComponents.DefaultTheme = styledComponents.DefaultTheme +>({ darkMode = false, ...otherProps -}: ThemeProviderProps & { +}: Omit, 'theme'> & { darkMode?: boolean; - children?: React.ReactNode; }) => ( ({ + theme={(outerTheme?: OuterTheme) => ({ + ...outerTheme, eui: darkMode ? euiDarkVars : euiLightVars, darkMode, })} @@ -35,9 +37,9 @@ const EuiThemeProvider = ({ const { default: euiStyled, css, - injectGlobal, + createGlobalStyle, keyframes, withTheme, } = (styledComponents as unknown) as ThemedStyledComponentsModule; -export { css, euiStyled, EuiThemeProvider, injectGlobal, keyframes, withTheme }; +export { css, euiStyled, EuiThemeProvider, createGlobalStyle, keyframes, withTheme }; diff --git a/x-pack/legacy/common/eui_styled_components/index.ts b/x-pack/legacy/common/eui_styled_components/index.ts index 9d07b540d4974..9b3ed903627b4 100644 --- a/x-pack/legacy/common/eui_styled_components/index.ts +++ b/x-pack/legacy/common/eui_styled_components/index.ts @@ -9,12 +9,12 @@ import { euiStyled, EuiTheme, EuiThemeProvider, - injectGlobal, + createGlobalStyle, keyframes, withTheme, } from './eui_styled_components'; -export { css, euiStyled, EuiTheme, EuiThemeProvider, injectGlobal, keyframes, withTheme }; +export { css, euiStyled, EuiTheme, EuiThemeProvider, createGlobalStyle, keyframes, withTheme }; // In order to to mimic the styled-components module we need to ignore the following // eslint-disable-next-line import/no-default-export export default euiStyled; diff --git a/x-pack/legacy/plugins/apm/common/__snapshots__/elasticsearch_fieldnames.test.ts.snap b/x-pack/legacy/plugins/apm/common/__snapshots__/elasticsearch_fieldnames.test.ts.snap index 0521270a7ba74..9d82cd6b5455c 100644 --- a/x-pack/legacy/plugins/apm/common/__snapshots__/elasticsearch_fieldnames.test.ts.snap +++ b/x-pack/legacy/plugins/apm/common/__snapshots__/elasticsearch_fieldnames.test.ts.snap @@ -102,6 +102,8 @@ exports[`Error TRANSACTION_TYPE 1`] = `"request"`; exports[`Error URL_FULL 1`] = `undefined`; +exports[`Error USER_AGENT_NAME 1`] = `undefined`; + exports[`Error USER_ID 1`] = `undefined`; exports[`Span CLIENT_GEO_COUNTRY_ISO_CODE 1`] = `undefined`; @@ -206,6 +208,8 @@ exports[`Span TRANSACTION_TYPE 1`] = `undefined`; exports[`Span URL_FULL 1`] = `undefined`; +exports[`Span USER_AGENT_NAME 1`] = `undefined`; + exports[`Span USER_ID 1`] = `undefined`; exports[`Transaction CLIENT_GEO_COUNTRY_ISO_CODE 1`] = `undefined`; @@ -310,4 +314,6 @@ exports[`Transaction TRANSACTION_TYPE 1`] = `"transaction type"`; exports[`Transaction URL_FULL 1`] = `"http://www.elastic.co"`; +exports[`Transaction USER_AGENT_NAME 1`] = `"Other"`; + exports[`Transaction USER_ID 1`] = `"1337"`; diff --git a/x-pack/legacy/plugins/apm/common/elasticsearch_fieldnames.test.ts b/x-pack/legacy/plugins/apm/common/elasticsearch_fieldnames.test.ts index 52471e08b1b4d..82a679ccdd32e 100644 --- a/x-pack/legacy/plugins/apm/common/elasticsearch_fieldnames.test.ts +++ b/x-pack/legacy/plugins/apm/common/elasticsearch_fieldnames.test.ts @@ -34,6 +34,7 @@ describe('Transaction', () => { timestamp: { us: 1337 }, trace: { id: 'trace id' }, user: { id: '1337' }, + user_agent: { name: 'Other', original: 'test original' }, parent: { id: 'parentId' }, diff --git a/x-pack/legacy/plugins/apm/common/elasticsearch_fieldnames.ts b/x-pack/legacy/plugins/apm/common/elasticsearch_fieldnames.ts index 552c149ce6214..d0830337e0d35 100644 --- a/x-pack/legacy/plugins/apm/common/elasticsearch_fieldnames.ts +++ b/x-pack/legacy/plugins/apm/common/elasticsearch_fieldnames.ts @@ -10,6 +10,7 @@ export const SERVICE_NODE_NAME = 'service.node.name'; export const URL_FULL = 'url.full'; export const HTTP_REQUEST_METHOD = 'http.request.method'; export const USER_ID = 'user.id'; +export const USER_AGENT_NAME = 'user_agent.name'; export const OBSERVER_VERSION_MAJOR = 'observer.version_major'; export const OBSERVER_LISTENING = 'observer.listening'; diff --git a/x-pack/legacy/plugins/apm/common/processor_event.ts b/x-pack/legacy/plugins/apm/common/processor_event.ts index a513f62092767..83dadfc21da90 100644 --- a/x-pack/legacy/plugins/apm/common/processor_event.ts +++ b/x-pack/legacy/plugins/apm/common/processor_event.ts @@ -4,4 +4,8 @@ * you may not use this file except in compliance with the Elastic License. */ -export type ProcessorEvent = 'transaction' | 'error' | 'metric'; +export enum ProcessorEvent { + transaction = 'transaction', + error = 'error', + metric = 'metric' +} diff --git a/x-pack/legacy/plugins/apm/common/transaction_types.ts b/x-pack/legacy/plugins/apm/common/transaction_types.ts index 4dd59af63047d..1226e926b1ee3 100644 --- a/x-pack/legacy/plugins/apm/common/transaction_types.ts +++ b/x-pack/legacy/plugins/apm/common/transaction_types.ts @@ -5,5 +5,5 @@ */ export const TRANSACTION_PAGE_LOAD = 'page-load'; -export const TRANSACTION_ROUTE_CHANGE = 'route-change'; export const TRANSACTION_REQUEST = 'request'; +export const TRANSACTION_ROUTE_CHANGE = 'route-change'; diff --git a/x-pack/legacy/plugins/apm/common/viz_colors.ts b/x-pack/legacy/plugins/apm/common/viz_colors.ts new file mode 100644 index 0000000000000..cc070005409b6 --- /dev/null +++ b/x-pack/legacy/plugins/apm/common/viz_colors.ts @@ -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 lightTheme from '@elastic/eui/dist/eui_theme_light.json'; + +function getVizColorsForTheme(theme = lightTheme) { + return [ + theme.euiColorVis0, + theme.euiColorVis1, + theme.euiColorVis2, + theme.euiColorVis3, + theme.euiColorVis4, + theme.euiColorVis5, + theme.euiColorVis6, + theme.euiColorVis7, + theme.euiColorVis8, + theme.euiColorVis9 + ]; +} + +export function getVizColorForIndex(index = 0, theme = lightTheme) { + const colors = getVizColorsForTheme(theme); + return colors[index % colors.length]; +} diff --git a/x-pack/legacy/plugins/apm/public/components/app/ErrorGroupOverview/List/__test__/__snapshots__/List.test.tsx.snap b/x-pack/legacy/plugins/apm/public/components/app/ErrorGroupOverview/List/__test__/__snapshots__/List.test.tsx.snap index c663c52d7d639..2b053274e8afe 100644 --- a/x-pack/legacy/plugins/apm/public/components/app/ErrorGroupOverview/List/__test__/__snapshots__/List.test.tsx.snap +++ b/x-pack/legacy/plugins/apm/public/components/app/ErrorGroupOverview/List/__test__/__snapshots__/List.test.tsx.snap @@ -122,7 +122,7 @@ exports[`ErrorGroupOverview -> List should render empty state 1`] = ` @@ -501,7 +501,7 @@ exports[`ErrorGroupOverview -> List should render with data 1`] = ` @@ -669,18 +669,24 @@ exports[`ErrorGroupOverview -> List should render with data 1`] = ` List should render with data 1`] = `
-
- - - - About to blow up! - - - -
- -
+ + About to blow up! + + + + +
+ - elasticapm.contrib.django.client.capture -
-
-
+ +
+ elasticapm.contrib.django.client.capture +
+
+ +
+
List should render with data 1`] = ` List should render with data 1`] = `
-
- - - - AssertionError: - - - -
- -
+ + AssertionError: + + + + +
+ - opbeans.views.oopsie -
-
-
+ +
+ opbeans.views.oopsie +
+
+ +
+
List should render with data 1`] = ` List should render with data 1`] = `
-
- - - - AssertionError: Bad luck! - - - -
- -
+ + AssertionError: Bad luck! + + + + +
+ - opbeans.tasks.update_stats -
-
-
+ +
+ opbeans.tasks.update_stats +
+
+ +
+
List should render with data 1`] = ` List should render with data 1`] = `
-
- - - - Customer with ID 8517 not found - - - -
- -
+ + Customer with ID 8517 not found + + + + +
+ - opbeans.views.customer -
-
-
+ +
+ opbeans.views.customer +
+
+ +
+
{ - const core = useKibanaCore(); - - return ( - - - - {i18n.translate('xpack.apm.feedbackMenu.provideFeedbackTitle', { - defaultMessage: 'Provide feedback for APM' - })} - - - - - {i18n.translate('xpack.apm.helpMenu.upgradeAssistantLink', { - defaultMessage: 'Upgrade assistant' - })} - - - - ); -}; diff --git a/x-pack/legacy/plugins/apm/public/components/app/ServiceOverview/ServiceList/__test__/__snapshots__/List.test.js.snap b/x-pack/legacy/plugins/apm/public/components/app/ServiceOverview/ServiceList/__test__/__snapshots__/List.test.js.snap index 146f6f58031bb..904e16f92f4a0 100644 --- a/x-pack/legacy/plugins/apm/public/components/app/ServiceOverview/ServiceList/__test__/__snapshots__/List.test.js.snap +++ b/x-pack/legacy/plugins/apm/public/components/app/ServiceOverview/ServiceList/__test__/__snapshots__/List.test.js.snap @@ -7,11 +7,11 @@ exports[`ServiceOverview -> List should render columns correctly 1`] = ` id="service-name-tooltip" position="top" > - opbeans-python - + `; diff --git a/x-pack/legacy/plugins/apm/public/components/app/ServiceOverview/__test__/__snapshots__/ServiceOverview.test.tsx.snap b/x-pack/legacy/plugins/apm/public/components/app/ServiceOverview/__test__/__snapshots__/ServiceOverview.test.tsx.snap index 6dcb9140a8bb9..489d4f2908cbe 100644 --- a/x-pack/legacy/plugins/apm/public/components/app/ServiceOverview/__test__/__snapshots__/ServiceOverview.test.tsx.snap +++ b/x-pack/legacy/plugins/apm/public/components/app/ServiceOverview/__test__/__snapshots__/ServiceOverview.test.tsx.snap @@ -138,7 +138,15 @@ NodeList [ exports[`Service Overview -> View should render services, when list is not empty 1`] = ` NodeList [ - @@ -236,7 +244,15 @@ NodeList [ , - diff --git a/x-pack/legacy/plugins/apm/public/components/app/TransactionDetails/WaterfallWithSummmary/WaterfallContainer/Waterfall/WaterfallItem.tsx b/x-pack/legacy/plugins/apm/public/components/app/TransactionDetails/WaterfallWithSummmary/WaterfallContainer/Waterfall/WaterfallItem.tsx index c64231a6ded86..339346ae2961e 100644 --- a/x-pack/legacy/plugins/apm/public/components/app/TransactionDetails/WaterfallWithSummmary/WaterfallContainer/Waterfall/WaterfallItem.tsx +++ b/x-pack/legacy/plugins/apm/public/components/app/TransactionDetails/WaterfallWithSummmary/WaterfallContainer/Waterfall/WaterfallItem.tsx @@ -27,12 +27,10 @@ interface IContainerStyleProps { interface IBarStyleProps { type: ItemType; - left: number; - width: number; color: string; } -const Container = styled('div')` +const Container = styled.div` position: relative; display: block; user-select: none; @@ -50,7 +48,7 @@ const Container = styled('div')` } `; -const ItemBar = styled('div')` +const ItemBar = styled.div` box-sizing: border-box; position: relative; height: ${px(unit)}; diff --git a/x-pack/legacy/plugins/apm/public/components/shared/Links/DiscoverLinks/__test__/DiscoverErrorButton.test.tsx b/x-pack/legacy/plugins/apm/public/components/shared/Links/DiscoverLinks/__test__/DiscoverErrorButton.test.tsx index 26f830a3b8efb..33cf05401a729 100644 --- a/x-pack/legacy/plugins/apm/public/components/shared/Links/DiscoverLinks/__test__/DiscoverErrorButton.test.tsx +++ b/x-pack/legacy/plugins/apm/public/components/shared/Links/DiscoverLinks/__test__/DiscoverErrorButton.test.tsx @@ -5,7 +5,6 @@ */ import { shallow, ShallowWrapper } from 'enzyme'; -import 'jest-styled-components'; import React from 'react'; import { APMError } from '../../../../../../typings/es_schemas/ui/APMError'; import { DiscoverErrorLink } from '../DiscoverErrorLink'; diff --git a/x-pack/legacy/plugins/apm/public/components/shared/Links/DiscoverLinks/__test__/DiscoverErrorLink.test.tsx b/x-pack/legacy/plugins/apm/public/components/shared/Links/DiscoverLinks/__test__/DiscoverErrorLink.test.tsx index 26f830a3b8efb..33cf05401a729 100644 --- a/x-pack/legacy/plugins/apm/public/components/shared/Links/DiscoverLinks/__test__/DiscoverErrorLink.test.tsx +++ b/x-pack/legacy/plugins/apm/public/components/shared/Links/DiscoverLinks/__test__/DiscoverErrorLink.test.tsx @@ -5,7 +5,6 @@ */ import { shallow, ShallowWrapper } from 'enzyme'; -import 'jest-styled-components'; import React from 'react'; import { APMError } from '../../../../../../typings/es_schemas/ui/APMError'; import { DiscoverErrorLink } from '../DiscoverErrorLink'; diff --git a/x-pack/legacy/plugins/apm/public/components/shared/Links/DiscoverLinks/__test__/DiscoverTransactionButton.test.tsx b/x-pack/legacy/plugins/apm/public/components/shared/Links/DiscoverLinks/__test__/DiscoverTransactionButton.test.tsx index 979391f260eda..a16bf389f177c 100644 --- a/x-pack/legacy/plugins/apm/public/components/shared/Links/DiscoverLinks/__test__/DiscoverTransactionButton.test.tsx +++ b/x-pack/legacy/plugins/apm/public/components/shared/Links/DiscoverLinks/__test__/DiscoverTransactionButton.test.tsx @@ -5,7 +5,6 @@ */ import { shallow } from 'enzyme'; -import 'jest-styled-components'; import React from 'react'; import { Transaction } from '../../../../../../typings/es_schemas/ui/Transaction'; import { diff --git a/x-pack/legacy/plugins/apm/public/components/shared/Links/DiscoverLinks/__test__/DiscoverTransactionLink.test.tsx b/x-pack/legacy/plugins/apm/public/components/shared/Links/DiscoverLinks/__test__/DiscoverTransactionLink.test.tsx index 9b314615f6413..3b876aa5950b4 100644 --- a/x-pack/legacy/plugins/apm/public/components/shared/Links/DiscoverLinks/__test__/DiscoverTransactionLink.test.tsx +++ b/x-pack/legacy/plugins/apm/public/components/shared/Links/DiscoverLinks/__test__/DiscoverTransactionLink.test.tsx @@ -4,7 +4,6 @@ * you may not use this file except in compliance with the Elastic License. */ -import 'jest-styled-components'; import { Transaction } from '../../../../../../typings/es_schemas/ui/Transaction'; // @ts-ignore import configureStore from '../../../../../store/config/configureStore'; diff --git a/x-pack/legacy/plugins/apm/public/components/shared/LocalUIFilters/Filter/FilterTitleButton.tsx b/x-pack/legacy/plugins/apm/public/components/shared/LocalUIFilters/Filter/FilterTitleButton.tsx index a257e52ab01cc..d2e9578b45e07 100644 --- a/x-pack/legacy/plugins/apm/public/components/shared/LocalUIFilters/Filter/FilterTitleButton.tsx +++ b/x-pack/legacy/plugins/apm/public/components/shared/LocalUIFilters/Filter/FilterTitleButton.tsx @@ -8,12 +8,12 @@ import React from 'react'; import { EuiButtonEmpty, EuiTitle } from '@elastic/eui'; import styled from 'styled-components'; -const Button = styled(EuiButtonEmpty).attrs({ +const Button = styled(EuiButtonEmpty).attrs(() => ({ contentProps: { className: 'alignLeft' }, color: 'text' -})` +}))` width: 100%; .alignLeft { diff --git a/x-pack/legacy/plugins/apm/public/components/shared/LocalUIFilters/Filter/index.tsx b/x-pack/legacy/plugins/apm/public/components/shared/LocalUIFilters/Filter/index.tsx index 412b92d525aa2..f47bc92567f9f 100644 --- a/x-pack/legacy/plugins/apm/public/components/shared/LocalUIFilters/Filter/index.tsx +++ b/x-pack/legacy/plugins/apm/public/components/shared/LocalUIFilters/Filter/index.tsx @@ -4,10 +4,11 @@ * you may not use this file except in compliance with the Elastic License. */ -import React, { useState, useMemo, useEffect } from 'react'; +import React, { FunctionComponent, useState, useMemo, useEffect } from 'react'; import { EuiTitle, EuiPopover, + EuiPopoverProps, EuiSelectable, EuiSpacer, EuiHorizontalRule, @@ -23,9 +24,11 @@ import { FilterBadgeList } from './FilterBadgeList'; import { unit, px } from '../../../../style/variables'; import { FilterTitleButton } from './FilterTitleButton'; -const Popover = styled(EuiPopover).attrs({ - anchorClassName: 'anchor' -})` +const Popover = styled((EuiPopover as unknown) as FunctionComponent).attrs( + () => ({ + anchorClassName: 'anchor' + }) +)` .anchor { display: block; } diff --git a/x-pack/legacy/plugins/apm/public/components/shared/Stacktrace/__test__/Stackframe.test.tsx b/x-pack/legacy/plugins/apm/public/components/shared/Stacktrace/__test__/Stackframe.test.tsx index 5f6519b7c7b96..b485b4f844f64 100644 --- a/x-pack/legacy/plugins/apm/public/components/shared/Stacktrace/__test__/Stackframe.test.tsx +++ b/x-pack/legacy/plugins/apm/public/components/shared/Stacktrace/__test__/Stackframe.test.tsx @@ -5,7 +5,6 @@ */ import { mount, ReactWrapper, shallow } from 'enzyme'; -import 'jest-styled-components'; import React from 'react'; import { IStackframe } from '../../../../../typings/es_schemas/raw/fields/Stackframe'; import { Stackframe } from '../Stackframe'; diff --git a/x-pack/legacy/plugins/apm/public/components/shared/Stacktrace/__test__/__snapshots__/Stackframe.test.tsx.snap b/x-pack/legacy/plugins/apm/public/components/shared/Stacktrace/__test__/__snapshots__/Stackframe.test.tsx.snap index 55cec7389dc5c..5b17b124a321d 100644 --- a/x-pack/legacy/plugins/apm/public/components/shared/Stacktrace/__test__/__snapshots__/Stackframe.test.tsx.snap +++ b/x-pack/legacy/plugins/apm/public/components/shared/Stacktrace/__test__/__snapshots__/Stackframe.test.tsx.snap @@ -394,8 +394,72 @@ exports[`Stackframe when stackframe has source lines should render correctly 1`] className="c8" > + url.full - + } delay="regular" position="top" @@ -59,9 +59,9 @@ exports[`StickyProperties should render entire component 1`] = ` + http.request.method - + } delay="regular" position="top" @@ -88,9 +88,9 @@ exports[`StickyProperties should render entire component 1`] = ` + error.exception.handled - + } delay="regular" position="top" @@ -117,9 +117,9 @@ exports[`StickyProperties should render entire component 1`] = ` + user.id - + } delay="regular" position="top" diff --git a/x-pack/legacy/plugins/apm/public/components/shared/charts/CustomPlot/test/__snapshots__/CustomPlot.test.js.snap b/x-pack/legacy/plugins/apm/public/components/shared/charts/CustomPlot/test/__snapshots__/CustomPlot.test.js.snap index aeef8ed995e92..ff917dd95bf96 100644 --- a/x-pack/legacy/plugins/apm/public/components/shared/charts/CustomPlot/test/__snapshots__/CustomPlot.test.js.snap +++ b/x-pack/legacy/plugins/apm/public/components/shared/charts/CustomPlot/test/__snapshots__/CustomPlot.test.js.snap @@ -6,28 +6,28 @@ Array [ "color": "#3185fc", "disabled": undefined, "onClick": [Function], - "text": + "text": Avg. - + 468 ms - - , + + , }, Object { "color": "#e6c220", "disabled": undefined, "onClick": [Function], - "text": + "text": 95th percentile - , + , }, Object { "color": "#f98510", "disabled": undefined, "onClick": [Function], - "text": + "text": 99th percentile - , + , }, ] `; @@ -2703,66 +2703,112 @@ Array [ display: inline-block; } -
+
- - - Avg. - - 468 ms - - -
-
- - + + + + + Avg. + + + 468 ms + + + + +
+
+ - 95th percentile - -
-
- - + + + + + + 95th percentile + + +
+ + - 99th percentile - +
+ + + + + + 99th percentile + + +
+
- , + , ] `; @@ -5077,85 +5123,159 @@ Array [ } } > -
+
- 1502283720 -
-
-
-
- - Avg. -
-
- 438704.4 -
-
-
-
- - 95th -
+
- 1557383.999999999 + 1502283720
-
-
+ +
- - 99th + +
+ + +
+ + + + Avg. +
+
+
+ +
+ 438704.4 +
+
+
+
+ +
+ + +
+ + + + 95th +
+
+
+ +
+ 1557383.999999999 +
+
+
+
+ +
+ + +
+ + + + 99th +
+
+
+ +
+ 1820377.1200000006 +
+
+
+
+
+
- 1820377.1200000006 -
-
+ className="c10" + /> +
-
-
+
@@ -5740,66 +5860,112 @@ Array [ display: inline-block; } -
+
- - - Avg. - - 468 ms - - -
-
- - + + + + + Avg. + + + 468 ms + + + + +
+
+ - 95th percentile - -
-
- - + + + + + + 95th percentile + + +
+ + - 99th percentile - +
+ + + + + + 99th percentile + + +
+
- , + , ] `; diff --git a/x-pack/legacy/plugins/apm/public/components/shared/charts/Histogram/__test__/__snapshots__/Histogram.test.js.snap b/x-pack/legacy/plugins/apm/public/components/shared/charts/Histogram/__test__/__snapshots__/Histogram.test.js.snap index 468116b84b6bb..da71e264ac099 100644 --- a/x-pack/legacy/plugins/apm/public/components/shared/charts/Histogram/__test__/__snapshots__/Histogram.test.js.snap +++ b/x-pack/legacy/plugins/apm/public/components/shared/charts/Histogram/__test__/__snapshots__/Histogram.test.js.snap @@ -19,1400 +19,1402 @@ exports[`Histogram Initially should have default markup 1`] = ` } } > -
+
- - - - - - - + - + + + + + - - + - - - 0 ms - - - - - + + 0 ms + + + - 500 ms - - - - - + + 500 ms + + + - 1,000 ms - - - - - + + 1,000 ms + + + - 1,500 ms - - - - - + + 1,500 ms + + + - 2,000 ms - - - - - + + 2,000 ms + + + - 2,500 ms - - - - - + + 2,500 ms + + + - 3,000 ms - + + + 3,000 ms + + - - - - - 0.0 occ. - - - - - + + 0.0 occ. + + + - 27.5 occ. - - - - - + + 27.5 occ. + + + - 55.0 occ. - + + + 55.0 occ. + + - - - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + /> + + +
- + `; @@ -1467,26 +1469,36 @@ exports[`Histogram when hovering over a non-empty bucket should have correct mar } } > -
-
- 811 - 927 ms -
+
-
- 49.0 occurrences -
+ +
+ 811 - 927 ms +
+
+ +
+ +
+ 49.0 occurrences +
+
+
+
+ +
+
-
-
+
`; diff --git a/x-pack/legacy/plugins/apm/public/components/shared/charts/Timeline/__test__/__snapshots__/Timeline.test.js.snap b/x-pack/legacy/plugins/apm/public/components/shared/charts/Timeline/__test__/__snapshots__/Timeline.test.js.snap index c1bde70f93429..80baba28fcfdf 100644 --- a/x-pack/legacy/plugins/apm/public/components/shared/charts/Timeline/__test__/__snapshots__/Timeline.test.js.snap +++ b/x-pack/legacy/plugins/apm/public/components/shared/charts/Timeline/__test__/__snapshots__/Timeline.test.js.snap @@ -540,19 +540,32 @@ exports[`Timeline should render with data 1`] = ` onMouseOut={[Function]} onMouseOver={[Function]} > -
- -
+
+ + + +
+
-
- -
+
+ + + +
+
-
- -
+
+ + + +
+
diff --git a/x-pack/legacy/plugins/apm/public/components/shared/charts/TransactionCharts/BrowserLineChart.test.tsx b/x-pack/legacy/plugins/apm/public/components/shared/charts/TransactionCharts/BrowserLineChart.test.tsx new file mode 100644 index 0000000000000..e95f733fb4bc8 --- /dev/null +++ b/x-pack/legacy/plugins/apm/public/components/shared/charts/TransactionCharts/BrowserLineChart.test.tsx @@ -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 React from 'react'; +import { shallow } from 'enzyme'; +import { BrowserLineChart } from './BrowserLineChart'; + +describe('BrowserLineChart', () => { + describe('render', () => { + it('renders', () => { + expect(() => shallow()).not.toThrowError(); + }); + }); +}); diff --git a/x-pack/legacy/plugins/apm/public/components/shared/charts/TransactionCharts/BrowserLineChart.tsx b/x-pack/legacy/plugins/apm/public/components/shared/charts/TransactionCharts/BrowserLineChart.tsx new file mode 100644 index 0000000000000..58bc4655f730c --- /dev/null +++ b/x-pack/legacy/plugins/apm/public/components/shared/charts/TransactionCharts/BrowserLineChart.tsx @@ -0,0 +1,45 @@ +/* + * 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 { i18n } from '@kbn/i18n'; +import { EuiTitle } from '@elastic/eui'; +import { TransactionLineChart } from './TransactionLineChart'; +import { + getMaxY, + getResponseTimeTickFormatter, + getResponseTimeTooltipFormatter +} from '.'; +import { getDurationFormatter } from '../../../../utils/formatters'; +import { useAvgDurationByBrowser } from '../../../../hooks/useAvgDurationByBrowser'; + +export function BrowserLineChart() { + const { data } = useAvgDurationByBrowser(); + const maxY = getMaxY(data); + const formatter = getDurationFormatter(maxY); + const formatTooltipValue = getResponseTimeTooltipFormatter(formatter); + const tickFormatY = getResponseTimeTickFormatter(formatter); + + return ( + <> + + + {i18n.translate( + 'xpack.apm.metrics.pageLoadCharts.avgPageLoadByBrowser', + { + defaultMessage: 'Avg. page load duration distribution by browser' + } + )} + + + + + ); +} diff --git a/x-pack/legacy/plugins/apm/public/components/shared/charts/TransactionCharts/DurationByCountryMap/index.tsx b/x-pack/legacy/plugins/apm/public/components/shared/charts/TransactionCharts/DurationByCountryMap/index.tsx index 6176397170797..bea858d1358c5 100644 --- a/x-pack/legacy/plugins/apm/public/components/shared/charts/TransactionCharts/DurationByCountryMap/index.tsx +++ b/x-pack/legacy/plugins/apm/public/components/shared/charts/TransactionCharts/DurationByCountryMap/index.tsx @@ -4,33 +4,30 @@ * you may not use this file except in compliance with the Elastic License. */ -import { EuiFlexGrid, EuiFlexItem, EuiPanel, EuiTitle } from '@elastic/eui'; +import { EuiTitle } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import React from 'react'; import { useAvgDurationByCountry } from '../../../../../hooks/useAvgDurationByCountry'; + import { ChoroplethMap } from '../ChoroplethMap'; export const DurationByCountryMap: React.SFC = () => { const { data } = useAvgDurationByCountry(); return ( - - - - - - {i18n.translate( - 'xpack.apm.metrics.durationByCountryMap.avgPageLoadByCountryLabel', - { - defaultMessage: - 'Avg. page load duration distribution by country' - } - )} - - - - - - + <> + {' '} + + + {i18n.translate( + 'xpack.apm.metrics.durationByCountryMap.avgPageLoadByCountryLabel', + { + defaultMessage: 'Avg. page load duration distribution by country' + } + )} + + + + ); }; diff --git a/x-pack/legacy/plugins/apm/public/components/shared/charts/TransactionCharts/index.tsx b/x-pack/legacy/plugins/apm/public/components/shared/charts/TransactionCharts/index.tsx index c032d60359903..97794bf66687b 100644 --- a/x-pack/legacy/plugins/apm/public/components/shared/charts/TransactionCharts/index.tsx +++ b/x-pack/legacy/plugins/apm/public/components/shared/charts/TransactionCharts/index.tsx @@ -33,6 +33,7 @@ import { MLJobLink } from '../../Links/MachineLearningLinks/MLJobLink'; import { LicenseContext } from '../../../../context/LicenseContext'; import { TransactionLineChart } from './TransactionLineChart'; import { isValidCoordinateValue } from '../../../../utils/isValidCoordinateValue'; +import { BrowserLineChart } from './BrowserLineChart'; import { DurationByCountryMap } from './DurationByCountryMap'; import { TRANSACTION_PAGE_LOAD, @@ -59,31 +60,29 @@ const ShiftedEuiText = styled(EuiText)` top: 5px; `; -export class TransactionCharts extends Component { - public getMaxY = (responseTimeSeries: TimeSeries[]) => { - const coordinates = flatten( - responseTimeSeries.map((serie: TimeSeries) => serie.data as Coordinate[]) - ); - - const numbers: number[] = coordinates.map((c: Coordinate) => - c.y ? c.y : 0 - ); +export function getResponseTimeTickFormatter(formatter: TimeFormatter) { + return (t: number) => formatter(t).formatted; +} - return Math.max(...numbers, 0); +export function getResponseTimeTooltipFormatter(formatter: TimeFormatter) { + return (p: Coordinate) => { + return isValidCoordinateValue(p.y) + ? formatter(p.y).formatted + : NOT_AVAILABLE_LABEL; }; +} - public getResponseTimeTickFormatter = (formatter: TimeFormatter) => { - return (t: number) => formatter(t).formatted; - }; +export function getMaxY(responseTimeSeries: TimeSeries[]) { + const coordinates = flatten( + responseTimeSeries.map((serie: TimeSeries) => serie.data as Coordinate[]) + ); - public getResponseTimeTooltipFormatter = (formatter: TimeFormatter) => { - return (p: Coordinate) => { - return isValidCoordinateValue(p.y) - ? formatter(p.y).formatted - : NOT_AVAILABLE_LABEL; - }; - }; + const numbers: number[] = coordinates.map((c: Coordinate) => (c.y ? c.y : 0)); + return Math.max(...numbers, 0); +} + +export class TransactionCharts extends Component { public getTPMFormatter = (t: number) => { const { urlParams } = this.props; const unit = tpmUnit(urlParams.transactionType); @@ -154,7 +153,7 @@ export class TransactionCharts extends Component { const { charts, urlParams } = this.props; const { responseTimeSeries, tpmSeries } = charts; const { transactionType } = urlParams; - const maxY = this.getMaxY(responseTimeSeries); + const maxY = getMaxY(responseTimeSeries); const formatter = getDurationFormatter(maxY); return ( @@ -177,8 +176,8 @@ export class TransactionCharts extends Component { @@ -205,7 +204,18 @@ export class TransactionCharts extends Component { {transactionType === TRANSACTION_PAGE_LOAD && ( <> - + + + + + + + + + + + + )} diff --git a/x-pack/legacy/plugins/apm/public/context/UrlParamsContext/helpers.ts b/x-pack/legacy/plugins/apm/public/context/UrlParamsContext/helpers.ts index 5fa9294a95dfd..1806e7395a8cc 100644 --- a/x-pack/legacy/plugins/apm/public/context/UrlParamsContext/helpers.ts +++ b/x-pack/legacy/plugins/apm/public/context/UrlParamsContext/helpers.ts @@ -83,24 +83,24 @@ export function getPathParams(pathname: string = ''): PathParams { switch (servicePageName) { case 'transactions': return { - processorEvent: 'transaction', + processorEvent: ProcessorEvent.transaction, serviceName }; case 'errors': return { - processorEvent: 'error', + processorEvent: ProcessorEvent.error, serviceName, errorGroupId: paths[3] }; case 'metrics': return { - processorEvent: 'metric', + processorEvent: ProcessorEvent.metric, serviceName, serviceNodeName }; case 'nodes': return { - processorEvent: 'metric', + processorEvent: ProcessorEvent.metric, serviceName }; case 'service-map': @@ -113,7 +113,7 @@ export function getPathParams(pathname: string = ''): PathParams { case 'traces': return { - processorEvent: 'transaction' + processorEvent: ProcessorEvent.transaction }; default: return {}; diff --git a/x-pack/legacy/plugins/apm/public/hooks/useAvgDurationByBrowser.test.ts b/x-pack/legacy/plugins/apm/public/hooks/useAvgDurationByBrowser.test.ts new file mode 100644 index 0000000000000..38f26c2ba9fbd --- /dev/null +++ b/x-pack/legacy/plugins/apm/public/hooks/useAvgDurationByBrowser.test.ts @@ -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 { renderHook } from 'react-hooks-testing-library'; +import theme from '@elastic/eui/dist/eui_theme_light.json'; +import * as useFetcherModule from './useFetcher'; +import { useAvgDurationByBrowser } from './useAvgDurationByBrowser'; + +describe('useAvgDurationByBrowser', () => { + it('returns data', () => { + const data = [ + { title: 'Other', data: [{ x: 1572530100000, y: 130010.8947368421 }] } + ]; + jest.spyOn(useFetcherModule, 'useFetcher').mockReturnValueOnce({ + data, + refetch: () => {}, + status: 'success' as useFetcherModule.FETCH_STATUS + }); + const { result } = renderHook(() => useAvgDurationByBrowser()); + + expect(result.current.data).toEqual([ + { + color: theme.euiColorVis0, + data: [{ x: 1572530100000, y: 130010.8947368421 }], + title: 'Other', + type: 'linemark' + } + ]); + }); +}); diff --git a/x-pack/legacy/plugins/apm/public/hooks/useAvgDurationByBrowser.ts b/x-pack/legacy/plugins/apm/public/hooks/useAvgDurationByBrowser.ts new file mode 100644 index 0000000000000..a1e9294455d54 --- /dev/null +++ b/x-pack/legacy/plugins/apm/public/hooks/useAvgDurationByBrowser.ts @@ -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 theme from '@elastic/eui/dist/eui_theme_light.json'; +import { useFetcher } from './useFetcher'; +import { useUrlParams } from './useUrlParams'; +import { AvgDurationByBrowserAPIResponse } from '../../server/lib/transactions/avg_duration_by_browser'; +import { TimeSeries } from '../../typings/timeseries'; +import { getVizColorForIndex } from '../../common/viz_colors'; + +function toTimeSeries(data?: AvgDurationByBrowserAPIResponse): TimeSeries[] { + if (!data) { + return []; + } + + return data.map((item, index) => { + return { + ...item, + color: getVizColorForIndex(index, theme), + type: 'linemark' + }; + }); +} + +export function useAvgDurationByBrowser() { + const { + urlParams: { serviceName, start, end, transactionName }, + uiFilters + } = useUrlParams(); + + const { data, error, status } = useFetcher( + callApmApi => { + if (serviceName && start && end) { + return callApmApi({ + pathname: + '/api/apm/services/{serviceName}/transaction_groups/avg_duration_by_browser', + params: { + path: { serviceName }, + query: { + start, + end, + transactionName, + uiFilters: JSON.stringify(uiFilters) + } + } + }); + } + }, + [serviceName, start, end, transactionName, uiFilters] + ); + + return { + data: toTimeSeries(data), + status, + error + }; +} diff --git a/x-pack/legacy/plugins/apm/public/index.tsx b/x-pack/legacy/plugins/apm/public/index.tsx index 7d6fa70f025aa..8fd3cb0893dea 100644 --- a/x-pack/legacy/plugins/apm/public/index.tsx +++ b/x-pack/legacy/plugins/apm/public/index.tsx @@ -4,33 +4,43 @@ * you may not use this file except in compliance with the Elastic License. */ -import React from 'react'; -import ReactDOM from 'react-dom'; import { npStart } from 'ui/new_platform'; import 'react-vis/dist/style.css'; import 'ui/autoload/all'; import chrome from 'ui/chrome'; +import { i18n } from '@kbn/i18n'; +import url from 'url'; + // @ts-ignore import { uiModules } from 'ui/modules'; -import { GlobalHelpExtension } from './components/app/GlobalHelpExtension'; import { plugin } from './new-platform'; import { REACT_APP_ROOT_ID } from './new-platform/plugin'; import './style/global_overrides.css'; import template from './templates/index.html'; -import { KibanaCoreContextProvider } from '../../observability/public'; + const { core } = npStart; // render APM feedback link in global help menu -core.chrome.setHelpExtension(domElement => { - ReactDOM.render( - - - , - domElement - ); - return () => { - ReactDOM.unmountComponentAtNode(domElement); - }; +core.chrome.setHelpExtension({ + appName: i18n.translate('xpack.apm.feedbackMenu.appName', { + defaultMessage: 'APM' + }), + links: [ + { + linkType: 'discuss', + href: 'https://discuss.elastic.co/c/apm' + }, + { + linkType: 'custom', + href: url.format({ + pathname: core.http.basePath.prepend('/app/kibana'), + hash: '/management/elasticsearch/upgrade_assistant' + }), + content: i18n.translate('xpack.apm.helpMenu.upgradeAssistantLink', { + defaultMessage: 'Upgrade assistant' + }) + } + ] }); // @ts-ignore diff --git a/x-pack/legacy/plugins/apm/public/utils/testHelpers.tsx b/x-pack/legacy/plugins/apm/public/utils/testHelpers.tsx index 60a5f7172b956..751756146b8fe 100644 --- a/x-pack/legacy/plugins/apm/public/utils/testHelpers.tsx +++ b/x-pack/legacy/plugins/apm/public/utils/testHelpers.tsx @@ -9,7 +9,6 @@ import { ReactWrapper } from 'enzyme'; import enzymeToJson from 'enzyme-to-json'; import { Location } from 'history'; -import 'jest-styled-components'; import moment from 'moment'; import { Moment } from 'moment-timezone'; import React from 'react'; diff --git a/x-pack/legacy/plugins/apm/server/lib/metrics/by_agent/java/gc/fetchAndTransformGcMetrics.ts b/x-pack/legacy/plugins/apm/server/lib/metrics/by_agent/java/gc/fetchAndTransformGcMetrics.ts index 180537d68a2a2..8cff6e5d3aa80 100644 --- a/x-pack/legacy/plugins/apm/server/lib/metrics/by_agent/java/gc/fetchAndTransformGcMetrics.ts +++ b/x-pack/legacy/plugins/apm/server/lib/metrics/by_agent/java/gc/fetchAndTransformGcMetrics.ts @@ -23,16 +23,7 @@ import { METRIC_JAVA_GC_TIME } from '../../../../../../common/elasticsearch_fieldnames'; import { getBucketSize } from '../../../../helpers/get_bucket_size'; - -const colors = [ - theme.euiColorVis0, - theme.euiColorVis1, - theme.euiColorVis2, - theme.euiColorVis3, - theme.euiColorVis4, - theme.euiColorVis5, - theme.euiColorVis6 -]; +import { getVizColorForIndex } from '../../../../../../common/viz_colors'; export async function fetchAndTransformGcMetrics({ setup, @@ -148,7 +139,7 @@ export async function fetchAndTransformGcMetrics({ title: label, key: label, type: chartBase.type, - color: colors[i], + color: getVizColorForIndex(i, theme), overallValue, data }; diff --git a/x-pack/legacy/plugins/apm/server/lib/metrics/transform_metrics_chart.ts b/x-pack/legacy/plugins/apm/server/lib/metrics/transform_metrics_chart.ts index 1e7f197435a67..03f21e4f26e7b 100644 --- a/x-pack/legacy/plugins/apm/server/lib/metrics/transform_metrics_chart.ts +++ b/x-pack/legacy/plugins/apm/server/lib/metrics/transform_metrics_chart.ts @@ -11,16 +11,7 @@ import { ESSearchRequest } from '../../../typings/elasticsearch'; import { AggregationOptionsByType } from '../../../typings/elasticsearch/aggregations'; - -const colors = [ - theme.euiColorVis0, - theme.euiColorVis1, - theme.euiColorVis2, - theme.euiColorVis3, - theme.euiColorVis4, - theme.euiColorVis5, - theme.euiColorVis6 -]; +import { getVizColorForIndex } from '../../../common/viz_colors'; export type GenericMetricsChart = ReturnType< typeof transformDataToMetricsChart @@ -66,7 +57,8 @@ export function transformDataToMetricsChart( title: chartBase.series[seriesKey].title, key: seriesKey, type: chartBase.type, - color: chartBase.series[seriesKey].color || colors[i], + color: + chartBase.series[seriesKey].color || getVizColorForIndex(i, theme), overallValue, data: timeseriesData?.buckets.map(bucket => { diff --git a/x-pack/legacy/plugins/apm/server/lib/transactions/avg_duration_by_browser/__fixtures__/responses.ts b/x-pack/legacy/plugins/apm/server/lib/transactions/avg_duration_by_browser/__fixtures__/responses.ts new file mode 100644 index 0000000000000..3f0f8a84dc62f --- /dev/null +++ b/x-pack/legacy/plugins/apm/server/lib/transactions/avg_duration_by_browser/__fixtures__/responses.ts @@ -0,0 +1,74 @@ +/* + * 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 { + ESSearchResponse, + ESSearchRequest +} from '../../../../../typings/elasticsearch'; + +export const response = ({ + hits: { + total: 599, + max_score: 0, + hits: [] + }, + took: 4, + timed_out: false, + _shards: { + total: 1, + successful: 1, + skipped: 0, + failed: 0 + }, + aggregations: { + user_agent_keys: { + buckets: [{ key: 'Firefox' }, { key: 'Other' }] + }, + browsers: { + buckets: [ + { + key_as_string: '2019-10-21T04:38:20.000-05:00', + key: 1571650700000, + doc_count: 0, + user_agent: { + doc_count_error_upper_bound: 0, + sum_other_doc_count: 0, + buckets: [] + } + }, + { + key_as_string: '2019-10-21T04:40:00.000-05:00', + key: 1571650800000, + doc_count: 1, + user_agent: { + doc_count_error_upper_bound: 0, + sum_other_doc_count: 0, + buckets: [ + { + key: 'Other', + doc_count: 1, + avg_duration: { + value: 860425.0 + } + }, + { + key: 'Firefox', + doc_count: 10, + avg_duration: { + value: 86425.1 + } + } + ] + } + } + ] + } + } +} as unknown) as ESSearchResponse< + unknown, + ESSearchRequest, + { restTotalHitsAsInt: false } +>; diff --git a/x-pack/legacy/plugins/apm/server/lib/transactions/avg_duration_by_browser/fetcher.test.ts b/x-pack/legacy/plugins/apm/server/lib/transactions/avg_duration_by_browser/fetcher.test.ts new file mode 100644 index 0000000000000..f2227524db081 --- /dev/null +++ b/x-pack/legacy/plugins/apm/server/lib/transactions/avg_duration_by_browser/fetcher.test.ts @@ -0,0 +1,23 @@ +/* + * 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 { Setup } from '../../helpers/setup_request'; +import { fetcher } from './fetcher'; + +describe('fetcher', () => { + it('performs a search', async () => { + const search = jest.fn(); + const setup = ({ + client: { search }, + indices: {}, + uiFiltersES: [] + } as unknown) as Setup; + + await fetcher({ serviceName: 'testServiceName', setup }); + + expect(search).toHaveBeenCalled(); + }); +}); diff --git a/x-pack/legacy/plugins/apm/server/lib/transactions/avg_duration_by_browser/fetcher.ts b/x-pack/legacy/plugins/apm/server/lib/transactions/avg_duration_by_browser/fetcher.ts new file mode 100644 index 0000000000000..8a96a25aef50e --- /dev/null +++ b/x-pack/legacy/plugins/apm/server/lib/transactions/avg_duration_by_browser/fetcher.ts @@ -0,0 +1,78 @@ +/* + * 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 { ESFilter } from '../../../../typings/elasticsearch'; +import { PromiseReturnType } from '../../../../typings/common'; +import { + PROCESSOR_EVENT, + SERVICE_NAME, + TRANSACTION_TYPE, + USER_AGENT_NAME, + TRANSACTION_DURATION +} from '../../../../common/elasticsearch_fieldnames'; +import { rangeFilter } from '../../helpers/range_filter'; +import { getBucketSize } from '../../helpers/get_bucket_size'; +import { Options } from '.'; +import { TRANSACTION_PAGE_LOAD } from '../../../../common/transaction_types'; +import { ProcessorEvent } from '../../../../common/processor_event'; + +export type ESResponse = PromiseReturnType; + +export function fetcher(options: Options) { + const { end, client, indices, start, uiFiltersES } = options.setup; + const { serviceName } = options; + const { intervalString } = getBucketSize(start, end, 'auto'); + + const filter: ESFilter[] = [ + { term: { [PROCESSOR_EVENT]: ProcessorEvent.transaction } }, + { term: { [SERVICE_NAME]: serviceName } }, + { term: { [TRANSACTION_TYPE]: TRANSACTION_PAGE_LOAD } }, + { range: rangeFilter(start, end) }, + ...uiFiltersES + ]; + + const params = { + index: indices['apm_oss.transactionIndices'], + body: { + size: 0, + query: { bool: { filter } }, + aggs: { + user_agent_keys: { + terms: { + field: USER_AGENT_NAME + } + }, + browsers: { + date_histogram: { + extended_bounds: { + max: end, + min: start + }, + field: '@timestamp', + fixed_interval: intervalString, + min_doc_count: 0 + }, + aggs: { + user_agent: { + terms: { + field: USER_AGENT_NAME + }, + aggs: { + avg_duration: { + avg: { + field: TRANSACTION_DURATION + } + } + } + } + } + } + } + } + }; + + return client.search(params); +} diff --git a/x-pack/legacy/plugins/apm/server/lib/transactions/avg_duration_by_browser/index.test.ts b/x-pack/legacy/plugins/apm/server/lib/transactions/avg_duration_by_browser/index.test.ts new file mode 100644 index 0000000000000..fe103ade24161 --- /dev/null +++ b/x-pack/legacy/plugins/apm/server/lib/transactions/avg_duration_by_browser/index.test.ts @@ -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 { + getTransactionAvgDurationByBrowser, + Options, + AvgDurationByBrowserAPIResponse +} from '.'; +import * as transformerModule from './transformer'; +import * as fetcherModule from './fetcher'; +import { response } from './__fixtures__/responses'; + +describe('getAvgDurationByBrowser', () => { + it('returns a transformed response', async () => { + const transformer = jest + .spyOn(transformerModule, 'transformer') + .mockReturnValueOnce(({} as unknown) as AvgDurationByBrowserAPIResponse); + const search = () => {}; + const options = ({ + setup: { client: { search }, indices: {}, uiFiltersES: [] } + } as unknown) as Options; + jest + .spyOn<{ fetcher: any }, 'fetcher'>(fetcherModule, 'fetcher') + .mockResolvedValueOnce(response); + + await getTransactionAvgDurationByBrowser(options); + + expect(transformer).toHaveBeenCalledWith({ response }); + }); +}); diff --git a/x-pack/legacy/plugins/apm/server/lib/transactions/avg_duration_by_browser/index.ts b/x-pack/legacy/plugins/apm/server/lib/transactions/avg_duration_by_browser/index.ts new file mode 100644 index 0000000000000..57b3c8cbe9f93 --- /dev/null +++ b/x-pack/legacy/plugins/apm/server/lib/transactions/avg_duration_by_browser/index.ts @@ -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 { Coordinate } from '../../../../typings/timeseries'; +import { Setup } from '../../helpers/setup_request'; +import { fetcher } from './fetcher'; +import { transformer } from './transformer'; + +export interface Options { + serviceName: string; + setup: Setup; +} + +export type AvgDurationByBrowserAPIResponse = Array<{ + data: Coordinate[]; + title: string; +}>; + +export async function getTransactionAvgDurationByBrowser(options: Options) { + return transformer({ response: await fetcher(options) }); +} diff --git a/x-pack/legacy/plugins/apm/server/lib/transactions/avg_duration_by_browser/transformer.test.ts b/x-pack/legacy/plugins/apm/server/lib/transactions/avg_duration_by_browser/transformer.test.ts new file mode 100644 index 0000000000000..5caec12c81d5d --- /dev/null +++ b/x-pack/legacy/plugins/apm/server/lib/transactions/avg_duration_by_browser/transformer.test.ts @@ -0,0 +1,29 @@ +/* + * 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 { transformer } from './transformer'; +import { response } from './__fixtures__/responses'; + +describe('transformer', () => { + it('transforms', () => { + expect(transformer({ response })).toEqual([ + { + data: [ + { x: 1571650700000, y: undefined }, + { x: 1571650800000, y: 86425.1 } + ], + title: 'Firefox' + }, + { + data: [ + { x: 1571650700000, y: undefined }, + { x: 1571650800000, y: 860425.0 } + ], + title: 'Other' + } + ]); + }); +}); diff --git a/x-pack/legacy/plugins/apm/server/lib/transactions/avg_duration_by_browser/transformer.ts b/x-pack/legacy/plugins/apm/server/lib/transactions/avg_duration_by_browser/transformer.ts new file mode 100644 index 0000000000000..805f8f192bdb1 --- /dev/null +++ b/x-pack/legacy/plugins/apm/server/lib/transactions/avg_duration_by_browser/transformer.ts @@ -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 { ESResponse } from './fetcher'; +import { AvgDurationByBrowserAPIResponse } from '.'; +import { Coordinate } from '../../../../typings/timeseries'; + +export function transformer({ + response +}: { + response: ESResponse; +}): AvgDurationByBrowserAPIResponse { + const allUserAgentKeys = new Set( + // TODO(TS-3.7-ESLINT) + // eslint-disable-next-line @typescript-eslint/camelcase + (response.aggregations?.user_agent_keys?.buckets ?? []).map(({ key }) => + key.toString() + ) + ); + const buckets = response.aggregations?.browsers?.buckets ?? []; + + const series = buckets.reduce<{ [key: string]: Coordinate[] }>( + (acc, next) => { + const userAgentBuckets = next.user_agent?.buckets ?? []; + const x = next.key; + const seenUserAgentKeys = new Set(); + + userAgentBuckets.map(userAgentBucket => { + const key = userAgentBucket.key; + const y = userAgentBucket.avg_duration?.value; + + seenUserAgentKeys.add(key.toString()); + acc[key] = (acc[key] || []).concat({ x, y }); + }); + + const emptyUserAgents = new Set( + [...allUserAgentKeys].filter(key => !seenUserAgentKeys.has(key)) + ); + + // If no user agent requests exist for this bucked, fill in the data with + // undefined + [...emptyUserAgents].map(key => { + acc[key] = (acc[key] || []).concat({ x, y: undefined }); + }); + + return acc; + }, + {} + ); + + return Object.entries(series).map(([title, data]) => ({ title, data })); +} diff --git a/x-pack/legacy/plugins/apm/server/lib/transactions/breakdown/constants.ts b/x-pack/legacy/plugins/apm/server/lib/transactions/breakdown/constants.ts index 0e288de1e4600..dcf6e8e07c45b 100644 --- a/x-pack/legacy/plugins/apm/server/lib/transactions/breakdown/constants.ts +++ b/x-pack/legacy/plugins/apm/server/lib/transactions/breakdown/constants.ts @@ -3,19 +3,5 @@ * or more contributor license agreements. Licensed under the Elastic License; * you may not use this file except in compliance with the Elastic License. */ -import theme from '@elastic/eui/dist/eui_theme_light.json'; export const MAX_KPIS = 20; - -export const COLORS = [ - theme.euiColorVis0, - theme.euiColorVis1, - theme.euiColorVis2, - theme.euiColorVis3, - theme.euiColorVis4, - theme.euiColorVis5, - theme.euiColorVis6, - theme.euiColorVis7, - theme.euiColorVis8, - theme.euiColorVis9 -]; diff --git a/x-pack/legacy/plugins/apm/server/lib/transactions/breakdown/index.ts b/x-pack/legacy/plugins/apm/server/lib/transactions/breakdown/index.ts index 3166938090d8f..12f6694116950 100644 --- a/x-pack/legacy/plugins/apm/server/lib/transactions/breakdown/index.ts +++ b/x-pack/legacy/plugins/apm/server/lib/transactions/breakdown/index.ts @@ -18,7 +18,8 @@ import { import { Setup } from '../../helpers/setup_request'; import { rangeFilter } from '../../helpers/range_filter'; import { getMetricsDateHistogramParams } from '../../helpers/metrics'; -import { MAX_KPIS, COLORS } from './constants'; +import { MAX_KPIS } from './constants'; +import { getVizColorForIndex } from '../../../../common/viz_colors'; export async function getTransactionBreakdown({ setup, @@ -142,7 +143,7 @@ export async function getTransactionBreakdown({ const kpis = sortByOrder(visibleKpis, 'name').map((kpi, index) => { return { ...kpi, - color: COLORS[index % COLORS.length] + color: getVizColorForIndex(index) }; }); diff --git a/x-pack/legacy/plugins/apm/server/routes/create_apm_api.ts b/x-pack/legacy/plugins/apm/server/routes/create_apm_api.ts index c35b66b453634..1735aa9da7dca 100644 --- a/x-pack/legacy/plugins/apm/server/routes/create_apm_api.ts +++ b/x-pack/legacy/plugins/apm/server/routes/create_apm_api.ts @@ -42,7 +42,8 @@ import { transactionGroupsChartsRoute, transactionGroupsDistributionRoute, transactionGroupsRoute, - transactionGroupsAvgDurationByCountry + transactionGroupsAvgDurationByCountry, + transactionGroupsAvgDurationByBrowser } from './transaction_groups'; import { errorGroupsLocalFiltersRoute, @@ -102,6 +103,7 @@ const createApmApi = () => { .add(transactionGroupsChartsRoute) .add(transactionGroupsDistributionRoute) .add(transactionGroupsRoute) + .add(transactionGroupsAvgDurationByBrowser) .add(transactionGroupsAvgDurationByCountry) // UI filters diff --git a/x-pack/legacy/plugins/apm/server/routes/transaction_groups.ts b/x-pack/legacy/plugins/apm/server/routes/transaction_groups.ts index 0b5c29fc29857..269f5fee9738c 100644 --- a/x-pack/legacy/plugins/apm/server/routes/transaction_groups.ts +++ b/x-pack/legacy/plugins/apm/server/routes/transaction_groups.ts @@ -12,6 +12,7 @@ import { getTransactionBreakdown } from '../lib/transactions/breakdown'; import { getTransactionGroupList } from '../lib/transaction_groups'; import { createRoute } from './create_route'; import { uiFiltersRt, rangeRt } from './default_api_types'; +import { getTransactionAvgDurationByBrowser } from '../lib/transactions/avg_duration_by_browser'; import { getTransactionAvgDurationByCountry } from '../lib/transactions/avg_duration_by_country'; export const transactionGroupsRoute = createRoute(() => ({ @@ -144,6 +145,32 @@ export const transactionGroupsBreakdownRoute = createRoute(() => ({ } })); +export const transactionGroupsAvgDurationByBrowser = createRoute(() => ({ + path: `/api/apm/services/{serviceName}/transaction_groups/avg_duration_by_browser`, + params: { + path: t.type({ + serviceName: t.string + }), + query: t.intersection([ + t.partial({ + transactionType: t.string, + transactionName: t.string + }), + uiFiltersRt, + rangeRt + ]) + }, + handler: async (req, { path }) => { + const setup = await setupRequest(req); + const { serviceName } = path; + + return getTransactionAvgDurationByBrowser({ + serviceName, + setup + }); + } +})); + export const transactionGroupsAvgDurationByCountry = createRoute(() => ({ path: `/api/apm/services/{serviceName}/transaction_groups/avg_duration_by_country`, params: { diff --git a/x-pack/legacy/plugins/beats_management/public/components/autocomplete_field/index.tsx b/x-pack/legacy/plugins/beats_management/public/components/autocomplete_field/index.tsx index 3ac2ff72c0116..4270a5ae1ec8d 100644 --- a/x-pack/legacy/plugins/beats_management/public/components/autocomplete_field/index.tsx +++ b/x-pack/legacy/plugins/beats_management/public/components/autocomplete_field/index.tsx @@ -275,10 +275,10 @@ const AutocompleteContainer = styled.div` position: relative; `; -const SuggestionsPanel = styled(EuiPanel).attrs({ +const SuggestionsPanel = styled(EuiPanel).attrs(() => ({ paddingSize: 'none', hasShadow: true, -})` +}))` position: absolute; width: 100%; margin-top: 2px; diff --git a/x-pack/legacy/plugins/beats_management/public/components/autocomplete_field/suggestion_item.tsx b/x-pack/legacy/plugins/beats_management/public/components/autocomplete_field/suggestion_item.tsx index 2ae475475829f..a90451c388d7a 100644 --- a/x-pack/legacy/plugins/beats_management/public/components/autocomplete_field/suggestion_item.tsx +++ b/x-pack/legacy/plugins/beats_management/public/components/autocomplete_field/suggestion_item.tsx @@ -57,7 +57,7 @@ const SuggestionItemField = styled.div` padding: ${props => props.theme.eui.default.euiSizeXs}; `; -const SuggestionItemIconField = SuggestionItemField.extend<{ suggestionType: string }>` +const SuggestionItemIconField = styled(SuggestionItemField)<{ suggestionType: string }>` background-color: ${props => { return tint(0.1, getEuiIconColor(props.theme, props.suggestionType)); }}; @@ -69,12 +69,12 @@ const SuggestionItemIconField = SuggestionItemField.extend<{ suggestionType: str width: ${props => props.theme.eui.default.euiSizeXl}; `; -const SuggestionItemTextField = SuggestionItemField.extend` +const SuggestionItemTextField = styled(SuggestionItemField)` flex: 2 0 0; font-family: ${props => props.theme.eui.default.euiCodeFontFamily}; `; -const SuggestionItemDescriptionField = SuggestionItemField.extend` +const SuggestionItemDescriptionField = styled(SuggestionItemField)` flex: 3 0 0; p { display: inline; diff --git a/x-pack/legacy/plugins/canvas/i18n/components.ts b/x-pack/legacy/plugins/canvas/i18n/components.ts index 5b9f6f00940f4..c898db7467b44 100644 --- a/x-pack/legacy/plugins/canvas/i18n/components.ts +++ b/x-pack/legacy/plugins/canvas/i18n/components.ts @@ -531,7 +531,7 @@ export const ComponentStrings = { }), getKeyboardShortcutsLinkLabel: () => i18n.translate('xpack.canvas.helpMenu.keyboardShortcutsLinkLabel', { - defaultMessage: 'Keyboard Shortcuts', + defaultMessage: 'Keyboard shortcuts', }), }, KeyboardShortcutsDoc: { @@ -547,7 +547,7 @@ export const ComponentStrings = { }), getTitle: () => i18n.translate('xpack.canvas.keyboardShortcutsDoc.flyoutHeaderTitle', { - defaultMessage: 'Keyboard Shortcuts', + defaultMessage: 'Keyboard shortcuts', }), }, Link: { diff --git a/x-pack/legacy/plugins/canvas/public/app.js b/x-pack/legacy/plugins/canvas/public/app.js index 0ba7385cf7a9e..760bb7a46f955 100644 --- a/x-pack/legacy/plugins/canvas/public/app.js +++ b/x-pack/legacy/plugins/canvas/public/app.js @@ -9,7 +9,9 @@ import './angular/config'; import './angular/services'; import React from 'react'; import ReactDOM from 'react-dom'; +import { i18n } from '@kbn/i18n'; import chrome from 'ui/chrome'; +import { documentationLinks } from './lib/documentation_links'; import { CanvasRootController } from './angular/controllers'; // Import the uiExports that the application uses @@ -19,7 +21,6 @@ import 'uiExports/visRequestHandlers'; import 'uiExports/visEditorTypes'; import 'uiExports/savedObjectTypes'; import 'uiExports/spyModes'; -import 'uiExports/fieldFormats'; import 'uiExports/embeddableFactories'; import 'uiExports/interpreter'; @@ -34,6 +35,17 @@ import { HelpMenu } from './components/help_menu/help_menu'; chrome.setRootController('canvas', CanvasRootController); // add Canvas docs to help menu in global nav -chrome.helpExtension.set(domNode => { - ReactDOM.render(, domNode); +chrome.helpExtension.set({ + appName: i18n.translate('xpack.canvas.helpMenu.appName', { + defaultMessage: 'Canvas', + }), + links: [ + { + linkType: 'documentation', + href: documentationLinks.canvas, + }, + ], + content: domNode => { + ReactDOM.render(, domNode); + }, }); diff --git a/x-pack/legacy/plugins/canvas/public/components/custom_element_modal/__examples__/__snapshots__/custom_element_modal.examples.storyshot b/x-pack/legacy/plugins/canvas/public/components/custom_element_modal/__examples__/__snapshots__/custom_element_modal.examples.storyshot index 134a3da5ec657..a42360d815176 100644 --- a/x-pack/legacy/plugins/canvas/public/components/custom_element_modal/__examples__/__snapshots__/custom_element_modal.examples.storyshot +++ b/x-pack/legacy/plugins/canvas/public/components/custom_element_modal/__examples__/__snapshots__/custom_element_modal.examples.storyshot @@ -246,8 +246,9 @@ Array [ />
- - - +
@@ -277,8 +278,8 @@ Array [ best element ever

-
- +
@@ -599,8 +600,9 @@ Array [ />
- - - +
@@ -626,8 +628,8 @@ Array [

-
- +
@@ -949,8 +951,9 @@ Array [ />
- - - +
My Chart @@ -980,8 +983,8 @@ Array [

-
- +
@@ -1301,8 +1304,9 @@ Array [ />
- - - +
@@ -1332,8 +1336,8 @@ Array [

-
- +
diff --git a/x-pack/legacy/plugins/canvas/public/components/element_card/__examples__/__snapshots__/element_card.examples.storyshot b/x-pack/legacy/plugins/canvas/public/components/element_card/__examples__/__snapshots__/element_card.examples.storyshot index 35135b5662b24..f09921607ef46 100644 --- a/x-pack/legacy/plugins/canvas/public/components/element_card/__examples__/__snapshots__/element_card.examples.storyshot +++ b/x-pack/legacy/plugins/canvas/public/components/element_card/__examples__/__snapshots__/element_card.examples.storyshot @@ -8,11 +8,11 @@ exports[`Storyshots components/Elements/ElementCard with click handler 1`] = ` } } > -
- - +
- +
`; @@ -60,8 +66,9 @@ exports[`Storyshots components/Elements/ElementCard with image 1`] = ` >
- - - +
Element 1 @@ -87,8 +94,8 @@ exports[`Storyshots components/Elements/ElementCard with image 1`] = ` Lorem ipsum dolor sit amet, consectetur adipiscing elit. Fusce lobortis aliquet arcu ut turpis duis.

-
- +
@@ -103,11 +110,11 @@ exports[`Storyshots components/Elements/ElementCard with tags 1`] = ` } } > -
- - +
- - +
+
`; @@ -270,8 +283,9 @@ exports[`Storyshots components/Elements/ElementCard with title and description 1 >
- - - +
Element 1 @@ -301,8 +315,8 @@ exports[`Storyshots components/Elements/ElementCard with title and description 1 Lorem ipsum dolor sit amet, consectetur adipiscing elit. Fusce lobortis aliquet arcu ut turpis duis.

-
- +
diff --git a/x-pack/legacy/plugins/canvas/public/components/element_types/__examples__/__snapshots__/element_grid.examples.storyshot b/x-pack/legacy/plugins/canvas/public/components/element_types/__examples__/__snapshots__/element_grid.examples.storyshot index c192e082523cb..01774f849dfe7 100644 --- a/x-pack/legacy/plugins/canvas/public/components/element_types/__examples__/__snapshots__/element_grid.examples.storyshot +++ b/x-pack/legacy/plugins/canvas/public/components/element_types/__examples__/__snapshots__/element_grid.examples.storyshot @@ -14,11 +14,11 @@ exports[`Storyshots components/Elements/ElementGrid with controls 1`] = `
-
- - +
- +
@@ -115,11 +121,11 @@ exports[`Storyshots components/Elements/ElementGrid with controls 1`] = `
-
- - +
- +
@@ -216,11 +228,11 @@ exports[`Storyshots components/Elements/ElementGrid with controls 1`] = `
-
- - +
- +
@@ -332,11 +350,11 @@ exports[`Storyshots components/Elements/ElementGrid with controls and filter 1`]
-
- - +
- +
@@ -448,11 +472,11 @@ exports[`Storyshots components/Elements/ElementGrid with tags filter 1`] = `
-
- - +
- - +
+
@@ -522,11 +552,11 @@ exports[`Storyshots components/Elements/ElementGrid with text filter 1`] = `
-
- - +
- - +
+
@@ -596,11 +632,11 @@ exports[`Storyshots components/Elements/ElementGrid without controls 1`] = `
-
- - +
- - +
+
-
- - +
- - +
+
-
- - +
- - +
+
diff --git a/x-pack/legacy/plugins/canvas/public/components/help_menu/help_menu.js b/x-pack/legacy/plugins/canvas/public/components/help_menu/help_menu.js index 6e1de129e84c6..4512ce2b4992e 100644 --- a/x-pack/legacy/plugins/canvas/public/components/help_menu/help_menu.js +++ b/x-pack/legacy/plugins/canvas/public/components/help_menu/help_menu.js @@ -5,8 +5,7 @@ */ import React, { Fragment, PureComponent } from 'react'; -import { EuiButton, EuiHorizontalRule, EuiText, EuiSpacer, EuiPortal } from '@elastic/eui'; -import { documentationLinks } from '../../lib/documentation_links'; +import { EuiButtonEmpty, EuiPortal } from '@elastic/eui'; import { KeyboardShortcutsDoc } from '../keyboard_shortcuts_doc'; import { ComponentStrings } from '../../../i18n'; @@ -26,19 +25,14 @@ export class HelpMenu extends PureComponent { render() { return ( - - - -

{strings.getHelpMenuDescription()}

-
- - - {strings.getDocumentationLinkLabel()} - - - + {strings.getKeyboardShortcutsLinkLabel()} - + {this.state.isFlyoutVisible && ( diff --git a/x-pack/legacy/plugins/canvas/public/components/keyboard_shortcuts_doc/__examples__/__snapshots__/keyboard_shortcuts_doc.examples.storyshot b/x-pack/legacy/plugins/canvas/public/components/keyboard_shortcuts_doc/__examples__/__snapshots__/keyboard_shortcuts_doc.examples.storyshot index cf37481d8ad7c..e02d64e3e0647 100644 --- a/x-pack/legacy/plugins/canvas/public/components/keyboard_shortcuts_doc/__examples__/__snapshots__/keyboard_shortcuts_doc.examples.storyshot +++ b/x-pack/legacy/plugins/canvas/public/components/keyboard_shortcuts_doc/__examples__/__snapshots__/keyboard_shortcuts_doc.examples.storyshot @@ -1,1601 +1,1599 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP exports[`Storyshots components/KeyboardShortcutsDoc default 1`] = ` - +
-
-
+
+ } + tabIndex={1} + /> +
+
- -
-

- Keyboard Shortcuts -

-
+ Keyboard shortcuts + +
+
-
-

- Element controls -

-
-
-
- Cut -
-
- - - - CTRL - - - - - - X - - - -
-
- Copy -
-
- - - - CTRL - - - - - - C - - - -
-
- Paste -
-
- - - - CTRL - - - - - - V - - - -
-
- Clone -
-
- - - - CTRL - - - - - - D - - - -
-
- Delete -
-
- - - - DEL - - - - - - or - - - - - - BACKSPACE - - - -
-
- Bring forward -
-
- - - - CTRL - - - - - - ↑ - - - -
-
- Bring to front -
-
- - - - CTRL - - - - - - SHIFT - - - - - - ↑ - - - -
-
- Send backward -
-
- - - - CTRL - - - - - - ↓ - - - -
-
- Send to back -
-
- - - - CTRL - - - - - - SHIFT - - - - - - ↓ - - - -
-
- Group -
-
- - - - G - - - -
-
- Ungroup -
-
- - - - U - - - -
-
- Shift up by 10px -
-
- - - - ↑ - - - -
-
- Shift down by 10px -
-
- - - - ↓ - - - -
-
- Shift left by 10px -
-
- - - - ← - - - -
-
- Shift right by 10px -
-
- - - - → - - - -
-
- Shift up by 1px -
-
- - - - SHIFT - - - - - - ↑ - - - -
-
- Shift down by 1px -
-
- - - - SHIFT - - - - - - ↓ - - - -
-
- Shift left by 1px -
-
- - - - SHIFT - - - - - - ← - - - -
-
- Shift right by 1px -
-
- - - - SHIFT - - - - - - → - - - -
-
-
-
+ Element controls + +
+
+
+ Cut +
+
+ + + + CTRL + + + + + + X + + + +
+
+ Copy +
+
+ + + + CTRL + + + + + + C + + + +
+
+ Paste +
+
+ + + + CTRL + + + + + + V + + + +
+
+ Clone +
+
+ + + + CTRL + + + + + + D + + + +
+
+ Delete +
+
+ + + + DEL + + + + + + or + + + + + + BACKSPACE + + + +
+
+ Bring forward +
+
+ + + + CTRL + + + + + + ↑ + + + +
+
+ Bring to front +
+
+ + + + CTRL + + + + + + SHIFT + + + + + + ↑ + + + +
+
+ Send backward +
+
+ + + + CTRL + + + + + + ↓ + + + +
+
+ Send to back +
+
+ + + + CTRL + + + + + + SHIFT + + + + + + ↓ + + + +
+
+ Group +
+
+ + + + G + + + +
+
+ Ungroup +
+
+ + + + U + + + +
+
+ Shift up by 10px +
+
+ + + + ↑ + + + +
+
+ Shift down by 10px +
+
+ + + + ↓ + + + +
+
+ Shift left by 10px +
+
+ + + + ← + + + +
+
+ Shift right by 10px +
+
+ + + + → + + + +
+
+ Shift up by 1px +
+
+ + + + SHIFT + + + + + + ↑ + + + +
+
+ Shift down by 1px +
+
+ + + + SHIFT + + + + + + ↓ + + + +
+
+ Shift left by 1px +
+
+ + + + SHIFT + + + + + + ← + + + +
+
+ Shift right by 1px +
+
+ + + + SHIFT + + + + + + → + + + +
+
+
+
+

+ Expression controls +

+
+
-

- Expression controls -

-
-
-
- Run whole expression -
-
- - - - CTRL - - - - - - ENTER - - - -
-
-
-
+
+ Run whole expression +
+
+ + + + CTRL + + + + + + ENTER + + + +
+
+
+
+

+ Editor controls +

+
+
-

- Editor controls -

-
-
-
- Select multiple elements -
-
- - - - SHIFT - - - - - - CLICK - - - -
-
- Resize from center -
-
- - - - ALT - - - - - - DRAG - - - -
-
- Move, resize, and rotate without snapping -
-
- - - - CTRL - - - - - - DRAG - - - -
-
- Select element below -
-
- - - - CTRL - - - - - - CLICK - - - -
-
- Undo last action -
-
- - - - CTRL - - - - - - Z - - - -
-
- Redo last action -
-
- - - - CTRL - - - - - - SHIFT - - - - - - Z - - - -
-
- Go to previous page -
-
- - - - ALT - - - - - - [ - - - -
-
- Go to next page -
-
- - - - ALT - - - - - - ] - - - -
-
- Toggle edit mode -
-
- - - - ALT - - - - - - E - - - -
-
- Show grid -
-
- - - - ALT - - - - - - G - - - -
-
- Refresh workpad -
-
- - - - ALT - - - - - - R - - - -
-
- Zoom in -
-
- - - - CTRL - - - - - - ALT - - - - - - + - - - -
-
- Zoom out -
-
- - - - CTRL - - - - - - ALT - - - - - - - - - - -
-
- Reset zoom to 100% -
-
- - - - CTRL - - - - - - ALT - - - - - - [ - - - -
-
- Enter presentation mode -
-
- - - - ALT - - - - - - F - - - - - - or - - - - - - ALT - - - - - - P - - - -
-
-
-
+
+ Select multiple elements +
+
+ + + + SHIFT + + + + + + CLICK + + + +
+
+ Resize from center +
+
+ + + + ALT + + + + + + DRAG + + + +
+
+ Move, resize, and rotate without snapping +
+
+ + + + CTRL + + + + + + DRAG + + + +
+
+ Select element below +
+
+ + + + CTRL + + + + + + CLICK + + + +
+
+ Undo last action +
+
+ + + + CTRL + + + + + + Z + + + +
+
+ Redo last action +
+
+ + + + CTRL + + + + + + SHIFT + + + + + + Z + + + +
+
+ Go to previous page +
+
+ + + + ALT + + + + + + [ + + + +
+
+ Go to next page +
+
+ + + + ALT + + + + + + ] + + + +
+
+ Toggle edit mode +
+
+ + + + ALT + + + + + + E + + + +
+
+ Show grid +
+
+ + + + ALT + + + + + + G + + + +
+
+ Refresh workpad +
+
+ + + + ALT + + + + + + R + + + +
+
+ Zoom in +
+
+ + + + CTRL + + + + + + ALT + + + + + + + + + + +
+
+ Zoom out +
+
+ + + + CTRL + + + + + + ALT + + + + + + - + + + +
+
+ Reset zoom to 100% +
+
+ + + + CTRL + + + + + + ALT + + + + + + [ + + + +
+
+ Enter presentation mode +
+
+ + + + ALT + + + + + + F + + + + + + or + + + + + + ALT + + + + + + P + + + +
+
+
+
+

+ Presentation controls +

+
+
-

- Presentation controls -

-
-
-
- Enter presentation mode -
-
- - - - ALT - - - - - - F - - - - - - or - - - - - - ALT - - - - - - P - - - -
-
- Exit presentation mode -
-
- - - - ESC - - - -
-
- Go to previous page -
-
- - - - ALT - - - - - - [ - - - - - - or - - - - - - BACKSPACE - - - - - - or - - - - - - ← - - - -
-
- Go to next page -
-
- - - - ALT - - - - - - ] - - - - - - or - - - - - - SPACE - - - - - - or - - - - - - → - - - -
-
- Refresh workpad -
-
- - - - ALT - - - - - - R - - - -
-
- Toggle page cycling -
-
- - - - P - - - -
-
-
-
+
+ Enter presentation mode +
+
+ + + + ALT + + + + + + F + + + + + + or + + + + + + ALT + + + + + + P + + + +
+
+ Exit presentation mode +
+
+ + + + ESC + + + +
+
+ Go to previous page +
+
+ + + + ALT + + + + + + [ + + + + + + or + + + + + + BACKSPACE + + + + + + or + + + + + + ← + + + +
+
+ Go to next page +
+
+ + + + ALT + + + + + + ] + + + + + + or + + + + + + SPACE + + + + + + or + + + + + + → + + + +
+
+ Refresh workpad +
+
+ + + + ALT + + + + + + R + + + +
+
+ Toggle page cycling +
+
+ + + + P + + + +
+
+
-
- +
+
`; diff --git a/x-pack/legacy/plugins/canvas/shareable_runtime/components/footer/settings/__examples__/__snapshots__/autoplay_settings.examples.storyshot b/x-pack/legacy/plugins/canvas/shareable_runtime/components/footer/settings/__examples__/__snapshots__/autoplay_settings.examples.storyshot index 1e66e19b3c0e1..e9f496bfe6358 100644 --- a/x-pack/legacy/plugins/canvas/shareable_runtime/components/footer/settings/__examples__/__snapshots__/autoplay_settings.examples.storyshot +++ b/x-pack/legacy/plugins/canvas/shareable_runtime/components/footer/settings/__examples__/__snapshots__/autoplay_settings.examples.storyshot @@ -27,7 +27,7 @@ exports[`Storyshots shareables/Footer/Settings/AutoplaySettings component: off, >
`; -exports[` can navigate Toolbar Settings, closes when activated 3`] = `"
Settings

Hide Toolbar

Hide the toolbar when the mouse is not within the Canvas?
"`; +exports[` can navigate Toolbar Settings, closes when activated 3`] = `"
Settings

Hide Toolbar

Hide the toolbar when the mouse is not within the Canvas?
"`; diff --git a/x-pack/legacy/plugins/dashboard_mode/public/dashboard_viewer.js b/x-pack/legacy/plugins/dashboard_mode/public/dashboard_viewer.js index 4fbba4a5ffd31..8093c57d2631a 100644 --- a/x-pack/legacy/plugins/dashboard_mode/public/dashboard_viewer.js +++ b/x-pack/legacy/plugins/dashboard_mode/public/dashboard_viewer.js @@ -26,7 +26,6 @@ import 'uiExports/embeddableActions'; import 'uiExports/embeddableFactories'; import 'uiExports/navbarExtensions'; import 'uiExports/docViews'; -import 'uiExports/fieldFormats'; import 'uiExports/search'; import 'uiExports/shareContextMenuExtensions'; import _ from 'lodash'; diff --git a/x-pack/legacy/plugins/graph/public/components/guidance_panel/guidance_panel.tsx b/x-pack/legacy/plugins/graph/public/components/guidance_panel/guidance_panel.tsx index 8dede207b803c..5fae9720db39a 100644 --- a/x-pack/legacy/plugins/graph/public/components/guidance_panel/guidance_panel.tsx +++ b/x-pack/legacy/plugins/graph/public/components/guidance_panel/guidance_panel.tsx @@ -18,7 +18,7 @@ import { i18n } from '@kbn/i18n'; import classNames from 'classnames'; import { FormattedMessage } from '@kbn/i18n/react'; import { connect } from 'react-redux'; -import { IDataPluginServices } from 'src/legacy/core_plugins/data/public/types'; +import { IDataPluginServices } from 'src/plugins/data/public'; import { GraphState, hasDatasourceSelector, diff --git a/x-pack/legacy/plugins/graph/public/components/search_bar.tsx b/x-pack/legacy/plugins/graph/public/components/search_bar.tsx index b6200d831b248..82e50c702997f 100644 --- a/x-pack/legacy/plugins/graph/public/components/search_bar.tsx +++ b/x-pack/legacy/plugins/graph/public/components/search_bar.tsx @@ -10,8 +10,7 @@ import React, { useState, useEffect } from 'react'; import { i18n } from '@kbn/i18n'; import { connect } from 'react-redux'; import { fromKueryExpression, toElasticsearchQuery } from '@kbn/es-query'; -import { IDataPluginServices } from 'src/legacy/core_plugins/data/public/types'; -import { Query } from 'src/plugins/data/public'; +import { IDataPluginServices, Query } from 'src/plugins/data/public'; import { IndexPatternSavedObject, IndexPatternProvider } from '../types'; import { QueryBarInput, IndexPattern } from '../../../../../../src/legacy/core_plugins/data/public'; import { openSourceModal } from '../services/source_modal'; diff --git a/x-pack/legacy/plugins/graph/public/index.ts b/x-pack/legacy/plugins/graph/public/index.ts index 833134abff0b6..988aa78695095 100644 --- a/x-pack/legacy/plugins/graph/public/index.ts +++ b/x-pack/legacy/plugins/graph/public/index.ts @@ -6,7 +6,6 @@ // legacy imports currently necessary to power Graph // for a cutover all of these have to be resolved -import 'uiExports/fieldFormats'; import 'uiExports/savedObjectTypes'; import 'uiExports/autocompleteProviders'; import 'ui/autoload/all'; diff --git a/x-pack/legacy/plugins/infra/docs/arch_client.md b/x-pack/legacy/plugins/infra/docs/arch_client.md index 2be9de469f0ee..cdc4746357216 100644 --- a/x-pack/legacy/plugins/infra/docs/arch_client.md +++ b/x-pack/legacy/plugins/infra/docs/arch_client.md @@ -14,10 +14,10 @@ The `apps` folder contains the entry point for the UI code, such as for use in K - All components, please use Styled-Components. This also applies to small tweaks to EUI, just use `styled(Component)` and the `attrs` method for always used props. For example: ```jsx -export const Toolbar = styled(EuiPanel).attrs({ +export const Toolbar = styled(EuiPanel).attrs(() => ({ paddingSize: 'none', grow: false, -})` +}))` margin: -2px; `; ``` diff --git a/x-pack/legacy/plugins/infra/public/components/autocomplete_field/autocomplete_field.tsx b/x-pack/legacy/plugins/infra/public/components/autocomplete_field/autocomplete_field.tsx index 255e5b75c1390..c569a5d01a1a4 100644 --- a/x-pack/legacy/plugins/infra/public/components/autocomplete_field/autocomplete_field.tsx +++ b/x-pack/legacy/plugins/infra/public/components/autocomplete_field/autocomplete_field.tsx @@ -101,7 +101,7 @@ export class AutocompleteField extends React.Component< } } - public componentDidUpdate(prevProps: AutocompleteFieldProps, prevState: AutocompleteFieldState) { + public componentDidUpdate(prevProps: AutocompleteFieldProps) { const hasNewValue = prevProps.value !== this.props.value; const hasNewSuggestions = prevProps.suggestions !== this.props.suggestions; @@ -312,10 +312,10 @@ const AutocompleteContainer = euiStyled.div` position: relative; `; -const SuggestionsPanel = euiStyled(EuiPanel).attrs({ +const SuggestionsPanel = euiStyled(EuiPanel).attrs(() => ({ paddingSize: 'none', hasShadow: true, -})` +}))` position: absolute; width: 100%; margin-top: 2px; diff --git a/x-pack/legacy/plugins/infra/public/components/autocomplete_field/suggestion_item.tsx b/x-pack/legacy/plugins/infra/public/components/autocomplete_field/suggestion_item.tsx index d7c9876a07a8d..6ddcd675487ba 100644 --- a/x-pack/legacy/plugins/infra/public/components/autocomplete_field/suggestion_item.tsx +++ b/x-pack/legacy/plugins/infra/public/components/autocomplete_field/suggestion_item.tsx @@ -57,7 +57,7 @@ const SuggestionItemField = euiStyled.div` padding: ${props => props.theme.eui.euiSizeXS}; `; -const SuggestionItemIconField = SuggestionItemField.extend<{ suggestionType: string }>` +const SuggestionItemIconField = euiStyled(SuggestionItemField)<{ suggestionType: string }>` background-color: ${props => transparentize(0.9, getEuiIconColor(props.theme, props.suggestionType))}; color: ${props => getEuiIconColor(props.theme, props.suggestionType)}; @@ -66,12 +66,12 @@ const SuggestionItemIconField = SuggestionItemField.extend<{ suggestionType: str width: ${props => props.theme.eui.euiSizeXL}; `; -const SuggestionItemTextField = SuggestionItemField.extend` +const SuggestionItemTextField = euiStyled(SuggestionItemField)` flex: 2 0 0; font-family: ${props => props.theme.eui.euiCodeFontFamily}; `; -const SuggestionItemDescriptionField = SuggestionItemField.extend` +const SuggestionItemDescriptionField = euiStyled(SuggestionItemField)` flex: 3 0 0; p { diff --git a/x-pack/legacy/plugins/infra/public/components/eui/toolbar/toolbar.tsx b/x-pack/legacy/plugins/infra/public/components/eui/toolbar/toolbar.tsx index 6f1cfc4078ae2..2c3b5cb924e36 100644 --- a/x-pack/legacy/plugins/infra/public/components/eui/toolbar/toolbar.tsx +++ b/x-pack/legacy/plugins/infra/public/components/eui/toolbar/toolbar.tsx @@ -8,10 +8,10 @@ import { EuiPanel } from '@elastic/eui'; import euiStyled from '../../../../../../common/eui_styled_components'; -export const Toolbar = euiStyled(EuiPanel).attrs({ +export const Toolbar = euiStyled(EuiPanel).attrs(() => ({ grow: false, paddingSize: 'none', -})` +}))` border-top: none; border-right: none; border-left: none; diff --git a/x-pack/legacy/plugins/infra/public/components/help_center_content.tsx b/x-pack/legacy/plugins/infra/public/components/help_center_content.tsx index 0560c42d7498b..3095230ab8311 100644 --- a/x-pack/legacy/plugins/infra/public/components/help_center_content.tsx +++ b/x-pack/legacy/plugins/infra/public/components/help_center_content.tsx @@ -4,37 +4,26 @@ * you may not use this file except in compliance with the Elastic License. */ -import { EuiLink } from '@elastic/eui'; import React, { useEffect } from 'react'; -import ReactDOM from 'react-dom'; import chrome from 'ui/chrome'; interface HelpCenterContentProps { feedbackLink: string; - feedbackLinkText: string; + appName: string; } -const Content: React.FC = ({ feedbackLink, feedbackLinkText }) => ( - - {feedbackLinkText} - -); - -export const HelpCenterContent: React.FC = ({ - feedbackLink, - feedbackLinkText, -}) => { +export const HelpCenterContent: React.FC = ({ feedbackLink, appName }) => { useEffect(() => { - chrome.helpExtension.set(domElement => { - ReactDOM.render( - , - domElement - ); - return () => { - ReactDOM.unmountComponentAtNode(domElement); - }; + chrome.helpExtension.set({ + appName, + links: [ + { + linkType: 'discuss', + href: feedbackLink, + }, + ], }); - }, [feedbackLink, feedbackLinkText]); + }, [feedbackLink, appName]); return null; }; diff --git a/x-pack/legacy/plugins/infra/public/components/logging/log_highlights_menu.tsx b/x-pack/legacy/plugins/infra/public/components/logging/log_highlights_menu.tsx index 6fcb1779cba0c..24a5e8bacb4f9 100644 --- a/x-pack/legacy/plugins/infra/public/components/logging/log_highlights_menu.tsx +++ b/x-pack/legacy/plugins/infra/public/components/logging/log_highlights_menu.tsx @@ -149,11 +149,11 @@ const goToNextHighlightLabel = i18n.translate( } ); -const ActiveHighlightsIndicator = euiStyled(EuiIcon).attrs({ +const ActiveHighlightsIndicator = euiStyled(EuiIcon).attrs(({ theme }) => ({ type: 'checkInCircleFilled', size: 'm', - color: props => props.theme.eui.euiColorAccent, -})` + color: theme.eui.euiColorAccent, +}))` padding-left: ${props => props.theme.eui.paddingSizes.xs}; `; diff --git a/x-pack/legacy/plugins/infra/public/components/logging/log_minimap/log_minimap.tsx b/x-pack/legacy/plugins/infra/public/components/logging/log_minimap/log_minimap.tsx index 90b1e455d477e..ad47d17fe3db9 100644 --- a/x-pack/legacy/plugins/infra/public/components/logging/log_minimap/log_minimap.tsx +++ b/x-pack/legacy/plugins/infra/public/components/logging/log_minimap/log_minimap.tsx @@ -238,7 +238,7 @@ export class LogMinimap extends React.Component { + ref={node => { this.dragTargetArea = node; }} x={0} diff --git a/x-pack/legacy/plugins/infra/public/components/logging/log_statusbar.tsx b/x-pack/legacy/plugins/infra/public/components/logging/log_statusbar.tsx index c52ef4a5062dc..4bda5a5a4b009 100644 --- a/x-pack/legacy/plugins/infra/public/components/logging/log_statusbar.tsx +++ b/x-pack/legacy/plugins/infra/public/components/logging/log_statusbar.tsx @@ -8,11 +8,11 @@ import { EuiFlexGroup, EuiFlexItem } from '@elastic/eui'; import euiStyled from '../../../../../common/eui_styled_components'; -export const LogStatusbar = euiStyled(EuiFlexGroup).attrs({ +export const LogStatusbar = euiStyled(EuiFlexGroup).attrs(() => ({ alignItems: 'center', gutterSize: 'none', justifyContent: 'flexEnd', -})` +}))` padding: ${props => props.theme.eui.euiSizeS}; border-top: ${props => props.theme.eui.euiBorderThin}; max-height: 48px; diff --git a/x-pack/legacy/plugins/infra/public/components/logging/log_text_stream/column_headers.tsx b/x-pack/legacy/plugins/infra/public/components/logging/log_text_stream/column_headers.tsx index 56a84d258c907..bf4a09769d254 100644 --- a/x-pack/legacy/plugins/infra/public/components/logging/log_text_stream/column_headers.tsx +++ b/x-pack/legacy/plugins/infra/public/components/logging/log_text_stream/column_headers.tsx @@ -79,9 +79,9 @@ const LogColumnHeader: React.FunctionComponent<{ ); -const LogColumnHeadersWrapper = euiStyled.div.attrs({ +const LogColumnHeadersWrapper = euiStyled.div.attrs(() => ({ role: 'row', -})` +}))` align-items: stretch; display: flex; flex-direction: row; @@ -95,9 +95,9 @@ const LogColumnHeadersWrapper = euiStyled.div.attrs({ z-index: 1; `; -const LogColumnHeaderWrapper = LogEntryColumn.extend.attrs({ +const LogColumnHeaderWrapper = euiStyled(LogEntryColumn).attrs(() => ({ role: 'columnheader', -})` +}))` align-items: center; display: flex; flex-direction: row; @@ -105,7 +105,7 @@ const LogColumnHeaderWrapper = LogEntryColumn.extend.attrs({ overflow: hidden; `; -const LogColumnHeaderContent = LogEntryColumnContent.extend` +const LogColumnHeaderContent = euiStyled(LogEntryColumnContent)` color: ${props => props.theme.eui.euiTitleColor}; font-size: ${props => props.theme.eui.euiFontSizeS}; font-weight: ${props => props.theme.eui.euiFontWeightSemiBold}; diff --git a/x-pack/legacy/plugins/infra/public/components/logging/log_text_stream/log_entry_column.tsx b/x-pack/legacy/plugins/infra/public/components/logging/log_text_stream/log_entry_column.tsx index 3df727789da74..643f98018cb0a 100644 --- a/x-pack/legacy/plugins/infra/public/components/logging/log_text_stream/log_entry_column.tsx +++ b/x-pack/legacy/plugins/infra/public/components/logging/log_text_stream/log_entry_column.tsx @@ -22,9 +22,9 @@ interface LogEntryColumnProps { shrinkWeight: number; } -export const LogEntryColumn = euiStyled.div.attrs({ +export const LogEntryColumn = euiStyled.div.attrs(() => ({ role: 'cell', -})` +}))` align-items: stretch; display: flex; flex-basis: ${props => props.baseWidth || '0%'}; diff --git a/x-pack/legacy/plugins/infra/public/components/logging/log_text_stream/log_entry_field_column.tsx b/x-pack/legacy/plugins/infra/public/components/logging/log_text_stream/log_entry_field_column.tsx index cf2f67f3eb126..6252b3a396d1b 100644 --- a/x-pack/legacy/plugins/infra/public/components/logging/log_text_stream/log_entry_field_column.tsx +++ b/x-pack/legacy/plugins/infra/public/components/logging/log_text_stream/log_entry_field_column.tsx @@ -8,7 +8,7 @@ import stringify from 'json-stable-stringify'; import { darken, transparentize } from 'polished'; import React, { useMemo } from 'react'; -import styled, { css } from '../../../../../../common/eui_styled_components'; +import euiStyled, { css } from '../../../../../../common/eui_styled_components'; import { isFieldColumn, isHighlightFieldColumn, @@ -83,7 +83,7 @@ const unwrappedContentStyle = css` white-space: pre; `; -const CommaSeparatedLi = styled.li` +const CommaSeparatedLi = euiStyled.li` display: inline; &:not(:last-child) { margin-right: 1ex; @@ -93,11 +93,13 @@ const CommaSeparatedLi = styled.li` } `; -const FieldColumnContent = LogEntryColumnContent.extend.attrs<{ +interface LogEntryColumnContentProps { isHighlighted: boolean; isHovered: boolean; isWrapped?: boolean; -}>({})` +} + +const FieldColumnContent = euiStyled(LogEntryColumnContent)` background-color: ${props => props.theme.eui.euiColorEmptyShade}; text-overflow: ellipsis; diff --git a/x-pack/legacy/plugins/infra/public/components/logging/log_text_stream/log_entry_icon_column.tsx b/x-pack/legacy/plugins/infra/public/components/logging/log_text_stream/log_entry_icon_column.tsx index 8e55caae738e7..f7d841bcce94f 100644 --- a/x-pack/legacy/plugins/infra/public/components/logging/log_text_stream/log_entry_icon_column.tsx +++ b/x-pack/legacy/plugins/infra/public/components/logging/log_text_stream/log_entry_icon_column.tsx @@ -47,10 +47,12 @@ export const LogEntryDetailsIconColumn: React.FunctionComponent({})` +} + +const IconColumnContent = euiStyled(LogEntryColumnContent)` background-color: ${props => props.theme.eui.euiColorEmptyShade}; overflow: hidden; user-select: none; diff --git a/x-pack/legacy/plugins/infra/public/components/logging/log_text_stream/log_entry_message_column.tsx b/x-pack/legacy/plugins/infra/public/components/logging/log_text_stream/log_entry_message_column.tsx index 3e6b1dc48e89d..11d73736463e2 100644 --- a/x-pack/legacy/plugins/infra/public/components/logging/log_text_stream/log_entry_message_column.tsx +++ b/x-pack/legacy/plugins/infra/public/components/logging/log_text_stream/log_entry_message_column.tsx @@ -6,7 +6,7 @@ import React, { memo, useMemo } from 'react'; -import { css } from '../../../../../../common/eui_styled_components'; +import euiStyled, { css } from '../../../../../../common/eui_styled_components'; import { isConstantSegment, isFieldSegment, @@ -62,11 +62,13 @@ const unwrappedContentStyle = css` white-space: pre; `; -const MessageColumnContent = LogEntryColumnContent.extend.attrs<{ +interface MessageColumnContentProps { isHovered: boolean; isHighlighted: boolean; isWrapped?: boolean; -}>({})` +} + +const MessageColumnContent = euiStyled(LogEntryColumnContent)` background-color: ${props => props.theme.eui.euiColorEmptyShade}; text-overflow: ellipsis; diff --git a/x-pack/legacy/plugins/infra/public/components/logging/log_text_stream/log_entry_row.tsx b/x-pack/legacy/plugins/infra/public/components/logging/log_text_stream/log_entry_row.tsx index ce3c0cf0f5a22..0da601ae52088 100644 --- a/x-pack/legacy/plugins/infra/public/components/logging/log_text_stream/log_entry_row.tsx +++ b/x-pack/legacy/plugins/infra/public/components/logging/log_text_stream/log_entry_row.tsx @@ -103,7 +103,7 @@ export const LogEntryRow = ({ return ( ({ +} + +const LogEntryRowWrapper = euiStyled.div.attrs(() => ({ role: 'row', -})` +}))` align-items: stretch; color: ${props => props.theme.eui.euiTextColor}; display: flex; @@ -204,5 +206,5 @@ const LogEntryRowWrapper = euiStyled.div.attrs<{ justify-content: flex-start; overflow: hidden; - ${props => monospaceTextStyle(props.scale)} + ${props => monospaceTextStyle(props.scale)}; `; diff --git a/x-pack/legacy/plugins/infra/public/components/logging/log_text_stream/log_entry_timestamp_column.tsx b/x-pack/legacy/plugins/infra/public/components/logging/log_text_stream/log_entry_timestamp_column.tsx index 884e5ff0a5bde..8e161367b428d 100644 --- a/x-pack/legacy/plugins/infra/public/components/logging/log_text_stream/log_entry_timestamp_column.tsx +++ b/x-pack/legacy/plugins/infra/public/components/logging/log_text_stream/log_entry_timestamp_column.tsx @@ -7,7 +7,7 @@ import { darken, transparentize } from 'polished'; import React, { memo } from 'react'; -import { css } from '../../../../../../common/eui_styled_components'; +import euiStyled, { css } from '../../../../../../common/eui_styled_components'; import { useFormattedTime } from '../../formatted_time'; import { LogEntryColumnContent } from './log_entry_column'; @@ -41,10 +41,12 @@ const hoveredContentStyle = css` color: ${props => props.theme.eui.euiColorFullShade}; `; -const TimestampColumnContent = LogEntryColumnContent.extend.attrs<{ +interface TimestampColumnContentProps { isHovered: boolean; isHighlighted: boolean; -}>({})` +} + +const TimestampColumnContent = euiStyled(LogEntryColumnContent)` color: ${props => props.theme.eui.euiColorDarkShade}; overflow: hidden; text-overflow: clip; diff --git a/x-pack/legacy/plugins/infra/public/components/logging/log_text_stream/scrollable_log_text_stream_view.tsx b/x-pack/legacy/plugins/infra/public/components/logging/log_text_stream/scrollable_log_text_stream_view.tsx index fc3c8b3bf2b31..674c3f59ce957 100644 --- a/x-pack/legacy/plugins/infra/public/components/logging/log_text_stream/scrollable_log_text_stream_view.tsx +++ b/x-pack/legacy/plugins/infra/public/components/logging/log_text_stream/scrollable_log_text_stream_view.tsx @@ -179,7 +179,7 @@ export class ScrollableLogTextStreamView extends React.PureComponent< /> {({ measureRef, bounds: { height = 0 }, content: { width = 0 } }) => ( - + css` default: return props.theme.eui.euiFontSize; } - }} + }}; line-height: ${props => props.theme.eui.euiLineHeight}; `; @@ -59,7 +59,7 @@ export const useMeasuredCharacterDimensions = (scale: TextScale) => { const CharacterDimensionsProbe = useMemo( () => () => ( - + X ), @@ -72,11 +72,13 @@ export const useMeasuredCharacterDimensions = (scale: TextScale) => { }; }; -const MonospaceCharacterDimensionsProbe = euiStyled.div.attrs<{ +interface MonospaceCharacterDimensionsProbe { scale: TextScale; -}>({ +} + +const MonospaceCharacterDimensionsProbe = euiStyled.div.attrs(() => ({ 'aria-hidden': true, -})` +}))` visibility: hidden; position: absolute; height: auto; @@ -84,5 +86,5 @@ const MonospaceCharacterDimensionsProbe = euiStyled.div.attrs<{ padding: 0; margin: 0; - ${props => monospaceTextStyle(props.scale)} + ${props => monospaceTextStyle(props.scale)}; `; diff --git a/x-pack/legacy/plugins/infra/public/components/logging/log_text_stream/vertical_scroll_panel.tsx b/x-pack/legacy/plugins/infra/public/components/logging/log_text_stream/vertical_scroll_panel.tsx index 62db9d517c9d2..6daa942be78c8 100644 --- a/x-pack/legacy/plugins/infra/public/components/logging/log_text_stream/vertical_scroll_panel.tsx +++ b/x-pack/legacy/plugins/infra/public/components/logging/log_text_stream/vertical_scroll_panel.tsx @@ -247,10 +247,7 @@ export class VerticalScrollPanel extends React.PureComponent< style={{ height, width: width + scrollbarOffset }} scrollbarOffset={scrollbarOffset} onScroll={this.handleScroll} - innerRef={ - /* workaround for missing RefObject support in styled-components typings */ - this.scrollRef as any - } + ref={this.scrollRef} > {typeof children === 'function' ? children(this.registerChild) : null} @@ -258,7 +255,11 @@ export class VerticalScrollPanel extends React.PureComponent< } } -const ScrollPanelWrapper = euiStyled.div.attrs<{ scrollbarOffset?: number }>({})` +interface ScrollPanelWrapperProps { + scrollbarOffset?: number; +} + +const ScrollPanelWrapper = euiStyled.div` overflow-x: hidden; overflow-y: scroll; position: relative; diff --git a/x-pack/legacy/plugins/infra/public/components/navigation/app_navigation.tsx b/x-pack/legacy/plugins/infra/public/components/navigation/app_navigation.tsx index fe3c930f9e08e..79785c11a3ebe 100644 --- a/x-pack/legacy/plugins/infra/public/components/navigation/app_navigation.tsx +++ b/x-pack/legacy/plugins/infra/public/components/navigation/app_navigation.tsx @@ -25,10 +25,9 @@ const Nav = euiStyled.nav` background: ${props => props.theme.eui.euiColorEmptyShade}; border-bottom: ${props => props.theme.eui.euiBorderThin}; padding: ${props => - `${props.theme.eui.euiSize} ${props.theme.eui.euiSizeL} ${props.theme.eui.euiSize} ${props.theme.eui.euiSizeL}`} - + `${props.theme.eui.euiSize} ${props.theme.eui.euiSizeL} ${props.theme.eui.euiSize} ${props.theme.eui.euiSizeL}`}; .euiTabs { padding-left: 3px; margin-left: -3px; - } + }; `; diff --git a/x-pack/legacy/plugins/infra/public/components/waffle/group_name.tsx b/x-pack/legacy/plugins/infra/public/components/waffle/group_name.tsx index 511b41d91dd7b..731bcdd52a98e 100644 --- a/x-pack/legacy/plugins/infra/public/components/waffle/group_name.tsx +++ b/x-pack/legacy/plugins/infra/public/components/waffle/group_name.tsx @@ -52,7 +52,7 @@ export class GroupName extends React.PureComponent { const GroupNameContainer = euiStyled.div` position: relative; - text-align: center + text-align: center; font-size: 16px; margin-bottom: 5px; top: 20px; @@ -65,7 +65,7 @@ interface InnerProps { isChild?: boolean; } -const Inner = euiStyled('div')` +const Inner = euiStyled.div` border: 1px solid ${props => props.theme.eui.euiBorderColor}; background-color: ${props => props.isChild ? props.theme.eui.euiColorLightestShade : props.theme.eui.euiColorEmptyShade}; diff --git a/x-pack/legacy/plugins/infra/public/components/waffle/group_of_groups.tsx b/x-pack/legacy/plugins/infra/public/components/waffle/group_of_groups.tsx index eaf0ea5e81d57..bf10133d1f16e 100644 --- a/x-pack/legacy/plugins/infra/public/components/waffle/group_of_groups.tsx +++ b/x-pack/legacy/plugins/infra/public/components/waffle/group_of_groups.tsx @@ -51,7 +51,7 @@ export const GroupOfGroups: React.SFC = props => { const GroupOfGroupsContainer = euiStyled.div` margin: 0 10px; - width: 100% + width: 100%; `; const Groups = euiStyled.div` diff --git a/x-pack/legacy/plugins/infra/public/components/waffle/map.tsx b/x-pack/legacy/plugins/infra/public/components/waffle/map.tsx index f15bfff5d283e..14c15cfd0fe3e 100644 --- a/x-pack/legacy/plugins/infra/public/components/waffle/map.tsx +++ b/x-pack/legacy/plugins/infra/public/components/waffle/map.tsx @@ -46,10 +46,7 @@ export const Map: React.SFC = ({ {({ measureRef, content: { width = 0, height = 0 } }) => { const groupsWithLayout = applyWaffleMapLayout(map, width, height); return ( - measureRef(el)} - data-test-subj="waffleMap" - > + measureRef(el)} data-test-subj="waffleMap"> {groupsWithLayout.map(group => { if (isWaffleMapGroupWithGroups(group)) { diff --git a/x-pack/legacy/plugins/infra/public/components/waffle/node.tsx b/x-pack/legacy/plugins/infra/public/components/waffle/node.tsx index 5839d070248cd..8f09a3fdca9cf 100644 --- a/x-pack/legacy/plugins/infra/public/components/waffle/node.tsx +++ b/x-pack/legacy/plugins/infra/public/components/waffle/node.tsx @@ -116,7 +116,7 @@ interface ColorProps { color: string; } -const SquareOuter = euiStyled('div')` +const SquareOuter = euiStyled.div` position: absolute; top: 4px; left: 4px; @@ -127,7 +127,7 @@ const SquareOuter = euiStyled('div')` box-shadow: 0 1px 2px 0 rgba(0, 0, 0, 0.2); `; -const SquareInner = euiStyled('div')` +const SquareInner = euiStyled.div` cursor: pointer; position: absolute; top: 0; @@ -161,7 +161,7 @@ const ValueInner = euiStyled.button` } `; -const SquareTextContent = euiStyled('div')` +const SquareTextContent = euiStyled.div` text-align: center; width: 100%; overflow: hidden; diff --git a/x-pack/legacy/plugins/infra/public/pages/infrastructure/index.tsx b/x-pack/legacy/plugins/infra/public/pages/infrastructure/index.tsx index 6affcae1805b3..fe48fcc62f77d 100644 --- a/x-pack/legacy/plugins/infra/public/pages/infrastructure/index.tsx +++ b/x-pack/legacy/plugins/infra/public/pages/infrastructure/index.tsx @@ -41,10 +41,9 @@ export const InfrastructurePage = injectUICapabilities(
- +
{ {({ measureRef, bounds: { height = 0 }, content: { width = 0 } }) => { return ( - + {({ buckets }) => ( diff --git a/x-pack/legacy/plugins/infra/public/pages/metrics/index.tsx b/x-pack/legacy/plugins/infra/public/pages/metrics/index.tsx index 643d943273a81..00be769d572ac 100644 --- a/x-pack/legacy/plugins/infra/public/pages/metrics/index.tsx +++ b/x-pack/legacy/plugins/infra/public/pages/metrics/index.tsx @@ -151,7 +151,7 @@ export const MetricDetail = withMetricPageProviders( {({ measureRef, bounds: { width = 0 } }) => { const w = width ? `${width}px` : `100%`; return ( - + diff --git a/x-pack/legacy/plugins/infra/types/eui.d.ts b/x-pack/legacy/plugins/infra/types/eui.d.ts index ef58bfcb2fa04..e4e0e70ce630b 100644 --- a/x-pack/legacy/plugins/infra/types/eui.d.ts +++ b/x-pack/legacy/plugins/infra/types/eui.d.ts @@ -53,10 +53,6 @@ declare module '@elastic/eui' { sizes: EuiSizesResponsive[]; }; - export const EuiHideFor: React.SFC; - - export const EuiShowFor: React.SFC; - type EuiInMemoryTableProps = CommonProps & { items?: any; columns?: any; diff --git a/x-pack/legacy/plugins/lens/common/constants.ts b/x-pack/legacy/plugins/lens/common/constants.ts index 787a348a788b8..c2eed1940fa1a 100644 --- a/x-pack/legacy/plugins/lens/common/constants.ts +++ b/x-pack/legacy/plugins/lens/common/constants.ts @@ -6,9 +6,13 @@ export const PLUGIN_ID = 'lens'; -export const BASE_APP_URL = '/app/lens'; +export const BASE_APP_URL = '/app/kibana'; export const BASE_API_URL = '/api/lens'; +export function getBasePath() { + return `${BASE_APP_URL}#/lens`; +} + export function getEditPath(id: string) { - return `${BASE_APP_URL}#/edit/${encodeURIComponent(id)}`; + return `${BASE_APP_URL}#/lens/edit/${encodeURIComponent(id)}`; } diff --git a/x-pack/legacy/plugins/lens/index.ts b/x-pack/legacy/plugins/lens/index.ts index 20f92ebbe0654..d4cea28d14085 100644 --- a/x-pack/legacy/plugins/lens/index.ts +++ b/x-pack/legacy/plugins/lens/index.ts @@ -12,7 +12,7 @@ import mappings from './mappings.json'; import { PLUGIN_ID, getEditPath } from './common'; import { lensServerPlugin } from './server'; -const NOT_INTERNATIONALIZED_PRODUCT_NAME = 'Lens Visualizations'; +export const NOT_INTERNATIONALIZED_PRODUCT_NAME = 'Lens Visualizations'; export const lens: LegacyPluginInitializer = kibana => { return new kibana.Plugin({ @@ -26,10 +26,11 @@ export const lens: LegacyPluginInitializer = kibana => { app: { title: NOT_INTERNATIONALIZED_PRODUCT_NAME, description: 'Explore and visualize data.', - main: `plugins/${PLUGIN_ID}/index`, + main: `plugins/${PLUGIN_ID}/redirect`, listed: false, }, - embeddableFactories: ['plugins/lens/register_embeddable'], + visualize: [`plugins/${PLUGIN_ID}/legacy`], + embeddableFactories: [`plugins/${PLUGIN_ID}/legacy`], styleSheetPaths: resolve(__dirname, 'public/index.scss'), mappings, visTypes: ['plugins/lens/register_vis_type_alias'], diff --git a/x-pack/legacy/plugins/lens/public/app_plugin/app.test.tsx b/x-pack/legacy/plugins/lens/public/app_plugin/app.test.tsx index 3fcb6609f28f1..ce05af46ade66 100644 --- a/x-pack/legacy/plugins/lens/public/app_plugin/app.test.tsx +++ b/x-pack/legacy/plugins/lens/public/app_plugin/app.test.tsx @@ -99,6 +99,12 @@ describe('Lens App', () => { data: { query: { filterManager: createMockFilterManager(), + timefilter: { + timefilter: { + getTime: jest.fn(() => ({ from: 'now-7d', to: 'now' })), + setTime: jest.fn(), + }, + }, }, }, dataShim: { @@ -109,7 +115,6 @@ describe('Lens App', () => { }), }, }, - timefilter: { history: {} }, }, storage: { get: jest.fn(), diff --git a/x-pack/legacy/plugins/lens/public/app_plugin/app.tsx b/x-pack/legacy/plugins/lens/public/app_plugin/app.tsx index fc5088c1271ad..553b98643f8a5 100644 --- a/x-pack/legacy/plugins/lens/public/app_plugin/app.tsx +++ b/x-pack/legacy/plugins/lens/public/app_plugin/app.tsx @@ -62,33 +62,35 @@ export function App({ docStorage: SavedObjectStore; redirectTo: (id?: string) => void; }) { - const timeDefaults = core.uiSettings.get('timepicker:timeDefaults'); const language = storage.get('kibana.userQueryLanguage') || core.uiSettings.get('search:queryLanguage'); - const [state, setState] = useState({ - isLoading: !!docId, - isSaveModalVisible: false, - indexPatternsForTopNav: [], - query: { query: '', language }, - dateRange: { - fromDate: timeDefaults.from, - toDate: timeDefaults.to, - }, - filters: [], + const [state, setState] = useState(() => { + const currentRange = data.query.timefilter.timefilter.getTime(); + return { + isLoading: !!docId, + isSaveModalVisible: false, + indexPatternsForTopNav: [], + query: { query: '', language }, + dateRange: { + fromDate: currentRange.from, + toDate: currentRange.to, + }, + filters: [], + }; }); const { lastKnownDoc } = state; useEffect(() => { - const subscription = data.query.filterManager.getUpdates$().subscribe({ + const filterSubscription = data.query.filterManager.getUpdates$().subscribe({ next: () => { setState(s => ({ ...s, filters: data.query.filterManager.getFilters() })); trackUiEvent('app_filters_updated'); }, }); return () => { - subscription.unsubscribe(); + filterSubscription.unsubscribe(); }; }, []); @@ -199,6 +201,7 @@ export function App({ dateRange.from !== state.dateRange.fromDate || dateRange.to !== state.dateRange.toDate ) { + data.query.timefilter.timefilter.setTime(dateRange); trackUiEvent('app_date_change'); } else { trackUiEvent('app_query_change'); diff --git a/x-pack/legacy/plugins/lens/public/app_plugin/plugin.tsx b/x-pack/legacy/plugins/lens/public/app_plugin/plugin.tsx index 56c19ea2bb9f2..60a375f696f7b 100644 --- a/x-pack/legacy/plugins/lens/public/app_plugin/plugin.tsx +++ b/x-pack/legacy/plugins/lens/public/app_plugin/plugin.tsx @@ -4,18 +4,27 @@ * you may not use this file except in compliance with the Elastic License. */ +import 'ui/autoload/all'; +// Used to run esaggs queries +import 'uiExports/fieldFormats'; +import 'uiExports/search'; +import 'uiExports/visRequestHandlers'; +import 'uiExports/visResponseHandlers'; +// Used for kibana_context function +import 'uiExports/savedObjectTypes'; + import React from 'react'; import { I18nProvider, FormattedMessage } from '@kbn/i18n/react'; import { HashRouter, Switch, Route, RouteComponentProps } from 'react-router-dom'; +import { render, unmountComponentAtNode } from 'react-dom'; import chrome from 'ui/chrome'; import { CoreSetup, CoreStart } from 'src/core/public'; -import { npSetup, npStart } from 'ui/new_platform'; import { DataPublicPluginStart } from 'src/plugins/data/public'; import { DataStart } from '../../../../../../src/legacy/core_plugins/data/public'; -import { start as dataShimStart } from '../../../../../../src/legacy/core_plugins/data/public/legacy'; import { Storage } from '../../../../../../src/plugins/kibana_utils/public'; import { editorFrameSetup, editorFrameStart, editorFrameStop } from '../editor_frame_plugin'; import { indexPatternDatasourceSetup, indexPatternDatasourceStop } from '../indexpattern_plugin'; +import { addHelpMenuToAppChrome } from '../help_menu_util'; import { SavedObjectIndexStore } from '../persistence'; import { xyVisualizationSetup, xyVisualizationStop } from '../xy_visualization_plugin'; import { metricVisualizationSetup, metricVisualizationStop } from '../metric_visualization_plugin'; @@ -31,10 +40,15 @@ import { stopReportManager, trackUiEvent, } from '../lens_ui_telemetry'; +import { LocalApplicationService } from '../../../../../../src/legacy/core_plugins/kibana/public/local_application_service'; +import { NOT_INTERNATIONALIZED_PRODUCT_NAME } from '../../index'; export interface LensPluginStartDependencies { data: DataPublicPluginStart; dataShim: DataStart; + __LEGACY: { + localApplicationService: LocalApplicationService; + }; } export class AppPlugin { private instance: EditorFrameInstance | null = null; @@ -58,11 +72,16 @@ export class AppPlugin { editorFrameSetupInterface.registerDatasource('indexpattern', indexPattern); } - start(core: CoreStart, { data, dataShim }: LensPluginStartDependencies) { + start( + core: CoreStart, + { data, dataShim, __LEGACY: { localApplicationService } }: LensPluginStartDependencies + ) { if (this.store === null) { throw new Error('Start lifecycle called before setup lifecycle'); } + addHelpMenuToAppChrome(core.chrome); + const store = this.store; const editorFrameStartInterface = editorFrameStart(); @@ -89,9 +108,9 @@ export class AppPlugin { docStorage={store} redirectTo={id => { if (!id) { - routeProps.history.push('/'); + routeProps.history.push('/lens'); } else { - routeProps.history.push(`/edit/${id}`); + routeProps.history.push(`/lens/edit/${id}`); } }} /> @@ -103,17 +122,27 @@ export class AppPlugin { return ; } - return ( - - - - - - - - - - ); + localApplicationService.register({ + id: 'lens', + title: NOT_INTERNATIONALIZED_PRODUCT_NAME, + mount: async (context, params) => { + render( + + + + + + + + + , + params.element + ); + return () => { + unmountComponentAtNode(params.element); + }; + }, + }); } stop() { @@ -131,10 +160,3 @@ export class AppPlugin { editorFrameStop(); } } - -const app = new AppPlugin(); - -export const appSetup = () => app.setup(npSetup.core, {}); -export const appStart = () => - app.start(npStart.core, { dataShim: dataShimStart, data: npStart.plugins.data }); -export const appStop = () => app.stop(); diff --git a/x-pack/legacy/plugins/lens/public/help_menu_util.tsx b/x-pack/legacy/plugins/lens/public/help_menu_util.tsx index 30a05dbc38537..9ead31690e854 100644 --- a/x-pack/legacy/plugins/lens/public/help_menu_util.tsx +++ b/x-pack/legacy/plugins/lens/public/help_menu_util.tsx @@ -4,55 +4,22 @@ * you may not use this file except in compliance with the Elastic License. */ -import React from 'react'; -import { EuiHorizontalRule, EuiSpacer, EuiLink, EuiText, EuiIcon, EuiButton } from '@elastic/eui'; import { ELASTIC_WEBSITE_URL, DOC_LINK_VERSION } from 'ui/documentation_links'; -import { i18n } from '@kbn/i18n'; -import { FormattedMessage } from '@kbn/i18n/react'; -import { render, unmountComponentAtNode } from 'react-dom'; -import { Chrome } from 'ui/chrome'; +import { ChromeStart } from 'kibana/public'; -const docsPage = 'lens'; - -export function addHelpMenuToAppChrome(chrome: Chrome) { - chrome.helpExtension.set(domElement => { - render(, domElement); - return () => { - unmountComponentAtNode(domElement); - }; +export function addHelpMenuToAppChrome(chrome: ChromeStart) { + chrome.setHelpExtension({ + appName: 'Lens', + links: [ + { + linkType: 'documentation', + href: `${ELASTIC_WEBSITE_URL}guide/en/kibana/${DOC_LINK_VERSION}/lens.html`, + }, + { + linkType: 'github', + title: '[Lens]', + labels: ['Feature:Lens'], + }, + ], }); } - -function HelpMenu() { - return ( - <> - - {docsPage && ( - <> - - - - - - )} - - - -   - - {i18n.translate('xpack.lens.helpMenu.feedbackLinkText', { - defaultMessage: 'Provide feedback for the Lens application', - })} - - - - ); -} diff --git a/x-pack/legacy/plugins/lens/public/index.ts b/x-pack/legacy/plugins/lens/public/index.ts index 2a5422d4bb8a1..9f4141dbcae7d 100644 --- a/x-pack/legacy/plugins/lens/public/index.ts +++ b/x-pack/legacy/plugins/lens/public/index.ts @@ -5,36 +5,3 @@ */ export * from './types'; - -import 'ui/autoload/all'; -// Used to run esaggs queries -import 'uiExports/fieldFormats'; -import 'uiExports/search'; -import 'uiExports/visRequestHandlers'; -import 'uiExports/visResponseHandlers'; -import 'uiExports/interpreter'; -// Used for kibana_context function -import 'uiExports/savedObjectTypes'; - -import { render, unmountComponentAtNode } from 'react-dom'; -import { IScope } from 'angular'; -import chrome from 'ui/chrome'; -import { appStart, appSetup, appStop } from './app_plugin'; -import { PLUGIN_ID } from '../common'; -import { addHelpMenuToAppChrome } from './help_menu_util'; - -// TODO: Convert this to the "new platform" way of doing UI -function Root($scope: IScope, $element: JQLite) { - const el = $element[0]; - $scope.$on('$destroy', () => { - unmountComponentAtNode(el); - appStop(); - }); - - appSetup(); - addHelpMenuToAppChrome(chrome); - - return render(appStart(), el); -} - -chrome.setRootController(PLUGIN_ID, Root); diff --git a/x-pack/legacy/plugins/lens/public/indexpattern_plugin/datapanel.test.tsx b/x-pack/legacy/plugins/lens/public/indexpattern_plugin/datapanel.test.tsx index affb1accbbef4..dc23df250ebd4 100644 --- a/x-pack/legacy/plugins/lens/public/indexpattern_plugin/datapanel.test.tsx +++ b/x-pack/legacy/plugins/lens/public/indexpattern_plugin/datapanel.test.tsx @@ -17,7 +17,6 @@ import { EuiProgress } from '@elastic/eui'; import { documentField } from './document_field'; jest.mock('ui/new_platform'); -jest.mock('../../../../../../src/legacy/ui/public/registry/field_formats'); const initialState: IndexPatternPrivateState = { indexPatternRefs: [], diff --git a/x-pack/legacy/plugins/lens/public/indexpattern_plugin/field_item.test.tsx b/x-pack/legacy/plugins/lens/public/indexpattern_plugin/field_item.test.tsx index 9956c0ec33061..1b49eb6bca7fa 100644 --- a/x-pack/legacy/plugins/lens/public/indexpattern_plugin/field_item.test.tsx +++ b/x-pack/legacy/plugins/lens/public/indexpattern_plugin/field_item.test.tsx @@ -10,63 +10,58 @@ import { EuiLoadingSpinner, EuiPopover } from '@elastic/eui'; import { FieldItem, FieldItemProps } from './field_item'; import { coreMock } from 'src/core/public/mocks'; import { mountWithIntl } from 'test_utils/enzyme_helpers'; +import { npStart } from 'ui/new_platform'; +import { FieldFormatsStart } from '../../../../../../src/plugins/data/public'; +import { IndexPattern } from './types'; jest.mock('ui/new_platform'); -// Formatter must be mocked to return a string, or the rendering will fail -jest.mock('../../../../../../src/legacy/ui/public/registry/field_formats', () => ({ - fieldFormats: { - getDefaultInstance: jest.fn().mockReturnValue({ - convert: jest.fn().mockReturnValue((s: unknown) => JSON.stringify(s)), - }), - }, -})); - const waitForPromises = () => new Promise(resolve => setTimeout(resolve)); -const indexPattern = { - id: '1', - title: 'my-fake-index-pattern', - timeFieldName: 'timestamp', - fields: [ - { - name: 'timestamp', - type: 'date', - aggregatable: true, - searchable: true, - }, - { - name: 'bytes', - type: 'number', - aggregatable: true, - searchable: true, - }, - { - name: 'memory', - type: 'number', - aggregatable: true, - searchable: true, - }, - { - name: 'unsupported', - type: 'geo', - aggregatable: true, - searchable: true, - }, - { - name: 'source', - type: 'string', - aggregatable: true, - searchable: true, - }, - ], -}; - describe('IndexPattern Field Item', () => { let defaultProps: FieldItemProps; + let indexPattern: IndexPattern; let core: ReturnType; beforeEach(() => { + indexPattern = { + id: '1', + title: 'my-fake-index-pattern', + timeFieldName: 'timestamp', + fields: [ + { + name: 'timestamp', + type: 'date', + aggregatable: true, + searchable: true, + }, + { + name: 'bytes', + type: 'number', + aggregatable: true, + searchable: true, + }, + { + name: 'memory', + type: 'number', + aggregatable: true, + searchable: true, + }, + { + name: 'unsupported', + type: 'geo', + aggregatable: true, + searchable: true, + }, + { + name: 'source', + type: 'string', + aggregatable: true, + searchable: true, + }, + ], + } as IndexPattern; + core = coreMock.createSetup(); core.http.post.mockClear(); defaultProps = { @@ -87,6 +82,12 @@ describe('IndexPattern Field Item', () => { }, exists: true, }; + + npStart.plugins.data.fieldFormats = ({ + getDefaultInstance: jest.fn(() => ({ + convert: jest.fn((s: unknown) => JSON.stringify(s)), + })), + } as unknown) as FieldFormatsStart; }); it('should request field stats every time the button is clicked', async () => { diff --git a/x-pack/legacy/plugins/lens/public/indexpattern_plugin/field_item.tsx b/x-pack/legacy/plugins/lens/public/indexpattern_plugin/field_item.tsx index 3536ad8053891..20505107be122 100644 --- a/x-pack/legacy/plugins/lens/public/indexpattern_plugin/field_item.tsx +++ b/x-pack/legacy/plugins/lens/public/indexpattern_plugin/field_item.tsx @@ -7,48 +7,49 @@ import React, { useState } from 'react'; import DateMath from '@elastic/datemath'; import { + EuiButtonGroup, EuiFlexGroup, EuiFlexItem, - EuiProgress, - EuiPopover, - EuiLoadingSpinner, + EuiIconTip, EuiKeyboardAccessible, - EuiText, - EuiToolTip, - EuiButtonGroup, + EuiLoadingSpinner, + EuiPopover, EuiPopoverFooter, EuiPopoverTitle, - EuiIconTip, + EuiProgress, + EuiText, + EuiToolTip, } from '@elastic/eui'; +import { npStart } from 'ui/new_platform'; import { EUI_CHARTS_THEME_DARK, EUI_CHARTS_THEME_LIGHT } from '@elastic/eui/dist/eui_charts_theme'; import { - Chart, Axis, + BarSeries, + Chart, + DataSeriesColorsValues, getAxisId, getSpecId, - BarSeries, + niceTimeFormatter, Position, ScaleType, Settings, - DataSeriesColorsValues, TooltipType, - niceTimeFormatter, } from '@elastic/charts'; import { i18n } from '@kbn/i18n'; import { Query, + KBN_FIELD_TYPES, + ES_FIELD_TYPES, esFilters, esQuery, IIndexPattern, } from '../../../../../../src/plugins/data/public'; -// @ts-ignore -import { fieldFormats } from '../../../../../../src/legacy/ui/public/registry/field_formats'; import { DraggedField } from './indexpattern'; import { DragDrop } from '../drag_drop'; import { DatasourceDataPanelProps, DataType } from '../types'; import { BucketedAggregation, FieldStatsResponse } from '../../common'; import { IndexPattern, IndexPatternField } from './types'; -import { LensFieldIcon, getColorForDataType } from './lens_field_icon'; +import { getColorForDataType, LensFieldIcon } from './lens_field_icon'; import { trackUiEvent } from '../lens_ui_telemetry'; export interface FieldItemProps { @@ -238,6 +239,7 @@ export function FieldItem(props: FieldItemProps) { } function FieldItemPopoverContents(props: State & FieldItemProps) { + const fieldFormats = npStart.plugins.data.fieldFormats; const { histogram, topValues, indexPattern, field, dateRange, core, sampledValues } = props; const IS_DARK_THEME = core.uiSettings.get('theme:darkMode'); @@ -289,7 +291,10 @@ function FieldItemPopoverContents(props: State & FieldItemProps) { formatter = { convert: (data: unknown) => JSON.stringify(data) }; } } else { - formatter = fieldFormats.getDefaultInstance(field.type, field.esTypes); + formatter = fieldFormats.getDefaultInstance( + field.type as KBN_FIELD_TYPES, + field.esTypes as ES_FIELD_TYPES[] + ); } const euiButtonColor = @@ -370,7 +375,7 @@ function FieldItemPopoverContents(props: State & FieldItemProps) { )}{' '} {fieldFormats - .getDefaultInstance('number', ['integer']) + .getDefaultInstance(KBN_FIELD_TYPES.NUMBER, [ES_FIELD_TYPES.INTEGER]) .convert(props.totalDocuments)} {' '} {i18n.translate('xpack.lens.indexPattern.ofDocumentsLabel', { diff --git a/x-pack/legacy/plugins/lens/public/legacy.ts b/x-pack/legacy/plugins/lens/public/legacy.ts new file mode 100644 index 0000000000000..0285e041de78c --- /dev/null +++ b/x-pack/legacy/plugins/lens/public/legacy.ts @@ -0,0 +1,23 @@ +/* + * 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 { npSetup, npStart } from 'ui/new_platform'; +import { start as dataShimStart } from '../../../../../src/legacy/core_plugins/data/public/legacy'; + +export * from './types'; + +import { localApplicationService } from '../../../../../src/legacy/core_plugins/kibana/public/local_application_service'; +import { AppPlugin } from './app_plugin'; + +const app = new AppPlugin(); +app.setup(npSetup.core, {}); +app.start(npStart.core, { + dataShim: dataShimStart, + data: npStart.plugins.data, + __LEGACY: { + localApplicationService, + }, +}); diff --git a/x-pack/legacy/plugins/lens/public/metric_visualization_plugin/metric_expression.test.tsx b/x-pack/legacy/plugins/lens/public/metric_visualization_plugin/metric_expression.test.tsx index ba1ac461161b1..9220c3ec75fad 100644 --- a/x-pack/legacy/plugins/lens/public/metric_visualization_plugin/metric_expression.test.tsx +++ b/x-pack/legacy/plugins/lens/public/metric_visualization_plugin/metric_expression.test.tsx @@ -9,7 +9,7 @@ import { LensMultiTable } from '../types'; import React from 'react'; import { shallow } from 'enzyme'; import { MetricConfig } from './types'; -import { FieldFormat } from 'ui/registry/field_formats'; +import { FieldFormat } from '../../../../../../src/plugins/data/public'; function sampleArgs() { const data: LensMultiTable = { diff --git a/x-pack/legacy/plugins/lens/public/redirect.ts b/x-pack/legacy/plugins/lens/public/redirect.ts new file mode 100644 index 0000000000000..25b0188214c5e --- /dev/null +++ b/x-pack/legacy/plugins/lens/public/redirect.ts @@ -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. + */ + +// This file redirects lens urls starting with app/lens#... to their counterpart on app/kibana#lens/... to +// make sure it's compatible with the 7.5 release + +import { npSetup } from 'ui/new_platform'; +import chrome from 'ui/chrome'; + +chrome.setRootController('lens', () => { + // prefix the path in the hash with lens/ + const prefixedHashRoute = window.location.hash.replace(/^#\//, '#/lens/'); + + // redirect to the new lens url `app/kibana#/lens/...` + window.location.href = npSetup.core.http.basePath.prepend('/app/kibana' + prefixedHashRoute); +}); diff --git a/x-pack/legacy/plugins/lens/public/register_embeddable.ts b/x-pack/legacy/plugins/lens/public/register_embeddable.ts deleted file mode 100644 index f86cb91a0029e..0000000000000 --- a/x-pack/legacy/plugins/lens/public/register_embeddable.ts +++ /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 { indexPatternDatasourceSetup } from './indexpattern_plugin'; -import { xyVisualizationSetup } from './xy_visualization_plugin'; -import { editorFrameSetup, editorFrameStart } from './editor_frame_plugin'; -import { datatableVisualizationSetup } from './datatable_visualization_plugin'; -import { metricVisualizationSetup } from './metric_visualization_plugin'; - -// bootstrap shimmed plugins to register everything necessary (expression functions and embeddables). -// the new platform will take care of this once in place. -indexPatternDatasourceSetup(); -datatableVisualizationSetup(); -xyVisualizationSetup(); -metricVisualizationSetup(); -editorFrameSetup(); -editorFrameStart(); diff --git a/x-pack/legacy/plugins/lens/public/register_vis_type_alias.ts b/x-pack/legacy/plugins/lens/public/register_vis_type_alias.ts index 562d0f0ef6135..185df12054a3c 100644 --- a/x-pack/legacy/plugins/lens/public/register_vis_type_alias.ts +++ b/x-pack/legacy/plugins/lens/public/register_vis_type_alias.ts @@ -6,10 +6,10 @@ import { i18n } from '@kbn/i18n'; import { visualizations } from '../../../../../src/legacy/core_plugins/visualizations/public'; -import { BASE_APP_URL, getEditPath } from '../common'; +import { getBasePath, getEditPath } from '../common'; visualizations.types.registerAlias({ - aliasUrl: BASE_APP_URL, + aliasUrl: getBasePath(), name: 'lens', promotion: { description: i18n.translate('xpack.lens.visTypeAlias.promotion.description', { diff --git a/x-pack/legacy/plugins/license_management/__jest__/__snapshots__/add_license.test.js.snap b/x-pack/legacy/plugins/license_management/__jest__/__snapshots__/add_license.test.js.snap index d5be772af9441..03421e66c77f5 100644 --- a/x-pack/legacy/plugins/license_management/__jest__/__snapshots__/add_license.test.js.snap +++ b/x-pack/legacy/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`] = `"
"`; -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.

"`; diff --git a/x-pack/legacy/plugins/license_management/__jest__/__snapshots__/request_trial_extension.test.js.snap b/x-pack/legacy/plugins/license_management/__jest__/__snapshots__/request_trial_extension.test.js.snap index 8d91ddcc563df..8670b2c378dca 100644 --- a/x-pack/legacy/plugins/license_management/__jest__/__snapshots__/request_trial_extension.test.js.snap +++ b/x-pack/legacy/plugins/license_management/__jest__/__snapshots__/request_trial_extension.test.js.snap @@ -1,7 +1,7 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`RequestTrialExtension component should display when license is active and trial has been used 1`] = `"
Extend your trial

If you’d like to continue using machine learning, advanced security, and our other awesome Platinum features, request an extension now.

Extend trial
"`; +exports[`RequestTrialExtension component should display when license is active and trial has been used 1`] = `"
Extend your trial

If you’d like to continue using machine learning, advanced security, and our other awesome Platinum features, request an extension now.

"`; -exports[`RequestTrialExtension component should display when license is not active and trial has been used 1`] = `"
Extend your trial

If you’d like to continue using machine learning, advanced security, and our other awesome Platinum features, request an extension now.

Extend trial
"`; +exports[`RequestTrialExtension component should display when license is not active and trial has been used 1`] = `"
Extend your trial

If you’d like to continue using machine learning, advanced security, and our other awesome Platinum features, request an extension now.

"`; -exports[`RequestTrialExtension component should display when platinum license is not active and trial has been used 1`] = `"
Extend your trial

If you’d like to continue using machine learning, advanced security, and our other awesome Platinum features, request an extension now.

Extend trial
"`; +exports[`RequestTrialExtension component should display when platinum license is not active and trial has been used 1`] = `"
Extend your trial

If you’d like to continue using machine learning, advanced security, and our other awesome Platinum features, request an extension now.

"`; diff --git a/x-pack/legacy/plugins/license_management/__jest__/__snapshots__/revert_to_basic.test.js.snap b/x-pack/legacy/plugins/license_management/__jest__/__snapshots__/revert_to_basic.test.js.snap index 3b3cf35dcfd91..cb2a41dadbe9e 100644 --- a/x-pack/legacy/plugins/license_management/__jest__/__snapshots__/revert_to_basic.test.js.snap +++ b/x-pack/legacy/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 machine learning, advanced security, 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 machine learning, advanced security, 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 machine learning, advanced security, 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 machine learning, advanced security, 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 machine learning, advanced security, 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 machine learning, advanced security, and other Platinum features.

"`; diff --git a/x-pack/legacy/plugins/license_management/__jest__/__snapshots__/start_trial.test.js.snap b/x-pack/legacy/plugins/license_management/__jest__/__snapshots__/start_trial.test.js.snap index 9812152dc6363..df82a820e9513 100644 --- a/x-pack/legacy/plugins/license_management/__jest__/__snapshots__/start_trial.test.js.snap +++ b/x-pack/legacy/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 machine learning, advanced security, 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 machine learning, advanced security, 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 machine learning, advanced security, 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 machine learning, advanced security, 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 machine learning, advanced security, 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 machine learning, advanced security, and all our other Platinum features have to offer.

"`; diff --git a/x-pack/legacy/plugins/maps/public/components/help_menu.js b/x-pack/legacy/plugins/maps/public/components/help_menu.js deleted file mode 100644 index 34cb66eb7bd83..0000000000000 --- a/x-pack/legacy/plugins/maps/public/components/help_menu.js +++ /dev/null @@ -1,39 +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, { Fragment, PureComponent } from 'react'; -import { EuiButton, EuiHorizontalRule, EuiSpacer, EuiLink, EuiText, EuiIcon } from '@elastic/eui'; -import { ELASTIC_WEBSITE_URL, DOC_LINK_VERSION } from 'ui/documentation_links'; -import { i18n } from '@kbn/i18n'; -import { FormattedMessage } from '@kbn/i18n/react'; - -export class HelpMenu extends PureComponent { - render() { - return ( - - - - - - - - -   - - {i18n.translate('xpack.maps.helpMenu.feedbackLinkText', { - defaultMessage: 'Provide feedback for the Maps application', - })} - - - - ); - } -} diff --git a/x-pack/legacy/plugins/maps/public/help_menu_util.js b/x-pack/legacy/plugins/maps/public/help_menu_util.js index c81261554004a..72d51cc180eb3 100644 --- a/x-pack/legacy/plugins/maps/public/help_menu_util.js +++ b/x-pack/legacy/plugins/maps/public/help_menu_util.js @@ -3,15 +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 { render, unmountComponentAtNode } from 'react-dom'; -import { HelpMenu } from './components/help_menu'; +import { ELASTIC_WEBSITE_URL, DOC_LINK_VERSION } from 'ui/documentation_links'; export function addHelpMenuToAppChrome(chrome) { - chrome.helpExtension.set(domElement => { - render(, domElement); - return () => { - unmountComponentAtNode(domElement); - }; + chrome.helpExtension.set({ + appName: 'Maps', + links: [ + { + linkType: 'documentation', + href: `${ELASTIC_WEBSITE_URL}guide/en/kibana/${DOC_LINK_VERSION}/maps.html`, + }, + { + linkType: 'github', + title: '[Maps]', + labels: ['Team:Geo'], + }, + ], }); } diff --git a/x-pack/legacy/plugins/maps/public/index.js b/x-pack/legacy/plugins/maps/public/index.js index 49d8646c6a251..964753f464d95 100644 --- a/x-pack/legacy/plugins/maps/public/index.js +++ b/x-pack/legacy/plugins/maps/public/index.js @@ -10,7 +10,6 @@ import { wrapInI18nContext } from 'ui/i18n'; import { i18n } from '@kbn/i18n'; // import the uiExports that we want to "use" -import 'uiExports/fieldFormats'; import 'uiExports/inspectorViews'; import 'uiExports/search'; import 'uiExports/embeddableFactories'; diff --git a/x-pack/legacy/plugins/ml/public/app.js b/x-pack/legacy/plugins/ml/public/app.js index b88346035f306..ead1af5f64e07 100644 --- a/x-pack/legacy/plugins/ml/public/app.js +++ b/x-pack/legacy/plugins/ml/public/app.js @@ -5,8 +5,6 @@ */ -// import the uiExports that we want to "use" -import 'uiExports/fieldFormats'; import 'uiExports/savedObjectTypes'; import 'ui/autoload/all'; diff --git a/x-pack/legacy/plugins/ml/public/components/navigation_menu/top_nav/__snapshots__/top_nav.test.tsx.snap b/x-pack/legacy/plugins/ml/public/components/navigation_menu/top_nav/__snapshots__/top_nav.test.tsx.snap index b898558b20738..f9df085d2cbe7 100644 --- a/x-pack/legacy/plugins/ml/public/components/navigation_menu/top_nav/__snapshots__/top_nav.test.tsx.snap +++ b/x-pack/legacy/plugins/ml/public/components/navigation_menu/top_nav/__snapshots__/top_nav.test.tsx.snap @@ -69,6 +69,7 @@ exports[`Navigation Menu: Minimal initialization. 1`] = ` refreshInterval={0} showUpdateButton={true} start="Thu Aug 29 2019 02:04:19 GMT+0200" + timeFormat="HH:mm" />
diff --git a/x-pack/legacy/plugins/ml/public/formatters/__tests__/abbreviate_whole_number.js b/x-pack/legacy/plugins/ml/public/formatters/__tests__/abbreviate_whole_number.js deleted file mode 100644 index 4e85bae4b1862..0000000000000 --- a/x-pack/legacy/plugins/ml/public/formatters/__tests__/abbreviate_whole_number.js +++ /dev/null @@ -1,42 +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 '@kbn/expect'; -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/legacy/plugins/ml/public/formatters/__tests__/format_value.js b/x-pack/legacy/plugins/ml/public/formatters/__tests__/format_value.js deleted file mode 100644 index ffdbdd915d3a8..0000000000000 --- a/x-pack/legacy/plugins/ml/public/formatters/__tests__/format_value.js +++ /dev/null @@ -1,93 +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 '@kbn/expect'; -import moment from 'moment-timezone'; -import { formatValue } from '../format_value'; - -describe('ML - formatValue formatter', () => { - const timeOfWeekRecord = { - job_id: 'gallery_time_of_week', - result_type: 'record', - probability: 0.012818, - record_score: 53.55134, - bucket_span: 900, - detector_index: 0, - timestamp: 1530155700000, - by_field_name: 'clientip', - by_field_value: '65.55.215.39', - function: 'time_of_week', - function_description: 'time' - }; - - const timeOfDayRecord = { - job_id: 'gallery_time_of_day', - result_type: 'record', - probability: 0.012818, - record_score: 97.94245, - bucket_span: 900, - detector_index: 0, - timestamp: 1517472900000, - by_field_name: 'clientip', - by_field_value: '157.56.93.83', - function: 'time_of_day', - function_description: 'time' - }; - - // Set timezone to US/Eastern for time_of_day and time_of_week tests. - beforeEach(() => { - moment.tz.setDefault('US/Eastern'); - }); - - afterEach(() => { - moment.tz.setDefault('Browser'); - }); - - // For time_of_day and time_of_week test values which are offsets in seconds - // from UTC start of week / day are formatted correctly using the test timezone. - it('correctly formats time_of_week value from numeric input', () => { - expect(formatValue(359739, 'time_of_week', undefined, timeOfWeekRecord)).to.be('Wed 23:55'); - }); - - it('correctly formats time_of_day value from numeric input', () => { - expect(formatValue(73781, 'time_of_day', undefined, timeOfDayRecord)).to.be('15:29'); - }); - - 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', () => { - expect(formatValue([359739], 'time_of_week', undefined, timeOfWeekRecord)).to.be('Wed 23:55'); - }); - - it('correctly formats time_of_day value from array input', () => { - expect(formatValue([73781], 'time_of_day', undefined, timeOfDayRecord)).to.be('15:29'); - }); - - 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/legacy/plugins/ml/public/formatters/__tests__/metric_change_description.js b/x-pack/legacy/plugins/ml/public/formatters/__tests__/metric_change_description.js deleted file mode 100644 index 45864ce58bf83..0000000000000 --- a/x-pack/legacy/plugins/ml/public/formatters/__tests__/metric_change_description.js +++ /dev/null @@ -1,33 +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 '@kbn/expect'; -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/legacy/plugins/ml/public/formatters/abbreviate_whole_number.test.ts b/x-pack/legacy/plugins/ml/public/formatters/abbreviate_whole_number.test.ts new file mode 100644 index 0000000000000..feabaa4064978 --- /dev/null +++ b/x-pack/legacy/plugins/ml/public/formatters/abbreviate_whole_number.test.ts @@ -0,0 +1,37 @@ +/* + * 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 { abbreviateWholeNumber } from './abbreviate_whole_number'; + +describe('ML - abbreviateWholeNumber formatter', () => { + test('returns the correct format using default max digits', () => { + expect(abbreviateWholeNumber(1)).toBe(1); + expect(abbreviateWholeNumber(12)).toBe(12); + expect(abbreviateWholeNumber(123)).toBe(123); + expect(abbreviateWholeNumber(1234)).toBe('1k'); + expect(abbreviateWholeNumber(12345)).toBe('12k'); + expect(abbreviateWholeNumber(123456)).toBe('123k'); + expect(abbreviateWholeNumber(1234567)).toBe('1m'); + expect(abbreviateWholeNumber(12345678)).toBe('12m'); + expect(abbreviateWholeNumber(123456789)).toBe('123m'); + expect(abbreviateWholeNumber(1234567890)).toBe('1b'); + expect(abbreviateWholeNumber(5555555555555.55)).toBe('6t'); + }); + + test('returns the correct format using custom max digits', () => { + expect(abbreviateWholeNumber(1, 4)).toBe(1); + expect(abbreviateWholeNumber(12, 4)).toBe(12); + expect(abbreviateWholeNumber(123, 4)).toBe(123); + expect(abbreviateWholeNumber(1234, 4)).toBe(1234); + expect(abbreviateWholeNumber(12345, 4)).toBe('12k'); + expect(abbreviateWholeNumber(123456, 6)).toBe(123456); + expect(abbreviateWholeNumber(1234567, 4)).toBe('1m'); + expect(abbreviateWholeNumber(12345678, 3)).toBe('12m'); + expect(abbreviateWholeNumber(123456789, 9)).toBe(123456789); + expect(abbreviateWholeNumber(1234567890, 3)).toBe('1b'); + expect(abbreviateWholeNumber(5555555555555.55, 5)).toBe('6t'); + }); +}); diff --git a/x-pack/legacy/plugins/ml/public/formatters/abbreviate_whole_number.js b/x-pack/legacy/plugins/ml/public/formatters/abbreviate_whole_number.ts similarity index 89% rename from x-pack/legacy/plugins/ml/public/formatters/abbreviate_whole_number.js rename to x-pack/legacy/plugins/ml/public/formatters/abbreviate_whole_number.ts index 445681be4ff81..6d630c740a359 100644 --- a/x-pack/legacy/plugins/ml/public/formatters/abbreviate_whole_number.js +++ b/x-pack/legacy/plugins/ml/public/formatters/abbreviate_whole_number.ts @@ -4,15 +4,14 @@ * 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 = 3) { +export function abbreviateWholeNumber(value: number, maxDigits = 3) { if (Math.abs(value) < Math.pow(10, maxDigits)) { return value; } else { diff --git a/x-pack/legacy/plugins/ml/public/formatters/format_value.test.ts b/x-pack/legacy/plugins/ml/public/formatters/format_value.test.ts new file mode 100644 index 0000000000000..5f146aef97fcc --- /dev/null +++ b/x-pack/legacy/plugins/ml/public/formatters/format_value.test.ts @@ -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 moment from 'moment-timezone'; +import { AnomalyRecordDoc } from '../../common/types/anomalies'; +import { formatValue } from './format_value'; + +describe('ML - formatValue formatter', () => { + const timeOfWeekRecord: AnomalyRecordDoc = { + job_id: 'gallery_time_of_week', + result_type: 'record', + probability: 0.012818, + record_score: 53.55134, + initial_record_score: 53, + bucket_span: 900, + detector_index: 0, + is_interim: false, + timestamp: 1530155700000, + by_field_name: 'clientip', + by_field_value: '65.55.215.39', + function: 'time_of_week', + function_description: 'time', + }; + + const timeOfDayRecord: AnomalyRecordDoc = { + job_id: 'gallery_time_of_day', + result_type: 'record', + probability: 0.012818, + record_score: 97.94245, + initial_record_score: 97, + bucket_span: 900, + detector_index: 0, + is_interim: false, + timestamp: 1517472900000, + by_field_name: 'clientip', + by_field_value: '157.56.93.83', + function: 'time_of_day', + function_description: 'time', + }; + + // Set timezone to US/Eastern for time_of_day and time_of_week tests. + beforeEach(() => { + moment.tz.setDefault('US/Eastern'); + }); + + afterEach(() => { + moment.tz.setDefault('Browser'); + }); + + // For time_of_day and time_of_week test values which are offsets in seconds + // from UTC start of week / day are formatted correctly using the test timezone. + test('correctly formats time_of_week value from numeric input', () => { + expect(formatValue(359739, 'time_of_week', undefined, timeOfWeekRecord)).toBe('Wed 23:55'); + }); + + test('correctly formats time_of_day value from numeric input', () => { + expect(formatValue(73781, 'time_of_day', undefined, timeOfDayRecord)).toBe('15:29'); + }); + + test('correctly formats number values from numeric input', () => { + expect(formatValue(1483228800, 'mean')).toBe(1483228800); + expect(formatValue(1234.5678, 'mean')).toBe(1234.6); + expect(formatValue(0.00012345, 'mean')).toBe(0.000123); + expect(formatValue(0, 'mean')).toBe(0); + expect(formatValue(-0.12345, 'mean')).toBe(-0.123); + expect(formatValue(-1234.5678, 'mean')).toBe(-1234.6); + expect(formatValue(-100000.1, 'mean')).toBe(-100000); + }); + + test('correctly formats time_of_week value from array input', () => { + expect(formatValue([359739], 'time_of_week', undefined, timeOfWeekRecord)).toBe('Wed 23:55'); + }); + + test('correctly formats time_of_day value from array input', () => { + expect(formatValue([73781], 'time_of_day', undefined, timeOfDayRecord)).toBe('15:29'); + }); + + test('correctly formats number values from array input', () => { + expect(formatValue([1483228800], 'mean')).toBe(1483228800); + expect(formatValue([1234.5678], 'mean')).toBe(1234.6); + expect(formatValue([0.00012345], 'mean')).toBe(0.000123); + expect(formatValue([0], 'mean')).toBe(0); + expect(formatValue([-0.12345], 'mean')).toBe(-0.123); + expect(formatValue([-1234.5678], 'mean')).toBe(-1234.6); + expect(formatValue([-100000.1], 'mean')).toBe(-100000); + }); + + test('correctly formats multi-valued array', () => { + expect(formatValue([30.3, 26.2], 'lat_long')).toBe('[30.3,26.2]'); + }); +}); diff --git a/x-pack/legacy/plugins/ml/public/formatters/format_value.js b/x-pack/legacy/plugins/ml/public/formatters/format_value.ts similarity index 75% rename from x-pack/legacy/plugins/ml/public/formatters/format_value.js rename to x-pack/legacy/plugins/ml/public/formatters/format_value.ts index 48988b5561e70..9360957c4a911 100644 --- a/x-pack/legacy/plugins/ml/public/formatters/format_value.js +++ b/x-pack/legacy/plugins/ml/public/formatters/format_value.ts @@ -4,8 +4,6 @@ * 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 @@ -14,12 +12,8 @@ */ 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 +import { AnomalyRecordDoc } from '../../common/types/anomalies'; +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', @@ -29,7 +23,12 @@ const SIGFIGS_IF_ROUNDING = 3; // Number of sigfigs to use for values < 10 // For time_of_day or time_of_week functions the anomaly record // containing the timestamp of the anomaly should be supplied in // order to correctly format the day or week offset to the time of the anomaly. -export function formatValue(value, mlFunction, fieldFormat, record) { +export function formatValue( + value: number[] | number, + mlFunction: string, + fieldFormat?: any, + record?: AnomalyRecordDoc +) { // 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. @@ -54,7 +53,12 @@ export function formatValue(value, mlFunction, fieldFormat, record) { // For time_of_day or time_of_week functions the anomaly record // containing the timestamp of the anomaly should be supplied in // order to correctly format the day or week offset to the time of the anomaly. -function formatSingleValue(value, mlFunction, fieldFormat, record) { +function formatSingleValue( + value: number, + mlFunction: string, + fieldFormat?: any, + record?: AnomalyRecordDoc +) { if (value === undefined || value === null) { return ''; } @@ -65,14 +69,24 @@ function formatSingleValue(value, mlFunction, fieldFormat, record) { // that the anomaly occurred using record timestamp if supplied, add on the offset, and finally // revert back to configured timezone for formatting. if (mlFunction === 'time_of_week') { - const d = ((record !== undefined && record.timestamp !== undefined) ? new Date(record.timestamp) : new Date()); - const i = parseInt(value); - const utcMoment = moment.utc(d).startOf('week').add(i, 's'); + const d = + record !== undefined && record.timestamp !== undefined + ? new Date(record.timestamp) + : new Date(); + const utcMoment = moment + .utc(d) + .startOf('week') + .add(value, 's'); return moment(utcMoment.valueOf()).format('ddd HH:mm'); } else if (mlFunction === 'time_of_day') { - const d = ((record !== undefined && record.timestamp !== undefined) ? new Date(record.timestamp) : new Date()); - const i = parseInt(value); - const utcMoment = moment.utc(d).startOf('day').add(i, 's'); + const d = + record !== undefined && record.timestamp !== undefined + ? new Date(record.timestamp) + : new Date(); + const utcMoment = moment + .utc(d) + .startOf('day') + .add(value, 's'); return moment(utcMoment.valueOf()).format('HH:mm'); } else { if (fieldFormat !== undefined) { @@ -81,32 +95,32 @@ function formatSingleValue(value, mlFunction, fieldFormat, record) { // 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)) { + 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 { + } 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); + 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); + multiple = Math.pow( + 10, + SIGFIGS_IF_ROUNDING - Math.floor(Math.log(-1 * value) / Math.LN10) - 1 + ); } - return (Math.round(value * multiple)) / multiple; + 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/legacy/plugins/ml/public/formatters/metric_change_description.js b/x-pack/legacy/plugins/ml/public/formatters/metric_change_description.js deleted file mode 100644 index 06074e9a842c5..0000000000000 --- a/x-pack/legacy/plugins/ml/public/formatters/metric_change_description.js +++ /dev/null @@ -1,139 +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. - */ - - - -/* - * Produces a concise textual description of how the - * actual value compares to the typical value for an anomaly. - */ - -import { i18n } from '@kbn/i18n'; -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: i18n.translate('xpack.ml.formatters.metricChangeDescription.unusualValuesDescription', { - defaultMessage: 'Unusual values', - }), - }; - } - } - - if (Array.isArray(typicalProp)) { - if (typicalProp.length === 1) { - typical = typicalProp[0]; - } - } - - if (actual === typical) { - // Very unlikely, but just in case. - message = i18n.translate('xpack.ml.formatters.metricChangeDescription.actualSameAsTypicalDescription', { - defaultMessage: '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; - if (factor > 1.5) { - if (factor <= 100) { - message = isHigher ? i18n.translate('xpack.ml.formatters.metricChangeDescription.moreThanOneAndHalfxHigherDescription', { - defaultMessage: '{factor}x higher', - values: { factor: Math.round(factor) }, - }) : i18n.translate('xpack.ml.formatters.metricChangeDescription.moreThanOneAndHalfxLowerDescription', { - defaultMessage: '{factor}x lower', - values: { factor: Math.round(factor) }, - }); - } else { - message = isHigher ? i18n.translate('xpack.ml.formatters.metricChangeDescription.moreThan100xHigherDescription', { - defaultMessage: 'More than 100x higher', - }) : i18n.translate('xpack.ml.formatters.metricChangeDescription.moreThan100xLowerDescription', { - defaultMessage: 'More than 100x lower', - }); - } - } else if (factor >= 1.05) { - message = isHigher ? i18n.translate('xpack.ml.formatters.metricChangeDescription.moreThanOneAndFiveHundredthsxHigherDescription', { - defaultMessage: '{factor}x higher', - values: { factor: factor.toPrecision(2) }, - }) : i18n.translate('xpack.ml.formatters.metricChangeDescription.moreThanOneAndFiveHundredthsxLowerDescription', { - defaultMessage: '{factor}x lower', - values: { factor: factor.toPrecision(2) }, - }); - } else { - message = isHigher ? i18n.translate('xpack.ml.formatters.metricChangeDescription.unusuallyHighDescription', { - defaultMessage: 'Unusually high', - }) : i18n.translate('xpack.ml.formatters.metricChangeDescription.unusuallyLowDescription', { - defaultMessage: 'Unusually low', - }); - } - - } else { - if (actual === 0) { - message = i18n.translate('xpack.ml.formatters.metricChangeDescription.unexpectedZeroValueDescription', { - defaultMessage: 'Unexpected zero value', - }); - } else { - message = i18n.translate('xpack.ml.formatters.metricChangeDescription.unexpectedNonZeroValueDescription', { - defaultMessage: '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/legacy/plugins/ml/public/formatters/metric_change_description.test.ts b/x-pack/legacy/plugins/ml/public/formatters/metric_change_description.test.ts new file mode 100644 index 0000000000000..93533fe155e80 --- /dev/null +++ b/x-pack/legacy/plugins/ml/public/formatters/metric_change_description.test.ts @@ -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 { getMetricChangeDescription } from './metric_change_description'; + +describe('ML - metricChangeDescription formatter', () => { + test('returns correct icon and message if actual > typical', () => { + expect(getMetricChangeDescription(1.01, 1)).toEqual({ + iconType: 'sortUp', + message: 'Unusually high', + }); + expect(getMetricChangeDescription(1.123, 1)).toEqual({ + iconType: 'sortUp', + message: '1.1x higher', + }); + expect(getMetricChangeDescription(2, 1)).toEqual({ iconType: 'sortUp', message: '2x higher' }); + expect(getMetricChangeDescription(9.5, 1)).toEqual({ + iconType: 'sortUp', + message: '10x higher', + }); + expect(getMetricChangeDescription(1000, 1)).toEqual({ + iconType: 'sortUp', + message: 'More than 100x higher', + }); + expect(getMetricChangeDescription(1, 0)).toEqual({ + iconType: 'sortUp', + message: 'Unexpected non-zero value', + }); + }); + + test('returns correct icon and message if actual < typical', () => { + expect(getMetricChangeDescription(1, 1.01)).toEqual({ + iconType: 'sortDown', + message: 'Unusually low', + }); + expect(getMetricChangeDescription(1, 1.123)).toEqual({ + iconType: 'sortDown', + message: '1.1x lower', + }); + expect(getMetricChangeDescription(1, 2)).toEqual({ iconType: 'sortDown', message: '2x lower' }); + expect(getMetricChangeDescription(1, 9.5)).toEqual({ + iconType: 'sortDown', + message: '10x lower', + }); + expect(getMetricChangeDescription(1, 1000)).toEqual({ + iconType: 'sortDown', + message: 'More than 100x lower', + }); + expect(getMetricChangeDescription(0, 1)).toEqual({ + iconType: 'sortDown', + message: 'Unexpected zero value', + }); + }); +}); diff --git a/x-pack/legacy/plugins/ml/public/formatters/metric_change_description.ts b/x-pack/legacy/plugins/ml/public/formatters/metric_change_description.ts new file mode 100644 index 0000000000000..68f437b5a1436 --- /dev/null +++ b/x-pack/legacy/plugins/ml/public/formatters/metric_change_description.ts @@ -0,0 +1,157 @@ +/* + * 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 { i18n } from '@kbn/i18n'; + +// Returns an Object containing a text message and EuiIcon type to +// describe how the actual value compares to the typical. +export function getMetricChangeDescription( + actualProp: number[] | number, + typicalProp: number[] | number +) { + if (actualProp === undefined || typicalProp === undefined) { + return { iconType: 'empty', message: '' }; + } + + let iconType: string = 'alert'; + let message: string; + + // For metric functions, actual and typical will be single value arrays. + let actual: number = 0; + let typical: number = 0; + if (Array.isArray(actualProp)) { + if (actualProp.length === 1) { + actual = actualProp[0]; + } else { + // lat_long anomalies currently the only multi-value case. + // 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: i18n.translate( + 'xpack.ml.formatters.metricChangeDescription.unusualValuesDescription', + { + defaultMessage: 'Unusual values', + } + ), + }; + } + } else { + actual = actualProp; + } + + if (Array.isArray(typicalProp)) { + if (typicalProp.length === 1) { + typical = typicalProp[0]; + } + } else { + typical = typicalProp; + } + + if (actual === typical) { + // Very unlikely, but just in case. + message = i18n.translate( + 'xpack.ml.formatters.metricChangeDescription.actualSameAsTypicalDescription', + { + defaultMessage: '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: number = isHigher ? actual / typical : typical / actual; + if (factor > 1.5) { + if (factor <= 100) { + message = isHigher + ? i18n.translate( + 'xpack.ml.formatters.metricChangeDescription.moreThanOneAndHalfxHigherDescription', + { + defaultMessage: '{factor}x higher', + values: { factor: Math.round(factor) }, + } + ) + : i18n.translate( + 'xpack.ml.formatters.metricChangeDescription.moreThanOneAndHalfxLowerDescription', + { + defaultMessage: '{factor}x lower', + values: { factor: Math.round(factor) }, + } + ); + } else { + message = isHigher + ? i18n.translate( + 'xpack.ml.formatters.metricChangeDescription.moreThan100xHigherDescription', + { + defaultMessage: 'More than 100x higher', + } + ) + : i18n.translate( + 'xpack.ml.formatters.metricChangeDescription.moreThan100xLowerDescription', + { + defaultMessage: 'More than 100x lower', + } + ); + } + } else if (factor >= 1.05) { + message = isHigher + ? i18n.translate( + 'xpack.ml.formatters.metricChangeDescription.moreThanOneAndFiveHundredthsxHigherDescription', + { + defaultMessage: '{factor}x higher', + values: { factor: factor.toPrecision(2) }, + } + ) + : i18n.translate( + 'xpack.ml.formatters.metricChangeDescription.moreThanOneAndFiveHundredthsxLowerDescription', + { + defaultMessage: '{factor}x lower', + values: { factor: factor.toPrecision(2) }, + } + ); + } else { + message = isHigher + ? i18n.translate('xpack.ml.formatters.metricChangeDescription.unusuallyHighDescription', { + defaultMessage: 'Unusually high', + }) + : i18n.translate('xpack.ml.formatters.metricChangeDescription.unusuallyLowDescription', { + defaultMessage: 'Unusually low', + }); + } + } else { + if (actual === 0) { + message = i18n.translate( + 'xpack.ml.formatters.metricChangeDescription.unexpectedZeroValueDescription', + { + defaultMessage: 'Unexpected zero value', + } + ); + } else { + message = i18n.translate( + 'xpack.ml.formatters.metricChangeDescription.unexpectedNonZeroValueDescription', + { + defaultMessage: 'Unexpected non-zero value', + } + ); + } + } + } + + return { iconType, message }; +} diff --git a/x-pack/legacy/plugins/ml/public/util/chart_utils.test.js b/x-pack/legacy/plugins/ml/public/util/chart_utils.test.js index 6d13f1bc66808..a229113826a2e 100644 --- a/x-pack/legacy/plugins/ml/public/util/chart_utils.test.js +++ b/x-pack/legacy/plugins/ml/public/util/chart_utils.test.js @@ -6,12 +6,6 @@ import seriesConfig from '../explorer/explorer_charts/__mocks__/mock_series_config_filebeat'; -jest.mock('ui/registry/field_formats', () => ({ - fieldFormats: { - getDefaultInstance: jest.fn(), - }, -})); - jest.mock('ui/timefilter', () => { const dateMath = require('@elastic/datemath'); let _time = undefined; diff --git a/x-pack/legacy/plugins/ml/public/util/time_buckets.js b/x-pack/legacy/plugins/ml/public/util/time_buckets.js index 6933ee6935e80..98cb677a4851a 100644 --- a/x-pack/legacy/plugins/ml/public/util/time_buckets.js +++ b/x-pack/legacy/plugins/ml/public/util/time_buckets.js @@ -9,10 +9,11 @@ import _ from 'lodash'; import moment from 'moment'; import dateMath from '@elastic/datemath'; import chrome from 'ui/chrome'; -import { fieldFormats } from 'ui/registry/field_formats'; +import { npStart } from 'ui/new_platform'; import { timeBucketsCalcAutoIntervalProvider } from './calc_auto_interval'; import { parseInterval } from '../../common/util/parse_interval'; +import { FIELD_FORMAT_IDS } from '../../../../../../src/plugins/data/public'; const unitsDesc = dateMath.unitsDesc; const largeMax = unitsDesc.indexOf('w'); // Multiple units of week or longer converted to days for ES intervals. @@ -316,7 +317,8 @@ TimeBuckets.prototype.getScaledDateFormat = function () { }; TimeBuckets.prototype.getScaledDateFormatter = function () { - const DateFieldFormat = fieldFormats.getType('date'); + const fieldFormats = npStart.plugins.data.fieldFormats; + const DateFieldFormat = fieldFormats.getType(FIELD_FORMAT_IDS.DATE); return new DateFieldFormat({ pattern: this.getScaledDateFormat() }, getConfig); diff --git a/x-pack/legacy/plugins/remote_clusters/public/app/sections/components/remote_cluster_form/__snapshots__/remote_cluster_form.test.js.snap b/x-pack/legacy/plugins/remote_clusters/public/app/sections/components/remote_cluster_form/__snapshots__/remote_cluster_form.test.js.snap index cf8cf37d2e4ee..bf309c65556a8 100644 --- a/x-pack/legacy/plugins/remote_clusters/public/app/sections/components/remote_cluster_form/__snapshots__/remote_cluster_form.test.js.snap +++ b/x-pack/legacy/plugins/remote_clusters/public/app/sections/components/remote_cluster_form/__snapshots__/remote_cluster_form.test.js.snap @@ -249,7 +249,7 @@ Array [ > +
+

+ Unable to fetch report info +

+
+
+
+
+ Could not fetch the job info +
+
+
+
+
} - tabIndex={1} - /> -
- + +
+ - - -
- } - onActivation={[Function]} - onDeactivation={[Function]} - persistentFocus={false} - /> - -
- - - - + + + + + +
-
- -

- Unable to fetch report info -

-
-
- - + Unable to fetch report info + + +
+
+ +
-
- -
- Could not fetch the job info -
-
-
+ +
+ Could not fetch the job info +
+
- -
+
+
-
+
- -
- - - - + } + tabIndex={0} + /> + +
+ + + ,
- - + + + } /> - - - } - /> - - + + - - -
- -
+
-
+
+ + } - tabIndex={1} - /> -
- + +
+ - - - } - onActivation={[Function]} - onDeactivation={[Function]} - persistentFocus={false} - /> - -
- - - - + + + + + +
-
- -

- Job Info -

-
-
- - + Job Info + + +
+
+ +
-
- -
- -
+ +
+
- -
+
+
-
+
- -
- - - - + } + tabIndex={0} + /> + +
+ + + ,
+ + } + > +
+
+ + + + API keys not enabled in Elasticsearch + + +
+ +
+ + + , + } + } + > + Contact your system administrator and refer to the + + + + docs + + + + to enable API keys. + +
+
+
+
+ +`; + +exports[`ApiKeysGridPage renders permission denied if user does not have required permissions 1`] = ` + + +
+ + +
+ + +

+ } + iconType="securityApp" + title={ +

+ +

+ } + > +
+ + + + + + + + + +
+ + + + +

+ + You need permission to manage API keys + +

+
+ +
+ + +
+

+ + Contact your system administrator. + +

+
+
+ + +
+ +
+ + +
+ + +`; diff --git a/x-pack/legacy/plugins/security/public/views/management/api_keys_grid/components/api_keys_grid_page.test.tsx b/x-pack/legacy/plugins/security/public/views/management/api_keys_grid/components/api_keys_grid_page.test.tsx new file mode 100644 index 0000000000000..19ac3881f78d9 --- /dev/null +++ b/x-pack/legacy/plugins/security/public/views/management/api_keys_grid/components/api_keys_grid_page.test.tsx @@ -0,0 +1,180 @@ +/* + * 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. + */ + +let mockSimulate403 = false; +let mockSimulate500 = false; +let mockAreApiKeysEnabled = true; +let mockIsAdmin = true; + +const mock403 = () => ({ body: { statusCode: 403 } }); +const mock500 = () => ({ body: { error: 'Internal Server Error', message: '', statusCode: 500 } }); + +jest.mock('../../../../lib/api_keys_api', () => { + return { + ApiKeysApi: { + async checkPrivileges() { + if (mockSimulate403) { + throw mock403(); + } + + return { + isAdmin: mockIsAdmin, + areApiKeysEnabled: mockAreApiKeysEnabled, + }; + }, + async getApiKeys() { + if (mockSimulate500) { + throw mock500(); + } + + return { + apiKeys: [ + { + creation: 1571322182082, + expiration: 1571408582082, + id: '0QQZ2m0BO2XZwgJFuWTT', + invalidated: false, + name: 'my-api-key', + realm: 'reserved', + username: 'elastic', + }, + ], + }; + }, + }, + }; +}); + +import { mountWithIntl } from 'test_utils/enzyme_helpers'; +import { ApiKeysGridPage } from './api_keys_grid_page'; +import React from 'react'; +import { ReactWrapper } from 'enzyme'; +import { EuiCallOut } from '@elastic/eui'; + +import { NotEnabled } from './not_enabled'; +import { PermissionDenied } from './permission_denied'; + +const waitForRender = async ( + wrapper: ReactWrapper, + condition: (wrapper: ReactWrapper) => boolean +) => { + return new Promise((resolve, reject) => { + const interval = setInterval(async () => { + await Promise.resolve(); + wrapper.update(); + if (condition(wrapper)) { + resolve(); + } + }, 10); + + setTimeout(() => { + clearInterval(interval); + reject(new Error('waitForRender timeout after 2000ms')); + }, 2000); + }); +}; + +describe('ApiKeysGridPage', () => { + beforeEach(() => { + mockSimulate403 = false; + mockSimulate500 = false; + mockAreApiKeysEnabled = true; + mockIsAdmin = true; + }); + + it('renders a loading state when fetching API keys', async () => { + const wrapper = mountWithIntl(); + + expect(wrapper.find('[data-test-subj="apiKeysSectionLoading"]')).toHaveLength(1); + }); + + it('renders a callout when API keys are not enabled', async () => { + mockAreApiKeysEnabled = false; + const wrapper = mountWithIntl(); + + await waitForRender(wrapper, updatedWrapper => { + return updatedWrapper.find(NotEnabled).length > 0; + }); + + expect(wrapper.find(NotEnabled)).toMatchSnapshot(); + }); + + it('renders permission denied if user does not have required permissions', async () => { + mockSimulate403 = true; + const wrapper = mountWithIntl(); + + await waitForRender(wrapper, updatedWrapper => { + return updatedWrapper.find(PermissionDenied).length > 0; + }); + + expect(wrapper.find(PermissionDenied)).toMatchSnapshot(); + }); + + it('renders error callout if error fetching API keys', async () => { + mockSimulate500 = true; + const wrapper = mountWithIntl(); + + await waitForRender(wrapper, updatedWrapper => { + return updatedWrapper.find(EuiCallOut).length > 0; + }); + + expect(wrapper.find('EuiCallOut[data-test-subj="apiKeysError"]')).toHaveLength(1); + }); + + describe('Admin view', () => { + const wrapper = mountWithIntl(); + + it('renders a callout indicating the user is an administrator', async () => { + const calloutEl = 'EuiCallOut[data-test-subj="apiKeyAdminDescriptionCallOut"]'; + + await waitForRender(wrapper, updatedWrapper => { + return updatedWrapper.find(calloutEl).length > 0; + }); + + expect(wrapper.find(calloutEl).text()).toEqual('You are an API Key administrator.'); + }); + + it('renders the correct description text', async () => { + const descriptionEl = 'EuiText[data-test-subj="apiKeysDescriptionText"]'; + + await waitForRender(wrapper, updatedWrapper => { + return updatedWrapper.find(descriptionEl).length > 0; + }); + + expect(wrapper.find(descriptionEl).text()).toEqual( + 'View and invalidate API keys. An API key sends requests on behalf of a user.' + ); + }); + }); + + describe('Non-admin view', () => { + mockIsAdmin = false; + const wrapper = mountWithIntl(); + + it('does NOT render a callout indicating the user is an administrator', async () => { + const descriptionEl = 'EuiText[data-test-subj="apiKeysDescriptionText"]'; + const calloutEl = 'EuiCallOut[data-test-subj="apiKeyAdminDescriptionCallOut"]'; + + await waitForRender(wrapper, updatedWrapper => { + return updatedWrapper.find(descriptionEl).length > 0; + }); + + expect(wrapper.find(calloutEl).length).toEqual(0); + }); + + it('renders the correct description text', async () => { + const descriptionEl = 'EuiText[data-test-subj="apiKeysDescriptionText"]'; + + await waitForRender(wrapper, updatedWrapper => { + return updatedWrapper.find(descriptionEl).length > 0; + }); + + expect(wrapper.find(descriptionEl).text()).toEqual( + 'View and invalidate your API keys. An API key sends requests on your behalf.' + ); + }); + }); +}); diff --git a/x-pack/legacy/plugins/security/public/views/management/api_keys_grid/components/api_keys_grid_page.tsx b/x-pack/legacy/plugins/security/public/views/management/api_keys_grid/components/api_keys_grid_page.tsx index 6bebf17c943a4..37838cfdb950d 100644 --- a/x-pack/legacy/plugins/security/public/views/management/api_keys_grid/components/api_keys_grid_page.tsx +++ b/x-pack/legacy/plugins/security/public/views/management/api_keys_grid/components/api_keys_grid_page.tsx @@ -86,7 +86,7 @@ export class ApiKeysGridPage extends Component { if (isLoadingApp) { return ( - + { } color="danger" iconType="alert" + data-test-subj="apiKeysError" > {statusCode}: {errorTitle} - {message} @@ -136,7 +137,7 @@ export class ApiKeysGridPage extends Component { } const description = ( - +

{isAdmin ? ( { color="success" iconType="user" size="s" + data-test-subj="apiKeyAdminDescriptionCallOut" /> diff --git a/x-pack/legacy/plugins/security/server/lib/__tests__/__fixtures__/server.ts b/x-pack/legacy/plugins/security/server/lib/__tests__/__fixtures__/server.ts index 82f91483dc60d..55b6f735cfced 100644 --- a/x-pack/legacy/plugins/security/server/lib/__tests__/__fixtures__/server.ts +++ b/x-pack/legacy/plugins/security/server/lib/__tests__/__fixtures__/server.ts @@ -37,6 +37,9 @@ export function serverFixture() { getUser: stub(), authenticate: stub(), deauthenticate: stub(), + authorization: { + application: stub(), + }, }, xpack_main: { diff --git a/x-pack/legacy/plugins/security/server/routes/api/v1/api_keys/get.test.js b/x-pack/legacy/plugins/security/server/routes/api/v1/api_keys/get.test.js new file mode 100644 index 0000000000000..400e5b705aeb2 --- /dev/null +++ b/x-pack/legacy/plugins/security/server/routes/api/v1/api_keys/get.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 Hapi from 'hapi'; +import Boom from 'boom'; + +import { initGetApiKeysApi } from './get'; +import { INTERNAL_API_BASE_PATH } from '../../../../../common/constants'; + +const createMockServer = () => new Hapi.Server({ debug: false, port: 8080 }); + +describe('GET API keys', () => { + const getApiKeysTest = ( + description, + { + preCheckLicenseImpl = () => null, + callWithRequestImpl, + asserts, + isAdmin = true, + } + ) => { + test(description, async () => { + const mockServer = createMockServer(); + const pre = jest.fn().mockImplementation(preCheckLicenseImpl); + const mockCallWithRequest = jest.fn(); + + if (callWithRequestImpl) { + mockCallWithRequest.mockImplementation(callWithRequestImpl); + } + + initGetApiKeysApi(mockServer, mockCallWithRequest, pre); + + const headers = { + authorization: 'foo', + }; + + const request = { + method: 'GET', + url: `${INTERNAL_API_BASE_PATH}/api_key?isAdmin=${isAdmin}`, + headers, + }; + + const { result, statusCode } = await mockServer.inject(request); + + expect(pre).toHaveBeenCalled(); + + if (callWithRequestImpl) { + expect(mockCallWithRequest).toHaveBeenCalledWith( + expect.objectContaining({ + headers: expect.objectContaining({ + authorization: headers.authorization, + }), + }), + 'shield.getAPIKeys', + { + owner: !isAdmin, + }, + ); + } else { + expect(mockCallWithRequest).not.toHaveBeenCalled(); + } + + expect(statusCode).toBe(asserts.statusCode); + expect(result).toEqual(asserts.result); + }); + }; + + describe('failure', () => { + getApiKeysTest('returns result of routePreCheckLicense', { + preCheckLicenseImpl: () => Boom.forbidden('test forbidden message'), + asserts: { + statusCode: 403, + result: { + error: 'Forbidden', + statusCode: 403, + message: 'test forbidden message', + }, + }, + }); + + getApiKeysTest('returns error from callWithRequest', { + callWithRequestImpl: async () => { + throw Boom.notAcceptable('test not acceptable message'); + }, + asserts: { + statusCode: 406, + result: { + error: 'Not Acceptable', + statusCode: 406, + message: 'test not acceptable message', + }, + }, + }); + }); + + describe('success', () => { + getApiKeysTest('returns API keys', { + callWithRequestImpl: async () => ({ + api_keys: + [{ + id: 'YCLV7m0BJ3xI4hhWB648', + name: 'test-api-key', + creation: 1571670001452, + expiration: 1571756401452, + invalidated: false, + username: 'elastic', + realm: 'reserved' + }] + }), + asserts: { + statusCode: 200, + result: { + apiKeys: + [{ + id: 'YCLV7m0BJ3xI4hhWB648', + name: 'test-api-key', + creation: 1571670001452, + expiration: 1571756401452, + invalidated: false, + username: 'elastic', + realm: 'reserved' + }] + }, + }, + }); + getApiKeysTest('returns only valid API keys', { + callWithRequestImpl: async () => ({ + api_keys: + [{ + id: 'YCLV7m0BJ3xI4hhWB648', + name: 'test-api-key1', + creation: 1571670001452, + expiration: 1571756401452, + invalidated: true, + username: 'elastic', + realm: 'reserved' + }, { + id: 'YCLV7m0BJ3xI4hhWB648', + name: 'test-api-key2', + creation: 1571670001452, + expiration: 1571756401452, + invalidated: false, + username: 'elastic', + realm: 'reserved' + }], + }), + asserts: { + statusCode: 200, + result: { + apiKeys: + [{ + id: 'YCLV7m0BJ3xI4hhWB648', + name: 'test-api-key2', + creation: 1571670001452, + expiration: 1571756401452, + invalidated: false, + username: 'elastic', + realm: 'reserved' + }] + }, + }, + }); + }); +}); diff --git a/x-pack/legacy/plugins/security/server/routes/api/v1/api_keys/invalidate.test.js b/x-pack/legacy/plugins/security/server/routes/api/v1/api_keys/invalidate.test.js new file mode 100644 index 0000000000000..3ed7ca94eb782 --- /dev/null +++ b/x-pack/legacy/plugins/security/server/routes/api/v1/api_keys/invalidate.test.js @@ -0,0 +1,200 @@ +/* + * 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 Hapi from 'hapi'; +import Boom from 'boom'; + +import { initInvalidateApiKeysApi } from './invalidate'; +import { INTERNAL_API_BASE_PATH } from '../../../../../common/constants'; + +const createMockServer = () => new Hapi.Server({ debug: false, port: 8080 }); + +describe('POST invalidate', () => { + const postInvalidateTest = ( + description, + { + preCheckLicenseImpl = () => null, + callWithRequestImpls = [], + asserts, + payload, + } + ) => { + test(description, async () => { + const mockServer = createMockServer(); + const pre = jest.fn().mockImplementation(preCheckLicenseImpl); + const mockCallWithRequest = jest.fn(); + + for (const impl of callWithRequestImpls) { + mockCallWithRequest.mockImplementationOnce(impl); + } + + initInvalidateApiKeysApi(mockServer, mockCallWithRequest, pre); + + const headers = { + authorization: 'foo', + }; + + const request = { + method: 'POST', + url: `${INTERNAL_API_BASE_PATH}/api_key/invalidate`, + headers, + payload, + }; + + const { result, statusCode } = await mockServer.inject(request); + + expect(pre).toHaveBeenCalled(); + + if (asserts.callWithRequests) { + for (const args of asserts.callWithRequests) { + expect(mockCallWithRequest).toHaveBeenCalledWith( + expect.objectContaining({ + headers: expect.objectContaining({ + authorization: headers.authorization, + }), + }), + ...args + ); + } + } else { + expect(mockCallWithRequest).not.toHaveBeenCalled(); + } + + expect(statusCode).toBe(asserts.statusCode); + expect(result).toEqual(asserts.result); + }); + }; + + describe('failure', () => { + postInvalidateTest('returns result of routePreCheckLicense', { + preCheckLicenseImpl: () => Boom.forbidden('test forbidden message'), + payload: { + apiKeys: [{ id: 'si8If24B1bKsmSLTAhJV', name: 'my-api-key' }], + isAdmin: true + }, + asserts: { + statusCode: 403, + result: { + error: 'Forbidden', + statusCode: 403, + message: 'test forbidden message', + }, + }, + }); + + postInvalidateTest('returns errors array from callWithRequest', { + callWithRequestImpls: [async () => { + throw Boom.notAcceptable('test not acceptable message'); + }], + payload: { + apiKeys: [{ id: 'si8If24B1bKsmSLTAhJV', name: 'my-api-key', }], + isAdmin: true + }, + asserts: { + callWithRequests: [ + ['shield.invalidateAPIKey', { + body: { + id: 'si8If24B1bKsmSLTAhJV', + }, + }], + ], + statusCode: 200, + result: { + itemsInvalidated: [], + errors: [{ + id: 'si8If24B1bKsmSLTAhJV', + name: 'my-api-key', + error: Boom.notAcceptable('test not acceptable message'), + }] + }, + }, + }); + }); + + describe('success', () => { + postInvalidateTest('invalidates API keys', { + callWithRequestImpls: [async () => null], + payload: { + apiKeys: [{ id: 'si8If24B1bKsmSLTAhJV', name: 'my-api-key', }], + isAdmin: true + }, + asserts: { + callWithRequests: [ + ['shield.invalidateAPIKey', { + body: { + id: 'si8If24B1bKsmSLTAhJV', + }, + }], + ], + statusCode: 200, + result: { + itemsInvalidated: [{ id: 'si8If24B1bKsmSLTAhJV', name: 'my-api-key', }], + errors: [], + }, + }, + }); + + postInvalidateTest('adds "owner" to body if isAdmin=false', { + callWithRequestImpls: [async () => null], + payload: { + apiKeys: [{ id: 'si8If24B1bKsmSLTAhJV', name: 'my-api-key', }], + isAdmin: false + }, + asserts: { + callWithRequests: [ + ['shield.invalidateAPIKey', { + body: { + id: 'si8If24B1bKsmSLTAhJV', + owner: true, + }, + }], + ], + statusCode: 200, + result: { + itemsInvalidated: [{ id: 'si8If24B1bKsmSLTAhJV', name: 'my-api-key' }], + errors: [], + }, + }, + }); + + postInvalidateTest('returns only successful invalidation requests', { + callWithRequestImpls: [ + async () => null, + async () => { + throw Boom.notAcceptable('test not acceptable message'); + }], + payload: { + apiKeys: [ + { id: 'si8If24B1bKsmSLTAhJV', name: 'my-api-key1' }, + { id: 'ab8If24B1bKsmSLTAhNC', name: 'my-api-key2' } + ], + isAdmin: true + }, + asserts: { + callWithRequests: [ + ['shield.invalidateAPIKey', { + body: { + id: 'si8If24B1bKsmSLTAhJV', + }, + }], + ['shield.invalidateAPIKey', { + body: { + id: 'ab8If24B1bKsmSLTAhNC', + }, + }], + ], + statusCode: 200, + result: { + itemsInvalidated: [{ id: 'si8If24B1bKsmSLTAhJV', name: 'my-api-key1' }], + errors: [{ + id: 'ab8If24B1bKsmSLTAhNC', + name: 'my-api-key2', + error: Boom.notAcceptable('test not acceptable message'), + }] + }, + }, + }); + }); +}); diff --git a/x-pack/legacy/plugins/security/server/routes/api/v1/api_keys/privileges.test.js b/x-pack/legacy/plugins/security/server/routes/api/v1/api_keys/privileges.test.js new file mode 100644 index 0000000000000..2a6f935e00595 --- /dev/null +++ b/x-pack/legacy/plugins/security/server/routes/api/v1/api_keys/privileges.test.js @@ -0,0 +1,254 @@ +/* + * 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 Hapi from 'hapi'; +import Boom from 'boom'; + +import { initCheckPrivilegesApi } from './privileges'; +import { INTERNAL_API_BASE_PATH } from '../../../../../common/constants'; + +const createMockServer = () => new Hapi.Server({ debug: false, port: 8080 }); + +describe('GET privileges', () => { + const getPrivilegesTest = ( + description, + { + preCheckLicenseImpl = () => null, + callWithRequestImpls = [], + asserts, + } + ) => { + test(description, async () => { + const mockServer = createMockServer(); + const pre = jest.fn().mockImplementation(preCheckLicenseImpl); + const mockCallWithRequest = jest.fn(); + + for (const impl of callWithRequestImpls) { + mockCallWithRequest.mockImplementationOnce(impl); + } + + initCheckPrivilegesApi(mockServer, mockCallWithRequest, pre); + + const headers = { + authorization: 'foo', + }; + + const request = { + method: 'GET', + url: `${INTERNAL_API_BASE_PATH}/api_key/privileges`, + headers, + }; + + const { result, statusCode } = await mockServer.inject(request); + + expect(pre).toHaveBeenCalled(); + + if (asserts.callWithRequests) { + for (const args of asserts.callWithRequests) { + expect(mockCallWithRequest).toHaveBeenCalledWith( + expect.objectContaining({ + headers: expect.objectContaining({ + authorization: headers.authorization, + }), + }), + ...args + ); + } + } else { + expect(mockCallWithRequest).not.toHaveBeenCalled(); + } + + expect(statusCode).toBe(asserts.statusCode); + expect(result).toEqual(asserts.result); + }); + }; + + describe('failure', () => { + getPrivilegesTest('returns result of routePreCheckLicense', { + preCheckLicenseImpl: () => Boom.forbidden('test forbidden message'), + asserts: { + statusCode: 403, + result: { + error: 'Forbidden', + statusCode: 403, + message: 'test forbidden message', + }, + }, + }); + + getPrivilegesTest('returns error from first callWithRequest', { + callWithRequestImpls: [async () => { + throw Boom.notAcceptable('test not acceptable message'); + }, async () => { }], + asserts: { + callWithRequests: [ + ['shield.hasPrivileges', { + body: { + cluster: [ + 'manage_security', + 'manage_api_key', + ], + }, + }], + ['shield.getAPIKeys', { owner: true }], + ], + statusCode: 406, + result: { + error: 'Not Acceptable', + statusCode: 406, + message: 'test not acceptable message', + }, + }, + }); + + getPrivilegesTest('returns error from second callWithRequest', { + callWithRequestImpls: [async () => { }, async () => { + throw Boom.notAcceptable('test not acceptable message'); + }], + asserts: { + callWithRequests: [ + ['shield.hasPrivileges', { + body: { + cluster: [ + 'manage_security', + 'manage_api_key', + ], + }, + }], + ['shield.getAPIKeys', { owner: true }], + ], + statusCode: 406, + result: { + error: 'Not Acceptable', + statusCode: 406, + message: 'test not acceptable message', + }, + }, + }); + }); + + describe('success', () => { + getPrivilegesTest('returns areApiKeysEnabled and isAdmin', { + callWithRequestImpls: [ + async () => ({ + username: 'elastic', + has_all_requested: true, + cluster: { manage_api_key: true, manage_security: true }, + index: {}, + application: {} + }), + async () => ( + { + api_keys: + [{ + id: 'si8If24B1bKsmSLTAhJV', + name: 'my-api-key', + creation: 1574089261632, + expiration: 1574175661632, + invalidated: false, + username: 'elastic', + realm: 'reserved' + }] + } + ), + ], + asserts: { + callWithRequests: [ + ['shield.getAPIKeys', { owner: true }], + ['shield.hasPrivileges', { + body: { + cluster: [ + 'manage_security', + 'manage_api_key', + ], + }, + }], + ], + statusCode: 200, + result: { + areApiKeysEnabled: true, + isAdmin: true, + }, + }, + }); + + getPrivilegesTest('returns areApiKeysEnabled=false when getAPIKeys error message includes "api keys are not enabled"', { + callWithRequestImpls: [ + async () => ({ + username: 'elastic', + has_all_requested: true, + cluster: { manage_api_key: true, manage_security: true }, + index: {}, + application: {} + }), + async () => { + throw Boom.unauthorized('api keys are not enabled'); + }, + ], + asserts: { + callWithRequests: [ + ['shield.getAPIKeys', { owner: true }], + ['shield.hasPrivileges', { + body: { + cluster: [ + 'manage_security', + 'manage_api_key', + ], + }, + }], + ], + statusCode: 200, + result: { + areApiKeysEnabled: false, + isAdmin: true, + }, + }, + }); + + getPrivilegesTest('returns isAdmin=false when user has insufficient privileges', { + callWithRequestImpls: [ + async () => ({ + username: 'elastic', + has_all_requested: true, + cluster: { manage_api_key: false, manage_security: false }, + index: {}, + application: {} + }), + async () => ( + { + api_keys: + [{ + id: 'si8If24B1bKsmSLTAhJV', + name: 'my-api-key', + creation: 1574089261632, + expiration: 1574175661632, + invalidated: false, + username: 'elastic', + realm: 'reserved' + }] + } + ), + ], + asserts: { + callWithRequests: [ + ['shield.getAPIKeys', { owner: true }], + ['shield.hasPrivileges', { + body: { + cluster: [ + 'manage_security', + 'manage_api_key', + ], + }, + }], + ], + statusCode: 200, + result: { + areApiKeysEnabled: true, + isAdmin: false, + }, + }, + }); + }); +}); diff --git a/x-pack/legacy/plugins/siem/cypress/integration/smoke_tests/events_viewer/events_viewer.spec.ts b/x-pack/legacy/plugins/siem/cypress/integration/smoke_tests/events_viewer/events_viewer.spec.ts index 400f82bf81188..57a1f318a7e31 100644 --- a/x-pack/legacy/plugins/siem/cypress/integration/smoke_tests/events_viewer/events_viewer.spec.ts +++ b/x-pack/legacy/plugins/siem/cypress/integration/smoke_tests/events_viewer/events_viewer.spec.ts @@ -57,7 +57,7 @@ describe('Events Viewer', () => { .should('eq', 'Customize Columns'); }); - it.skip('closes the fields browser when the user clicks outside of it', () => { + it('closes the fields browser when the user clicks outside of it', () => { openEventsViewerFieldsBrowser(); clickOutsideFieldsBrowser(); @@ -81,7 +81,7 @@ describe('Events Viewer', () => { ); }); - it.skip('removes the message field from the timeline when the user un-checks the field', () => { + it('removes the message field from the timeline when the user un-checks the field', () => { const toggleField = 'message'; cy.get(`${EVENTS_VIEWER_PANEL} [data-test-subj="header-text-${toggleField}"]`).should('exist'); @@ -99,7 +99,7 @@ describe('Events Viewer', () => { ); }); - it.skip('filters the events by applying filter criteria from the search bar at the top of the page', () => { + it('filters the events by applying filter criteria from the search bar at the top of the page', () => { const filterInput = '4bf34c1c-eaa9-46de-8921-67a4ccc49829'; // this will never match real data cy.get(HEADER_SUBTITLE) @@ -119,7 +119,7 @@ describe('Events Viewer', () => { }); }); - it.skip('adds a field to the events viewer when the user clicks the checkbox', () => { + it('adds a field to the events viewer when the user clicks the checkbox', () => { const filterInput = 'host.geo.c'; const toggleField = 'host.geo.city_name'; @@ -158,7 +158,7 @@ describe('Events Viewer', () => { }); }); - it.skip('launches the inspect query modal when the inspect button is clicked', () => { + it('launches the inspect query modal when the inspect button is clicked', () => { // wait for data to load cy.get(HEADER_SUBTITLE) .invoke('text') @@ -171,7 +171,7 @@ describe('Events Viewer', () => { cy.get(INSPECT_MODAL, { timeout: DEFAULT_TIMEOUT }).should('exist'); }); - it.skip('resets all fields in the events viewer when `Reset Fields` is clicked', () => { + it('resets all fields in the events viewer when `Reset Fields` is clicked', () => { const filterInput = 'host.geo.c'; const toggleField = 'host.geo.city_name'; diff --git a/x-pack/legacy/plugins/siem/cypress/integration/smoke_tests/ml_conditional_links/ml_conditional_links.spec.ts b/x-pack/legacy/plugins/siem/cypress/integration/smoke_tests/ml_conditional_links/ml_conditional_links.spec.ts index cec5d6d88d86d..a03ff0c1845f8 100644 --- a/x-pack/legacy/plugins/siem/cypress/integration/smoke_tests/ml_conditional_links/ml_conditional_links.spec.ts +++ b/x-pack/legacy/plugins/siem/cypress/integration/smoke_tests/ml_conditional_links/ml_conditional_links.spec.ts @@ -28,7 +28,7 @@ describe('ml conditional links', () => { return logout(); }); - it.skip('sets the KQL from a single IP with a value for the query', () => { + it('sets the KQL from a single IP with a value for the query', () => { loginAndWaitForPage(mlNetworkSingleIpKqlQuery); cy.get(KQL_INPUT, { timeout: 5000 }).should( 'have.attr', @@ -37,7 +37,7 @@ describe('ml conditional links', () => { ); }); - it.skip('sets the KQL from a multiple IPs with a null for the query', () => { + it('sets the KQL from a multiple IPs with a null for the query', () => { loginAndWaitForPage(mlNetworkMultipleIpNullKqlQuery); cy.get(KQL_INPUT, { timeout: 5000 }).should( 'have.attr', @@ -46,7 +46,7 @@ describe('ml conditional links', () => { ); }); - it.skip('sets the KQL from a multiple IPs with a value for the query', () => { + it('sets the KQL from a multiple IPs with a value for the query', () => { loginAndWaitForPage(mlNetworkMultipleIpKqlQuery); cy.get(KQL_INPUT, { timeout: 5000 }).should( 'have.attr', @@ -55,7 +55,7 @@ describe('ml conditional links', () => { ); }); - it.skip('sets the KQL from a $ip$ with a value for the query', () => { + it('sets the KQL from a $ip$ with a value for the query', () => { loginAndWaitForPage(mlNetworkKqlQuery); cy.get(KQL_INPUT, { timeout: 5000 }).should( 'have.attr', @@ -64,7 +64,7 @@ describe('ml conditional links', () => { ); }); - it.skip('sets the KQL from a single host name with a value for query', () => { + it('sets the KQL from a single host name with a value for query', () => { loginAndWaitForPage(mlHostSingleHostKqlQuery); cy.get(KQL_INPUT, { timeout: 5000 }).should( 'have.attr', @@ -73,7 +73,7 @@ describe('ml conditional links', () => { ); }); - it.skip('sets the KQL from a multiple host names with null for query', () => { + it('sets the KQL from a multiple host names with null for query', () => { loginAndWaitForPage(mlHostMultiHostNullKqlQuery); cy.get(KQL_INPUT, { timeout: 5000 }).should( 'have.attr', @@ -82,7 +82,7 @@ describe('ml conditional links', () => { ); }); - it.skip('sets the KQL from a multiple host names with a value for query', () => { + it('sets the KQL from a multiple host names with a value for query', () => { loginAndWaitForPage(mlHostMultiHostKqlQuery); cy.get(KQL_INPUT, { timeout: 5000 }).should( 'have.attr', @@ -91,7 +91,7 @@ describe('ml conditional links', () => { ); }); - it.skip('sets the KQL from a undefined/null host name but with a value for query', () => { + it('sets the KQL from a undefined/null host name but with a value for query', () => { loginAndWaitForPage(mlHostVariableHostKqlQuery); cy.get(KQL_INPUT, { timeout: 5000 }).should( 'have.attr', @@ -100,7 +100,7 @@ describe('ml conditional links', () => { ); }); - it.skip('redirects from a single IP with a null for the query', () => { + it('redirects from a single IP with a null for the query', () => { loginAndWaitForPage(mlNetworkSingleIpNullKqlQuery); cy.url().should( 'include', @@ -108,7 +108,7 @@ describe('ml conditional links', () => { ); }); - it.skip('redirects from a single IP with a value for the query', () => { + it('redirects from a single IP with a value for the query', () => { loginAndWaitForPage(mlNetworkSingleIpKqlQuery); cy.url().should( 'include', @@ -116,7 +116,7 @@ describe('ml conditional links', () => { ); }); - it.skip('redirects from a multiple IPs with a null for the query', () => { + it('redirects from a multiple IPs with a null for the query', () => { loginAndWaitForPage(mlNetworkMultipleIpNullKqlQuery); cy.url().should( 'include', diff --git a/x-pack/legacy/plugins/siem/package.json b/x-pack/legacy/plugins/siem/package.json index 0e01921325222..ca5fefe52bcc4 100644 --- a/x-pack/legacy/plugins/siem/package.json +++ b/x-pack/legacy/plugins/siem/package.json @@ -7,7 +7,7 @@ "scripts": { "build-graphql-types": "node scripts/generate_types_from_graphql.js", "cypress:open": "../../../node_modules/.bin/cypress open", - "cypress:run": "../../../node_modules/.bin/cypress run --spec ./cypress/integration/**/*.spec.ts --reporter ../../../node_modules/mocha-multi-reporters --reporter-options configFile=./reporter_config.json; ../../../node_modules/.bin/mochawesome-merge --reportDir ../../../../target/kibana-siem/cypress/results > ../../../../target/kibana-siem/cypress/results/output.json; ../../../node_modules/.bin/marge ../../../../target/kibana-siem/cypress/results/output.json --reportDir ../../../../target/kibana-siem/cypress/results; mkdir -p ../../../../target/junit && cp ../../../../target/kibana-siem/cypress/results/*.xml ../../../../target/junit/" + "cypress:run": "../../../node_modules/.bin/cypress run --spec ./cypress/integration/**/*.spec.ts --reporter ../../../node_modules/cypress-multi-reporters --reporter-options configFile=./reporter_config.json; ../../../node_modules/.bin/mochawesome-merge --reportDir ../../../../target/kibana-siem/cypress/results > ../../../../target/kibana-siem/cypress/results/output.json; ../../../../node_modules/.bin/marge ../../../../target/kibana-siem/cypress/results/output.json --reportDir ../../../../target/kibana-siem/cypress/results; mkdir -p ../../../../target/junit && cp ../../../../target/kibana-siem/cypress/results/*.xml ../../../../target/junit/" }, "devDependencies": { "@types/lodash": "^4.14.110", @@ -18,16 +18,5 @@ "lodash": "^4.17.15", "react-beautiful-dnd": "^10.0.1", "react-markdown": "^4.0.6" - }, - "workspaces": { - "packages": [ - "packages/*" - ], - "nohoist": [ - "**/mochawesome", - "**/mochawesome/**", - "**/mocha-multi-reporters", - "**/mocha-multi-reporters/**" - ] } } diff --git a/x-pack/legacy/plugins/siem/public/apps/index.ts b/x-pack/legacy/plugins/siem/public/apps/index.ts index b71c4fe699860..73f9b65ba3546 100644 --- a/x-pack/legacy/plugins/siem/public/apps/index.ts +++ b/x-pack/legacy/plugins/siem/public/apps/index.ts @@ -8,8 +8,8 @@ import chrome from 'ui/chrome'; import { npStart } from 'ui/new_platform'; import { Plugin } from './plugin'; -// eslint-disable-next-line @typescript-eslint/no-explicit-any -new Plugin({ opaqueId: Symbol('siem'), env: {} as any }, chrome).start( - npStart.core, - npStart.plugins -); +new Plugin( + // eslint-disable-next-line @typescript-eslint/no-explicit-any + { opaqueId: Symbol('siem'), env: {} as any, config: { get: () => ({} as any) } }, + chrome +).start(npStart.core, npStart.plugins); diff --git a/x-pack/legacy/plugins/siem/public/components/autocomplete_field/index.tsx b/x-pack/legacy/plugins/siem/public/components/autocomplete_field/index.tsx index 408743d261797..124ef26602f35 100644 --- a/x-pack/legacy/plugins/siem/public/components/autocomplete_field/index.tsx +++ b/x-pack/legacy/plugins/siem/public/components/autocomplete_field/index.tsx @@ -307,7 +307,7 @@ const withUnfocused = (state: AutocompleteFieldState) => ({ isFocused: false, }); -export const FixedEuiFieldSearch: React.SFC & +export const FixedEuiFieldSearch: React.FC & EuiFieldSearchProps & { inputRef?: (element: HTMLInputElement | null) => void; onSearch: (value: string) => void; @@ -319,10 +319,10 @@ const AutocompleteContainer = euiStyled.div` AutocompleteContainer.displayName = 'AutocompleteContainer'; -const SuggestionsPanel = euiStyled(EuiPanel).attrs({ +const SuggestionsPanel = euiStyled(EuiPanel).attrs(() => ({ paddingSize: 'none', hasShadow: true, -})` +}))` position: absolute; width: 100%; margin-top: 2px; diff --git a/x-pack/legacy/plugins/siem/public/components/charts/areachart.tsx b/x-pack/legacy/plugins/siem/public/components/charts/areachart.tsx index 6347b93772b4e..d51f5e081468c 100644 --- a/x-pack/legacy/plugins/siem/public/components/charts/areachart.tsx +++ b/x-pack/legacy/plugins/siem/public/components/charts/areachart.tsx @@ -127,7 +127,7 @@ export const AreaChart = React.memo<{ return checkIfAnyValidSeriesExist(areaChart) ? ( {({ measureRef, content: { height, width } }) => ( - + {({ measureRef, content: { height, width } }) => ( - + { diff --git a/x-pack/legacy/plugins/siem/public/components/detection_engine/utility_bar/utility_bar.test.tsx b/x-pack/legacy/plugins/siem/public/components/detection_engine/utility_bar/utility_bar.test.tsx index bf13a503838cf..0ae247f5c9dd0 100644 --- a/x-pack/legacy/plugins/siem/public/components/detection_engine/utility_bar/utility_bar.test.tsx +++ b/x-pack/legacy/plugins/siem/public/components/detection_engine/utility_bar/utility_bar.test.tsx @@ -7,7 +7,6 @@ import euiDarkVars from '@elastic/eui/dist/eui_theme_dark.json'; import { mount, shallow } from 'enzyme'; import toJson from 'enzyme-to-json'; -import 'jest-styled-components'; import React from 'react'; import '../../../mock/ui_settings'; diff --git a/x-pack/legacy/plugins/siem/public/components/detection_engine/utility_bar/utility_bar_action.test.tsx b/x-pack/legacy/plugins/siem/public/components/detection_engine/utility_bar/utility_bar_action.test.tsx index 7a1c35183e503..74eed8cfabf2d 100644 --- a/x-pack/legacy/plugins/siem/public/components/detection_engine/utility_bar/utility_bar_action.test.tsx +++ b/x-pack/legacy/plugins/siem/public/components/detection_engine/utility_bar/utility_bar_action.test.tsx @@ -6,7 +6,6 @@ import { mount, shallow } from 'enzyme'; import toJson from 'enzyme-to-json'; -import 'jest-styled-components'; import React from 'react'; import '../../../mock/ui_settings'; diff --git a/x-pack/legacy/plugins/siem/public/components/drag_and_drop/draggable_wrapper.tsx b/x-pack/legacy/plugins/siem/public/components/drag_and_drop/draggable_wrapper.tsx index 35d54414944f4..0f0e61e0206ec 100644 --- a/x-pack/legacy/plugins/siem/public/components/drag_and_drop/draggable_wrapper.tsx +++ b/x-pack/legacy/plugins/siem/public/components/drag_and_drop/draggable_wrapper.tsx @@ -39,31 +39,43 @@ const Wrapper = styled.div` Wrapper.displayName = 'Wrapper'; const ProviderContainer = styled.div<{ isDragging: boolean }>` - ${({ theme, isDragging }) => css` - &, - &::before, - &::after { - transition: background ${theme.eui.euiAnimSpeedFast} ease, - color ${theme.eui.euiAnimSpeedFast} ease; - } - - ${!isDragging && - ` + &, + &::before, + &::after { + transition: background ${({ theme }) => theme.eui.euiAnimSpeedFast} ease, + color ${({ theme }) => theme.eui.euiAnimSpeedFast} ease; + } + + ${({ isDragging }) => + !isDragging && + css` & { border-radius: 2px; padding: 0 4px 0 8px; position: relative; - z-index: ${theme.eui.euiZLevel0} !important; + z-index: ${({ theme }) => theme.eui.euiZLevel0} !important; &::before { background-image: linear-gradient( 135deg, - ${theme.eui.euiColorMediumShade} 25%, + ${({ theme }) => theme.eui.euiColorMediumShade} 25%, + transparent 25% + ), + linear-gradient( + -135deg, + ${({ theme }) => theme.eui.euiColorMediumShade} 25%, transparent 25% ), - linear-gradient(-135deg, ${theme.eui.euiColorMediumShade} 25%, transparent 25%), - linear-gradient(135deg, transparent 75%, ${theme.eui.euiColorMediumShade} 75%), - linear-gradient(-135deg, transparent 75%, ${theme.eui.euiColorMediumShade} 75%); + linear-gradient( + 135deg, + transparent 75%, + ${({ theme }) => theme.eui.euiColorMediumShade} 75% + ), + linear-gradient( + -135deg, + transparent 75%, + ${({ theme }) => theme.eui.euiColorMediumShade} 75% + ); background-position: 0 0, 1px 0, 1px -1px, 0px 1px; background-size: 2px 2px; bottom: 2px; @@ -87,17 +99,29 @@ const ProviderContainer = styled.div<{ isDragging: boolean }>` .${STATEFUL_EVENT_CSS_CLASS_NAME}:hover &, tr:hover & { - background-color: ${theme.eui.euiColorLightShade}; + background-color: ${({ theme }) => theme.eui.euiColorLightShade}; &::before { background-image: linear-gradient( 135deg, - ${theme.eui.euiColorDarkShade} 25%, + ${({ theme }) => theme.eui.euiColorDarkShade} 25%, + transparent 25% + ), + linear-gradient( + -135deg, + ${({ theme }) => theme.eui.euiColorDarkShade} 25%, transparent 25% ), - linear-gradient(-135deg, ${theme.eui.euiColorDarkShade} 25%, transparent 25%), - linear-gradient(135deg, transparent 75%, ${theme.eui.euiColorDarkShade} 75%), - linear-gradient(-135deg, transparent 75%, ${theme.eui.euiColorDarkShade} 75%); + linear-gradient( + 135deg, + transparent 75%, + ${({ theme }) => theme.eui.euiColorDarkShade} 75% + ), + linear-gradient( + -135deg, + transparent 75%, + ${({ theme }) => theme.eui.euiColorDarkShade} 75% + ); } } @@ -107,34 +131,46 @@ const ProviderContainer = styled.div<{ isDragging: boolean }>` .${STATEFUL_EVENT_CSS_CLASS_NAME}:focus &:focus, tr:hover &:hover, tr:hover &:focus { - background-color: ${theme.eui.euiColorPrimary}; + background-color: ${({ theme }) => theme.eui.euiColorPrimary}; &, & a, & a:hover { - color: ${theme.eui.euiColorEmptyShade}; + color: ${({ theme }) => theme.eui.euiColorEmptyShade}; } &::before { background-image: linear-gradient( 135deg, - ${theme.eui.euiColorEmptyShade} 25%, + ${({ theme }) => theme.eui.euiColorEmptyShade} 25%, transparent 25% ), - linear-gradient(-135deg, ${theme.eui.euiColorEmptyShade} 25%, transparent 25%), - linear-gradient(135deg, transparent 75%, ${theme.eui.euiColorEmptyShade} 75%), - linear-gradient(-135deg, transparent 75%, ${theme.eui.euiColorEmptyShade} 75%); + linear-gradient( + -135deg, + ${({ theme }) => theme.eui.euiColorEmptyShade} 25%, + transparent 25% + ), + linear-gradient( + 135deg, + transparent 75%, + ${({ theme }) => theme.eui.euiColorEmptyShade} 75% + ), + linear-gradient( + -135deg, + transparent 75%, + ${({ theme }) => theme.eui.euiColorEmptyShade} 75% + ); } } `} - ${isDragging && - ` + ${({ isDragging }) => + isDragging && + css` & { z-index: 9999 !important; } `} - `} `; ProviderContainer.displayName = 'ProviderContainer'; @@ -192,7 +228,7 @@ const DraggableWrapperComponent = React.memo( ( {(provided, snapshot) => ( diff --git a/x-pack/legacy/plugins/siem/public/components/draggables/field_badge/index.tsx b/x-pack/legacy/plugins/siem/public/components/draggables/field_badge/index.tsx index faf65338b4337..5bff59494b9ad 100644 --- a/x-pack/legacy/plugins/siem/public/components/draggables/field_badge/index.tsx +++ b/x-pack/legacy/plugins/siem/public/components/draggables/field_badge/index.tsx @@ -7,19 +7,17 @@ import { rgba } from 'polished'; import * as React from 'react'; import { pure } from 'recompose'; -import styled, { css } from 'styled-components'; +import styled from 'styled-components'; const Field = styled.div` - ${({ theme }) => css` - background-color: ${theme.eui.euiColorEmptyShade}; - border: ${theme.eui.euiBorderThin}; - box-shadow: 0 2px 2px -1px ${rgba(theme.eui.euiColorMediumShade, 0.3)}, - 0 1px 5px -2px ${rgba(theme.eui.euiColorMediumShade, 0.3)}; - font-size: ${theme.eui.euiFontSizeXS}; - font-weight: ${theme.eui.euiFontWeightSemiBold}; - line-height: ${theme.eui.euiLineHeight}; - padding: ${theme.eui.paddingSizes.xs}; - `} + background-color: ${({ theme }) => theme.eui.euiColorEmptyShade}; + border: ${({ theme }) => theme.eui.euiBorderThin}; + box-shadow: 0 2px 2px -1px ${({ theme }) => rgba(theme.eui.euiColorMediumShade, 0.3)}, + 0 1px 5px -2px ${({ theme }) => rgba(theme.eui.euiColorMediumShade, 0.3)}; + font-size: ${({ theme }) => theme.eui.euiFontSizeXS}; + font-weight: ${({ theme }) => theme.eui.euiFontWeightSemiBold}; + line-height: ${({ theme }) => theme.eui.euiLineHeight}; + padding: ${({ theme }) => theme.eui.paddingSizes.xs}; `; Field.displayName = 'Field'; diff --git a/x-pack/legacy/plugins/siem/public/components/edit_data_provider/index.tsx b/x-pack/legacy/plugins/siem/public/components/edit_data_provider/index.tsx index ec6646fc76085..214ac926e8868 100644 --- a/x-pack/legacy/plugins/siem/public/components/edit_data_provider/index.tsx +++ b/x-pack/legacy/plugins/siem/public/components/edit_data_provider/index.tsx @@ -18,7 +18,7 @@ import { EuiToolTip, } from '@elastic/eui'; import React, { useEffect, useState, useCallback } from 'react'; -import styled, { injectGlobal } from 'styled-components'; +import styled, { createGlobalStyle } from 'styled-components'; import { BrowserFields } from '../../containers/source'; import { OnDataProviderEdited } from '../timeline/events'; @@ -46,11 +46,11 @@ export const HeaderContainer = styled.div` HeaderContainer.displayName = 'HeaderContainer'; -// SIDE EFFECT: the following `injectGlobal` overrides the default styling +// SIDE EFFECT: the following `createGlobalStyle` overrides the default styling // of euiComboBoxOptionsList because it's implemented as a popover, so it's // not selectable as a child of the styled component // eslint-disable-next-line no-unused-expressions -injectGlobal` +createGlobalStyle` .euiComboBoxOptionsList { z-index: 9999; } diff --git a/x-pack/legacy/plugins/siem/public/components/embeddables/embeddable_header.tsx b/x-pack/legacy/plugins/siem/public/components/embeddables/embeddable_header.tsx index dbd9e3f763f92..f2abfdf307fa3 100644 --- a/x-pack/legacy/plugins/siem/public/components/embeddables/embeddable_header.tsx +++ b/x-pack/legacy/plugins/siem/public/components/embeddables/embeddable_header.tsx @@ -6,15 +6,13 @@ import { EuiFlexGroup, EuiFlexItem, EuiTitle } from '@elastic/eui'; import React from 'react'; -import styled, { css } from 'styled-components'; +import styled from 'styled-components'; -const Header = styled.header.attrs({ - className: 'siemEmbeddable__header', -})` - ${({ theme }) => css` - border-bottom: ${theme.eui.euiBorderThin}; - padding: ${theme.eui.paddingSizes.m}; - `} +const Header = styled.header.attrs(({ className }) => ({ + className: `siemEmbeddable__header ${className}`, +}))` + border-bottom: ${({ theme }) => theme.eui.euiBorderThin}; + padding: ${({ theme }) => theme.eui.paddingSizes.m}; `; Header.displayName = 'Header'; diff --git a/x-pack/legacy/plugins/siem/public/components/embeddables/embedded_map.tsx b/x-pack/legacy/plugins/siem/public/components/embeddables/embedded_map.tsx index 794e26b417012..fa3b95a2c805b 100644 --- a/x-pack/legacy/plugins/siem/public/components/embeddables/embedded_map.tsx +++ b/x-pack/legacy/plugins/siem/public/components/embeddables/embedded_map.tsx @@ -34,41 +34,40 @@ interface EmbeddableMapProps { maintainRatio?: boolean; } -const EmbeddableMap = styled.div.attrs({ +const EmbeddableMap = styled.div.attrs(() => ({ className: 'siemEmbeddable__map', -})` - ${({ maintainRatio, theme }) => css` - .embPanel { - border: none; - box-shadow: none; - } - - .mapToolbarOverlay__button { - display: none; - } - - ${maintainRatio && - css` - padding-top: calc(3 / 4 * 100%); //4:3 (standard) ratio - position: relative; - - @media only screen and (min-width: ${theme.eui.euiBreakpoints.m}) { - padding-top: calc(9 / 32 * 100%); //32:9 (ultra widescreen) ratio - } +}))` + .embPanel { + border: none; + box-shadow: none; + } - @media only screen and (min-width: 1441px) and (min-height: 901px) { - padding-top: calc(9 / 21 * 100%); //21:9 (ultrawide) ratio - } + .mapToolbarOverlay__button { + display: none; + } - .embPanel { - bottom: 0; - left: 0; - position: absolute; - right: 0; - top: 0; - } - `} - `} + ${({ maintainRatio }) => + maintainRatio && + css` + padding-top: calc(3 / 4 * 100%); //4:3 (standard) ratio + position: relative; + + @media only screen and (min-width: ${({ theme }) => theme.eui.euiBreakpoints.m}) { + padding-top: calc(9 / 32 * 100%); //32:9 (ultra widescreen) ratio + } + + @media only screen and (min-width: 1441px) and (min-height: 901px) { + padding-top: calc(9 / 21 * 100%); //21:9 (ultrawide) ratio + } + + .embPanel { + bottom: 0; + left: 0; + position: absolute; + right: 0; + top: 0; + } + `} `; EmbeddableMap.displayName = 'EmbeddableMap'; diff --git a/x-pack/legacy/plugins/siem/public/components/embeddables/embedded_map_helpers.test.tsx b/x-pack/legacy/plugins/siem/public/components/embeddables/embedded_map_helpers.test.tsx index 2ad38bae3ccef..a2c3e2cc288d7 100644 --- a/x-pack/legacy/plugins/siem/public/components/embeddables/embedded_map_helpers.test.tsx +++ b/x-pack/legacy/plugins/siem/public/components/embeddables/embedded_map_helpers.test.tsx @@ -14,6 +14,7 @@ jest.mock('../../lib/settings/use_kibana_ui_setting'); jest.mock('uuid', () => { return { + v1: jest.fn(() => '27261ae0-0bbb-11ea-b0ea-db767b07ea47'), v4: jest.fn(() => '9e1f72a9-7c73-4b7f-a562-09940f7daf4a'), }; }); diff --git a/x-pack/legacy/plugins/siem/public/components/events_viewer/events_viewer.tsx b/x-pack/legacy/plugins/siem/public/components/events_viewer/events_viewer.tsx index c5c0fe3503561..c868b7950289a 100644 --- a/x-pack/legacy/plugins/siem/public/components/events_viewer/events_viewer.tsx +++ b/x-pack/legacy/plugins/siem/public/components/events_viewer/events_viewer.tsx @@ -100,7 +100,7 @@ export const EventsViewer = React.memo( {({ measureRef, content: { width = 0 } }) => ( <> - +

` - ${({ theme, width }) => css` - background-color: ${theme.eui.euiColorLightestShade}; - border: ${theme.eui.euiBorderWidthThin} solid ${theme.eui.euiColorMediumShade}; - border-radius: ${theme.eui.euiBorderRadius}; - left: 0; - padding: ${theme.eui.paddingSizes.s} ${theme.eui.paddingSizes.s} ${theme.eui.paddingSizes.m}; - position: absolute; - top: calc(100% + ${theme.eui.euiSize}); - width: ${width}px; - z-index: 9990; - `} + background-color: ${({ theme }) => theme.eui.euiColorLightestShade}; + border: ${({ theme }) => theme.eui.euiBorderWidthThin} solid + ${({ theme }) => theme.eui.euiColorMediumShade}; + border-radius: ${({ theme }) => theme.eui.euiBorderRadius}; + left: 0; + padding: ${({ theme }) => theme.eui.paddingSizes.s} ${({ theme }) => theme.eui.paddingSizes.s} + ${({ theme }) => theme.eui.paddingSizes.m}; + position: absolute; + top: calc(100% + ${({ theme }) => theme.eui.euiSize}); + width: ${({ width }) => width}px; + z-index: 9990; `; FieldsBrowserContainer.displayName = 'FieldsBrowserContainer'; diff --git a/x-pack/legacy/plugins/siem/public/components/fields_browser/field_name.tsx b/x-pack/legacy/plugins/siem/public/components/fields_browser/field_name.tsx index 9c2cf2cb0e0b2..d5d8c54775566 100644 --- a/x-pack/legacy/plugins/siem/public/components/fields_browser/field_name.tsx +++ b/x-pack/legacy/plugins/siem/public/components/fields_browser/field_name.tsx @@ -16,7 +16,7 @@ import { EuiToolTip, } from '@elastic/eui'; import React, { useContext } from 'react'; -import styled, { css } from 'styled-components'; +import styled from 'styled-components'; import { WithCopyToClipboard } from '../../lib/clipboard/with_copy_to_clipboard'; import { ColumnHeader } from '../timeline/body/column_headers/column_header'; @@ -30,51 +30,55 @@ import * as i18n from './translations'; * The name of a (draggable) field */ export const FieldNameContainer = styled.span` - ${({ theme }) => css` - padding: 5px; - { - border-radius: 4px; - padding: 0 4px 0 8px; - position: relative; + padding: 5px; + { + border-radius: 4px; + padding: 0 4px 0 8px; + position: relative; + + &::before { + background-image: linear-gradient( + 135deg, + ${({ theme }) => theme.eui.euiColorMediumShade} 25%, + transparent 25% + ), + linear-gradient(-135deg, ${({ theme }) => + theme.eui.euiColorMediumShade} 25%, transparent 25%), + linear-gradient(135deg, transparent 75%, ${({ theme }) => + theme.eui.euiColorMediumShade} 75%), + linear-gradient(-135deg, transparent 75%, ${({ theme }) => + theme.eui.euiColorMediumShade} 75%); + background-position: 0 0, 1px 0, 1px -1px, 0px 1px; + background-size: 2px 2px; + bottom: 2px; + content: ''; + display: block; + left: 2px; + position: absolute; + top: 2px; + width: 4px; + } + + &:hover, + &:focus { + transition: background-color 0.7s ease; + background-color: #000; + color: #fff; &::before { background-image: linear-gradient( 135deg, - ${theme.eui.euiColorMediumShade} 25%, + #fff 25%, transparent 25% ), - linear-gradient(-135deg, ${theme.eui.euiColorMediumShade} 25%, transparent 25%), - linear-gradient(135deg, transparent 75%, ${theme.eui.euiColorMediumShade} 75%), - linear-gradient(-135deg, transparent 75%, ${theme.eui.euiColorMediumShade} 75%); - background-position: 0 0, 1px 0, 1px -1px, 0px 1px; - background-size: 2px 2px; - bottom: 2px; - content: ''; - display: block; - left: 2px; - position: absolute; - top: 2px; - width: 4px; + linear-gradient(-135deg, ${({ theme }) => + theme.eui.euiColorLightestShade} 25%, transparent 25%), + linear-gradient(135deg, transparent 75%, ${({ theme }) => + theme.eui.euiColorLightestShade} 75%), + linear-gradient(-135deg, transparent 75%, ${({ theme }) => + theme.eui.euiColorLightestShade} 75%); } - - &:hover, - &:focus { - transition: background-color 0.7s ease; - background-color: #000; - color: #fff; - - &::before { - background-image: linear-gradient( - 135deg, - #fff 25%, - transparent 25% - ), - linear-gradient(-135deg, ${theme.eui.euiColorLightestShade} 25%, transparent 25%), - linear-gradient(135deg, transparent 75%, ${theme.eui.euiColorLightestShade} 75%), - linear-gradient(-135deg, transparent 75%, ${theme.eui.euiColorLightestShade} 75%); - } - } - `} + } `; FieldNameContainer.displayName = 'FieldNameContainer'; diff --git a/x-pack/legacy/plugins/siem/public/components/fields_browser/index.test.tsx b/x-pack/legacy/plugins/siem/public/components/fields_browser/index.test.tsx index 8948f765b8fbc..e943ca6f3e863 100644 --- a/x-pack/legacy/plugins/siem/public/components/fields_browser/index.test.tsx +++ b/x-pack/legacy/plugins/siem/public/components/fields_browser/index.test.tsx @@ -6,7 +6,6 @@ import { mount } from 'enzyme'; import * as React from 'react'; -import 'jest-styled-components'; import { mockBrowserFields } from '../../containers/source/mock'; import { TestProviders } from '../../mock'; diff --git a/x-pack/legacy/plugins/siem/public/components/filters_global/filters_global.tsx b/x-pack/legacy/plugins/siem/public/components/filters_global/filters_global.tsx index 892c160d054bd..bdda8497a8bcb 100644 --- a/x-pack/legacy/plugins/siem/public/components/filters_global/filters_global.tsx +++ b/x-pack/legacy/plugins/siem/public/components/filters_global/filters_global.tsx @@ -18,25 +18,23 @@ const disableSticky = 'screen and (max-width: ' + euiLightVars.euiBreakpoints.s const disableStickyMq = window.matchMedia(disableSticky); const Wrapper = styled.aside<{ isSticky?: boolean }>` - ${props => css` - position: relative; - z-index: ${props.theme.eui.euiZNavigation}; - background: ${props.theme.eui.euiColorEmptyShade}; - border-bottom: ${props.theme.eui.euiBorderThin}; - padding: ${props.theme.eui.paddingSizes.m} ${gutterTimeline} ${ - props.theme.eui.paddingSizes.m - } ${props.theme.eui.paddingSizes.l}; - - ${props.isSticky && - ` + position: relative; + z-index: ${({ theme }) => theme.eui.euiZNavigation}; + background: ${({ theme }) => theme.eui.euiColorEmptyShade}; + border-bottom: ${({ theme }) => theme.eui.euiBorderThin}; + padding: ${({ theme }) => theme.eui.paddingSizes.m} ${gutterTimeline} ${({ theme }) => + theme.eui.paddingSizes.m} ${({ theme }) => theme.eui.paddingSizes.l}; + + ${({ isSticky }) => + isSticky && + css` top: ${offsetChrome}px !important; `} - @media only ${disableSticky} { - position: static !important; - z-index: ${props.theme.eui.euiZContent} !important; - } - `} + @media only ${disableSticky} { + position: static !important; + z-index: ${({ theme }) => theme.eui.euiZContent} !important; + } `; Wrapper.displayName = 'Wrapper'; diff --git a/x-pack/legacy/plugins/siem/public/components/flyout/pane/index.test.tsx b/x-pack/legacy/plugins/siem/public/components/flyout/pane/index.test.tsx index 4b7b935b1f536..65233e55901ff 100644 --- a/x-pack/legacy/plugins/siem/public/components/flyout/pane/index.test.tsx +++ b/x-pack/legacy/plugins/siem/public/components/flyout/pane/index.test.tsx @@ -6,7 +6,6 @@ import { mount, shallow } from 'enzyme'; import toJson from 'enzyme-to-json'; -import 'jest-styled-components'; import * as React from 'react'; import { flyoutHeaderHeight } from '../'; diff --git a/x-pack/legacy/plugins/siem/public/components/header_page/index.test.tsx b/x-pack/legacy/plugins/siem/public/components/header_page/index.test.tsx index ae33b63e93d39..9c50a915b7ba8 100644 --- a/x-pack/legacy/plugins/siem/public/components/header_page/index.test.tsx +++ b/x-pack/legacy/plugins/siem/public/components/header_page/index.test.tsx @@ -7,7 +7,6 @@ import euiDarkVars from '@elastic/eui/dist/eui_theme_dark.json'; import { mount, shallow } from 'enzyme'; import toJson from 'enzyme-to-json'; -import 'jest-styled-components'; import React from 'react'; import { TestProviders } from '../../mock'; diff --git a/x-pack/legacy/plugins/siem/public/components/header_section/index.test.tsx b/x-pack/legacy/plugins/siem/public/components/header_section/index.test.tsx index fffeece818d13..4a6da9c80968f 100644 --- a/x-pack/legacy/plugins/siem/public/components/header_section/index.test.tsx +++ b/x-pack/legacy/plugins/siem/public/components/header_section/index.test.tsx @@ -7,7 +7,6 @@ import euiDarkVars from '@elastic/eui/dist/eui_theme_dark.json'; import { mount, shallow } from 'enzyme'; import toJson from 'enzyme-to-json'; -import 'jest-styled-components'; import React from 'react'; import { TestProviders } from '../../mock'; diff --git a/x-pack/legacy/plugins/siem/public/components/header_section/index.tsx b/x-pack/legacy/plugins/siem/public/components/header_section/index.tsx index e46ae55a57a45..14af10eb6cd9b 100644 --- a/x-pack/legacy/plugins/siem/public/components/header_section/index.tsx +++ b/x-pack/legacy/plugins/siem/public/components/header_section/index.tsx @@ -15,19 +15,18 @@ interface HeaderProps { border?: boolean; } -const Header = styled.header.attrs({ +const Header = styled.header.attrs(() => ({ className: 'siemHeaderSection', -})` - ${({ border, theme }) => css` - margin-bottom: ${theme.eui.euiSizeL}; - user-select: text; +}))` + margin-bottom: ${({ theme }) => theme.eui.euiSizeL}; + user-select: text; - ${border && - css` - border-bottom: ${theme.eui.euiBorderThin}; - padding-bottom: ${theme.eui.paddingSizes.l}; - `} - `} + ${({ border }) => + border && + css` + border-bottom: ${({ theme }) => theme.eui.euiBorderThin}; + padding-bottom: ${({ theme }) => theme.eui.paddingSizes.l}; + `} `; Header.displayName = 'Header'; diff --git a/x-pack/legacy/plugins/siem/public/components/help_menu/help_menu.tsx b/x-pack/legacy/plugins/siem/public/components/help_menu/help_menu.tsx deleted file mode 100644 index b59753e8add6a..0000000000000 --- a/x-pack/legacy/plugins/siem/public/components/help_menu/help_menu.tsx +++ /dev/null @@ -1,43 +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 { EuiButton, EuiHorizontalRule, EuiIcon, EuiTitle, EuiSpacer } from '@elastic/eui'; -import { FormattedMessage } from '@kbn/i18n/react'; -import theme from '@elastic/eui/dist/eui_theme_light.json'; -import styled from 'styled-components'; - -export const Icon = styled(EuiIcon)` - margin-right: ${theme.euiSizeS}; -`; - -Icon.displayName = 'Icon'; - -export const HelpMenuComponent = React.memo(() => ( - <> - - - - - -
- - -
-
- - - - - - - -)); - -HelpMenuComponent.displayName = 'HelpMenuComponent'; diff --git a/x-pack/legacy/plugins/siem/public/components/help_menu/index.tsx b/x-pack/legacy/plugins/siem/public/components/help_menu/index.tsx index d145769319d5b..43fd8e653f3d8 100644 --- a/x-pack/legacy/plugins/siem/public/components/help_menu/index.tsx +++ b/x-pack/legacy/plugins/siem/public/components/help_menu/index.tsx @@ -4,20 +4,23 @@ * you may not use this file except in compliance with the Elastic License. */ -import { render, unmountComponentAtNode } from 'react-dom'; -import React, { useEffect } from 'react'; +import { useEffect } from 'react'; import { pure } from 'recompose'; import chrome from 'ui/chrome'; - -import { HelpMenuComponent } from './help_menu'; +import { i18n } from '@kbn/i18n'; export const HelpMenu = pure<{}>(() => { useEffect(() => { - chrome.helpExtension.set(domNode => { - render(, domNode); - return () => { - unmountComponentAtNode(domNode); - }; + chrome.helpExtension.set({ + appName: i18n.translate('xpack.siem.chrome.help.appName', { + defaultMessage: 'SIEM', + }), + links: [ + { + linkType: 'discuss', + href: 'https://discuss.elastic.co/c/siem', + }, + ], }); }, []); diff --git a/x-pack/legacy/plugins/siem/public/components/link_icon/index.test.tsx b/x-pack/legacy/plugins/siem/public/components/link_icon/index.test.tsx index 8e4387f35056e..451db49028ee1 100644 --- a/x-pack/legacy/plugins/siem/public/components/link_icon/index.test.tsx +++ b/x-pack/legacy/plugins/siem/public/components/link_icon/index.test.tsx @@ -6,7 +6,6 @@ import { mount, shallow } from 'enzyme'; import toJson from 'enzyme-to-json'; -import 'jest-styled-components'; import React from 'react'; import { TestProviders } from '../../mock'; diff --git a/x-pack/legacy/plugins/siem/public/components/loader/index.tsx b/x-pack/legacy/plugins/siem/public/components/loader/index.tsx index 988fa4a677d7a..55628fe2e8d33 100644 --- a/x-pack/legacy/plugins/siem/public/components/loader/index.tsx +++ b/x-pack/legacy/plugins/siem/public/components/loader/index.tsx @@ -18,14 +18,14 @@ import { pure } from 'recompose'; import styled, { css } from 'styled-components'; const Aside = styled.aside<{ overlay?: boolean; overlayBackground?: string }>` - ${({ overlay, overlayBackground, theme }) => css` - padding: ${theme.eui.paddingSizes.m}; + padding: ${({ theme }) => theme.eui.paddingSizes.m}; - ${overlay && - ` - background: ${ - overlayBackground ? rgba(overlayBackground, 0.9) : rgba(theme.eui.euiColorEmptyShade, 0.9) - }; + ${({ overlay, overlayBackground, theme }) => + overlay && + css` + background: ${overlayBackground + ? rgba(overlayBackground, 0.9) + : rgba(theme.eui.euiColorEmptyShade, 0.9)}; bottom: 0; left: 0; position: absolute; @@ -33,22 +33,21 @@ const Aside = styled.aside<{ overlay?: boolean; overlayBackground?: string }>` top: 0; z-index: ${theme.eui.euiZLevel1}; `} - `} `; Aside.displayName = 'Aside'; -const FlexGroup = styled(EuiFlexGroup).attrs({ +const FlexGroup = styled(EuiFlexGroup).attrs(() => ({ alignItems: 'center', direction: 'column', gutterSize: 's', justifyContent: 'center', -})<{ overlay: { overlay?: boolean } }>` +}))<{ overlay: { overlay?: boolean } }>` ${({ overlay }) => overlay && - ` - height: 100%; - `} + css` + height: 100%; + `} `; FlexGroup.displayName = 'FlexGroup'; diff --git a/x-pack/legacy/plugins/siem/public/components/loading/index.tsx b/x-pack/legacy/plugins/siem/public/components/loading/index.tsx index 5b9cb48789739..eb85edce78a8f 100644 --- a/x-pack/legacy/plugins/siem/public/components/loading/index.tsx +++ b/x-pack/legacy/plugins/siem/public/components/loading/index.tsx @@ -7,11 +7,11 @@ import { EuiFlexGroup, EuiFlexItem, EuiLoadingSpinner, EuiPanel, EuiText } from '@elastic/eui'; import * as React from 'react'; import { pure } from 'recompose'; -import styled, { injectGlobal } from 'styled-components'; +import styled, { createGlobalStyle } from 'styled-components'; -// SIDE EFFECT: the following `injectGlobal` overrides default styling in angular code that was not theme-friendly +// SIDE EFFECT: the following `createGlobalStyle` overrides default styling in angular code that was not theme-friendly // eslint-disable-next-line no-unused-expressions -injectGlobal` +createGlobalStyle` .euiPanel-loading-hide-border { border: none; } diff --git a/x-pack/legacy/plugins/siem/public/components/markdown/markdown_hint.test.tsx b/x-pack/legacy/plugins/siem/public/components/markdown/markdown_hint.test.tsx index a1d12f0d4e29e..6319af3e6ffa1 100644 --- a/x-pack/legacy/plugins/siem/public/components/markdown/markdown_hint.test.tsx +++ b/x-pack/legacy/plugins/siem/public/components/markdown/markdown_hint.test.tsx @@ -6,7 +6,6 @@ import { mount, shallow } from 'enzyme'; import toJson from 'enzyme-to-json'; -import 'jest-styled-components'; import * as React from 'react'; import { MarkdownHint } from './markdown_hint'; diff --git a/x-pack/legacy/plugins/siem/public/components/ml/score/__snapshots__/anomaly_score.test.tsx.snap b/x-pack/legacy/plugins/siem/public/components/ml/score/__snapshots__/anomaly_score.test.tsx.snap index 8760dce2b76df..9813456e41638 100644 --- a/x-pack/legacy/plugins/siem/public/components/ml/score/__snapshots__/anomaly_score.test.tsx.snap +++ b/x-pack/legacy/plugins/siem/public/components/ml/score/__snapshots__/anomaly_score.test.tsx.snap @@ -82,7 +82,7 @@ exports[`anomaly_scores renders correctly against snapshot 1`] = ` } @@ -105,9 +105,9 @@ exports[`anomaly_scores renders correctly against snapshot 1`] = ` - + 17 - + , "title": "Max Anomaly Score", }, diff --git a/x-pack/legacy/plugins/siem/public/components/notes/add_note/index.test.tsx b/x-pack/legacy/plugins/siem/public/components/notes/add_note/index.test.tsx index a764727e8af26..fc76780ef80c7 100644 --- a/x-pack/legacy/plugins/siem/public/components/notes/add_note/index.test.tsx +++ b/x-pack/legacy/plugins/siem/public/components/notes/add_note/index.test.tsx @@ -6,7 +6,6 @@ import { mount, shallow } from 'enzyme'; import toJson from 'enzyme-to-json'; -import 'jest-styled-components'; import * as React from 'react'; import { AddNote } from '.'; diff --git a/x-pack/legacy/plugins/siem/public/components/notes/note_card/__snapshots__/note_card_body.test.tsx.snap b/x-pack/legacy/plugins/siem/public/components/notes/note_card/__snapshots__/note_card_body.test.tsx.snap index 7a8232357d3e1..7e4b6babae449 100644 --- a/x-pack/legacy/plugins/siem/public/components/notes/note_card/__snapshots__/note_card_body.test.tsx.snap +++ b/x-pack/legacy/plugins/siem/public/components/notes/note_card/__snapshots__/note_card_body.test.tsx.snap @@ -1,7 +1,493 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP exports[`NoteCardBody renders correctly against snapshot 1`] = ` - + + + `; diff --git a/x-pack/legacy/plugins/siem/public/components/open_timeline/timelines_table/icon_header_columns.test.tsx b/x-pack/legacy/plugins/siem/public/components/open_timeline/timelines_table/icon_header_columns.test.tsx index 26dc0ca455f73..e5047662eef67 100644 --- a/x-pack/legacy/plugins/siem/public/components/open_timeline/timelines_table/icon_header_columns.test.tsx +++ b/x-pack/legacy/plugins/siem/public/components/open_timeline/timelines_table/icon_header_columns.test.tsx @@ -7,7 +7,6 @@ import euiDarkVars from '@elastic/eui/dist/eui_theme_dark.json'; import { cloneDeep, omit } from 'lodash/fp'; import { mountWithIntl } from 'test_utils/enzyme_helpers'; -import 'jest-styled-components'; import * as React from 'react'; import { ThemeProvider } from 'styled-components'; diff --git a/x-pack/legacy/plugins/siem/public/components/page/index.tsx b/x-pack/legacy/plugins/siem/public/components/page/index.tsx index d211d1513767d..bc701006c3a9c 100644 --- a/x-pack/legacy/plugins/siem/public/components/page/index.tsx +++ b/x-pack/legacy/plugins/siem/public/components/page/index.tsx @@ -13,11 +13,11 @@ import { EuiIcon, EuiPage, } from '@elastic/eui'; -import styled, { injectGlobal } from 'styled-components'; +import styled, { createGlobalStyle } from 'styled-components'; -// SIDE EFFECT: the following `injectGlobal` overrides default styling in angular code that was not theme-friendly +// SIDE EFFECT: the following `createGlobalStyle` overrides default styling in angular code that was not theme-friendly // eslint-disable-next-line no-unused-expressions -injectGlobal` +createGlobalStyle` div.app-wrapper { background-color: rgba(0,0,0,0); } diff --git a/x-pack/legacy/plugins/siem/public/components/paginated_table/__snapshots__/index.test.tsx.snap b/x-pack/legacy/plugins/siem/public/components/paginated_table/__snapshots__/index.test.tsx.snap index 14c5538843ef5..e000eeb14214e 100644 --- a/x-pack/legacy/plugins/siem/public/components/paginated_table/__snapshots__/index.test.tsx.snap +++ b/x-pack/legacy/plugins/siem/public/components/paginated_table/__snapshots__/index.test.tsx.snap @@ -1,107 +1,593 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP exports[`Paginated Table Component rendering it renders the default load more table 1`] = ` - - My test supplement. -

- } - headerTitle="Hosts" - headerTooltip="My test tooltip" - headerUnit="Test Unit" - itemsPerRow={ - Array [ - Object { - "numberOfRow": 2, - "text": "2 rows", - }, - Object { - "numberOfRow": 5, - "text": "5 rows", - }, - Object { - "numberOfRow": 10, - "text": "10 rows", - }, - Object { - "numberOfRow": 20, - "text": "20 rows", - }, - Object { - "numberOfRow": 50, - "text": "50 rows", - }, - ] - } - limit={1} - loadPage={[Function]} - loading={false} - pageOfItems={ - Array [ - Object { - "cursor": Object { - "value": "98966fa2013c396155c460d35c0902be", - }, - "host": Object { - "_id": "cPsuhGcB0WOhS6qyTKC0", - "firstSeen": "2018-12-06T15:40:53.319Z", - "name": "elrond.elstc.co", - "os": "Ubuntu", - "version": "18.04.1 LTS (Bionic Beaver)", + +> + + My test supplement. +

+ } + headerTitle="Hosts" + headerTooltip="My test tooltip" + headerUnit="Test Unit" + itemsPerRow={ + Array [ + Object { + "numberOfRow": 2, + "text": "2 rows", + }, + Object { + "numberOfRow": 5, + "text": "5 rows", + }, + Object { + "numberOfRow": 10, + "text": "10 rows", + }, + Object { + "numberOfRow": 20, + "text": "20 rows", + }, + Object { + "numberOfRow": 50, + "text": "50 rows", + }, + ] + } + limit={1} + loadPage={[Function]} + loading={false} + pageOfItems={ + Array [ + Object { + "cursor": Object { + "value": "98966fa2013c396155c460d35c0902be", + }, + "host": Object { + "_id": "cPsuhGcB0WOhS6qyTKC0", + "firstSeen": "2018-12-06T15:40:53.319Z", + "name": "elrond.elstc.co", + "os": "Ubuntu", + "version": "18.04.1 LTS (Bionic Beaver)", + }, + }, + Object { + "cursor": Object { + "value": "aa7ca589f1b8220002f2fc61c64cfbf1", + }, + "host": Object { + "_id": "KwQDiWcB0WOhS6qyXmrW", + "firstSeen": "2018-12-07T14:12:38.560Z", + "name": "siem-kibana", + "os": "Debian GNU/Linux", + "version": "9 (stretch)", + }, + }, + ] + } + showMorePagesIndicator={true} + totalCount={10} + updateActivePage={[Function]} + updateLimitPagination={[Function]} + /> +
`; diff --git a/x-pack/legacy/plugins/siem/public/components/paginated_table/index.tsx b/x-pack/legacy/plugins/siem/public/components/paginated_table/index.tsx index 7be0c1885811b..aedec1a340bfd 100644 --- a/x-pack/legacy/plugins/siem/public/components/paginated_table/index.tsx +++ b/x-pack/legacy/plugins/siem/public/components/paginated_table/index.tsx @@ -17,7 +17,7 @@ import { } from '@elastic/eui'; import { noop } from 'lodash/fp'; import React, { memo, useState, useEffect } from 'react'; -import styled, { css } from 'styled-components'; +import styled from 'styled-components'; import { Direction } from '../../graphql/types'; import { AuthTableColumns } from '../page/hosts/authentications_table'; @@ -319,37 +319,35 @@ const BasicTable = styled(EuiBasicTable)` BasicTable.displayName = 'BasicTable'; -const FooterAction = styled(EuiFlexGroup).attrs({ +const FooterAction = styled(EuiFlexGroup).attrs(() => ({ alignItems: 'center', responsive: false, -})` - margin-top: ${props => props.theme.eui.euiSizeXS}; +}))` + margin-top: ${({ theme }) => theme.eui.euiSizeXS}; `; FooterAction.displayName = 'FooterAction'; const PaginationEuiFlexItem = styled(EuiFlexItem)` - ${props => css` - @media only screen and (min-width: ${props.theme.eui.euiBreakpoints.m}) { - .euiButtonIcon:last-child { - margin-left: 28px; - } + @media only screen and (min-width: ${({ theme }) => theme.eui.euiBreakpoints.m}) { + .euiButtonIcon:last-child { + margin-left: 28px; + } - .euiPagination { - position: relative; - } + .euiPagination { + position: relative; + } - .euiPagination::before { - bottom: 0; - color: ${props.theme.eui.euiButtonColorDisabled}; - content: '\\2026'; - font-size: ${props.theme.eui.euiFontSizeS}; - padding: 5px ${props.theme.eui.euiSizeS}; - position: absolute; - right: ${props.theme.eui.euiSizeL}; - } + .euiPagination::before { + bottom: 0; + color: ${({ theme }) => theme.eui.euiButtonColorDisabled}; + content: '\\2026'; + font-size: ${({ theme }) => theme.eui.euiFontSizeS}; + padding: 5px ${({ theme }) => theme.eui.euiSizeS}; + position: absolute; + right: ${({ theme }) => theme.eui.euiSizeL}; } - `} + } `; PaginationEuiFlexItem.displayName = 'PaginationEuiFlexItem'; diff --git a/x-pack/legacy/plugins/siem/public/components/query_bar/index.tsx b/x-pack/legacy/plugins/siem/public/components/query_bar/index.tsx index c7e58532fc7e5..8b5f3b0f4d425 100644 --- a/x-pack/legacy/plugins/siem/public/components/query_bar/index.tsx +++ b/x-pack/legacy/plugins/siem/public/components/query_bar/index.tsx @@ -20,6 +20,7 @@ import { SavedQueryTimeFilter } from '../../../../../../../src/legacy/core_plugi import { Storage } from '../../../../../../../src/plugins/kibana_utils/public'; export interface QueryBarComponentProps { + dataTestSubj?: string; dateRangeFrom?: string; dateRangeTo?: string; hideSavedQuery?: boolean; @@ -50,6 +51,7 @@ export const QueryBar = memo( refreshInterval, savedQuery, onSavedQuery, + dataTestSubj, }) => { const [draftQuery, setDraftQuery] = useState(filterQuery); @@ -139,6 +141,7 @@ export const QueryBar = memo( showQueryInput={true} showSaveQuery={true} timeHistory={new TimeHistory(new Storage(localStorage))} + dataTestSubj={dataTestSubj} {...searchBarProps} /> ); diff --git a/x-pack/legacy/plugins/siem/public/components/resize_handle/__snapshots__/index.test.tsx.snap b/x-pack/legacy/plugins/siem/public/components/resize_handle/__snapshots__/index.test.tsx.snap index 432abd799b48a..6ae630f363b58 100644 --- a/x-pack/legacy/plugins/siem/public/components/resize_handle/__snapshots__/index.test.tsx.snap +++ b/x-pack/legacy/plugins/siem/public/components/resize_handle/__snapshots__/index.test.tsx.snap @@ -4,7 +4,7 @@ exports[`Resizeable it renders 1`] = ` } diff --git a/x-pack/legacy/plugins/siem/public/components/resize_handle/index.test.tsx b/x-pack/legacy/plugins/siem/public/components/resize_handle/index.test.tsx index 6bb036a88a9d7..f84276f99315d 100644 --- a/x-pack/legacy/plugins/siem/public/components/resize_handle/index.test.tsx +++ b/x-pack/legacy/plugins/siem/public/components/resize_handle/index.test.tsx @@ -6,7 +6,6 @@ import { mount, shallow } from 'enzyme'; import toJson from 'enzyme-to-json'; -import 'jest-styled-components'; import * as React from 'react'; import { TestProviders } from '../../mock/test_providers'; diff --git a/x-pack/legacy/plugins/siem/public/components/resize_handle/index.tsx b/x-pack/legacy/plugins/siem/public/components/resize_handle/index.tsx index 0a6203056fd20..eb3326c2f2cd0 100644 --- a/x-pack/legacy/plugins/siem/public/components/resize_handle/index.tsx +++ b/x-pack/legacy/plugins/siem/public/components/resize_handle/index.tsx @@ -7,7 +7,7 @@ import React, { useEffect, useRef } from 'react'; import { fromEvent, Observable, Subscription } from 'rxjs'; import { concatMap, takeUntil } from 'rxjs/operators'; -import styled, { css } from 'styled-components'; +import styled from 'styled-components'; export type OnResize = ({ delta, id }: { delta: number; id: string }) => void; @@ -42,16 +42,14 @@ interface Props extends ResizeHandleContainerProps { } const ResizeHandleContainer = styled.div` - ${({ bottom, height, left, positionAbsolute, right, theme, top }) => css` - bottom: ${positionAbsolute && bottom}; - cursor: ${resizeCursorStyle}; - height: ${height}; - left: ${positionAbsolute && left}; - position: ${positionAbsolute && 'absolute'}; - right: ${positionAbsolute && right}; - top: ${positionAbsolute && top}; - z-index: ${positionAbsolute && theme.eui.euiZLevel1}; - `} + bottom: ${({ positionAbsolute, bottom }) => positionAbsolute && bottom}; + cursor: ${resizeCursorStyle}; + height: ${({ height }) => height}; + left: ${({ positionAbsolute, left }) => positionAbsolute && left}; + position: ${({ positionAbsolute }) => positionAbsolute && 'absolute'}; + right: ${({ positionAbsolute, right }) => positionAbsolute && right}; + top: ${({ positionAbsolute, top }) => positionAbsolute && top}; + z-index: ${({ positionAbsolute, theme }) => positionAbsolute && theme.eui.euiZLevel1}; `; ResizeHandleContainer.displayName = 'ResizeHandleContainer'; @@ -69,7 +67,7 @@ export const Resizeable = React.memo( const dragEventTargets = useRef>([]); const dragSubscription = useRef(null); const prevX = useRef(0); - const ref = useRef>(React.createRef()); + const ref = useRef(null); const upSubscription = useRef(null); const isResizingRef = useRef(false); @@ -80,7 +78,7 @@ export const Resizeable = React.memo( }; useEffect(() => { const move$ = fromEvent(document, 'mousemove'); - const down$ = fromEvent(ref.current.current!, 'mousedown'); + const down$ = fromEvent(ref.current!, 'mousedown'); const up$ = fromEvent(document, 'mouseup'); drag$.current = down$.pipe(concatMap(() => move$.pipe(takeUntil(up$)))); @@ -131,7 +129,7 @@ export const Resizeable = React.memo( bottom={bottom} data-test-subj="resize-handle-container" height={height} - innerRef={ref.current} + ref={ref} left={left} positionAbsolute={positionAbsolute} right={right} diff --git a/x-pack/legacy/plugins/siem/public/components/search_bar/index.tsx b/x-pack/legacy/plugins/siem/public/components/search_bar/index.tsx index c16c3a33872d5..33fb2b9239a6a 100644 --- a/x-pack/legacy/plugins/siem/public/components/search_bar/index.tsx +++ b/x-pack/legacy/plugins/siem/public/components/search_bar/index.tsx @@ -71,6 +71,7 @@ interface SiemSearchBarProps { id: InputsModelId; indexPattern: StaticIndexPattern; timelineId?: string; + dataTestSubj?: string; } const SearchBarContainer = styled.div` @@ -95,6 +96,7 @@ const SearchBarComponent = memo { const { timefilter } = npStart.plugins.data.query.timefilter; if (fromStr != null && toStr != null) { @@ -275,6 +277,7 @@ const SearchBarComponent = memo ); diff --git a/x-pack/legacy/plugins/siem/public/components/selectable_text/index.test.tsx b/x-pack/legacy/plugins/siem/public/components/selectable_text/index.test.tsx index 3ecbfcc630752..95c68d0233c69 100644 --- a/x-pack/legacy/plugins/siem/public/components/selectable_text/index.test.tsx +++ b/x-pack/legacy/plugins/siem/public/components/selectable_text/index.test.tsx @@ -6,7 +6,6 @@ import { mount, shallow } from 'enzyme'; import toJson from 'enzyme-to-json'; -import 'jest-styled-components'; import * as React from 'react'; import { SelectableText } from '.'; diff --git a/x-pack/legacy/plugins/siem/public/components/skeleton_row/index.test.tsx b/x-pack/legacy/plugins/siem/public/components/skeleton_row/index.test.tsx index b5147d395c738..fc1c6e00edc03 100644 --- a/x-pack/legacy/plugins/siem/public/components/skeleton_row/index.test.tsx +++ b/x-pack/legacy/plugins/siem/public/components/skeleton_row/index.test.tsx @@ -6,7 +6,6 @@ import { mount, shallow } from 'enzyme'; import toJson from 'enzyme-to-json'; -import 'jest-styled-components'; import React from 'react'; import { TestProviders } from '../../mock'; diff --git a/x-pack/legacy/plugins/siem/public/components/skeleton_row/index.tsx b/x-pack/legacy/plugins/siem/public/components/skeleton_row/index.tsx index 6359063798ba8..20aea3251d838 100644 --- a/x-pack/legacy/plugins/siem/public/components/skeleton_row/index.tsx +++ b/x-pack/legacy/plugins/siem/public/components/skeleton_row/index.tsx @@ -5,24 +5,22 @@ */ import React from 'react'; -import styled, { css } from 'styled-components'; +import styled from 'styled-components'; interface RowProps { rowHeight?: string; rowPadding?: string; } -const Row = styled.div.attrs({ +const Row = styled.div.attrs(({ rowHeight, rowPadding, theme }) => ({ className: 'siemSkeletonRow', -})` - ${({ rowHeight, rowPadding, theme }) => css` - border-bottom: ${theme.eui.euiBorderThin}; - display: flex; - height: ${rowHeight ? rowHeight : theme.eui.euiSizeXL}; - padding: ${rowPadding - ? rowPadding - : theme.eui.paddingSizes.s + ' ' + theme.eui.paddingSizes.xs}; - `} + rowHeight: rowHeight || theme.eui.euiSizeXL, + rowPadding: rowPadding || `${theme.eui.paddingSizes.s} ${theme.eui.paddingSizes.xs}`, +}))` + border-bottom: ${({ theme }) => theme.eui.euiBorderThin}; + display: flex; + height: ${({ rowHeight }) => rowHeight}; + padding: ${({ rowPadding }) => rowPadding}; `; Row.displayName = 'Row'; @@ -31,18 +29,18 @@ interface CellProps { cellMargin?: string; } -const Cell = styled.div.attrs({ +const Cell = styled.div.attrs(({ cellColor, cellMargin, theme }) => ({ className: 'siemSkeletonRow__cell', -})` - ${({ cellColor, cellMargin, theme }) => css` - background-color: ${cellColor ? cellColor : theme.eui.euiColorLightestShade}; - border-radius: 2px; - flex: 1; + cellColor: cellColor || theme.eui.euiColorLightestShade, + cellMargin: cellMargin || theme.eui.gutterTypes.gutterSmall, +}))` + background-color: ${({ cellColor }) => cellColor}; + border-radius: 2px; + flex: 1; - & + & { - margin-left: ${cellMargin ? cellMargin : theme.eui.gutterTypes.gutterSmall}; - } - `} + & + & { + margin-left: ${({ cellMargin }) => cellMargin}; + } `; Cell.displayName = 'Cell'; diff --git a/x-pack/legacy/plugins/siem/public/components/stat_items/__snapshots__/index.test.tsx.snap b/x-pack/legacy/plugins/siem/public/components/stat_items/__snapshots__/index.test.tsx.snap index 7475220b56e77..952d92f532c83 100644 --- a/x-pack/legacy/plugins/siem/public/components/stat_items/__snapshots__/index.test.tsx.snap +++ b/x-pack/legacy/plugins/siem/public/components/stat_items/__snapshots__/index.test.tsx.snap @@ -38,11 +38,11 @@ exports[`Stat Items Component disable charts it renders the default widget 1`] = data-test-subj="stat-item" >

@@ -292,11 +292,11 @@ exports[`Stat Items Component disable charts it renders the default widget 2`] = data-test-subj="stat-item" >

@@ -616,11 +616,11 @@ exports[`Stat Items Component rendering kpis with charts it renders the default data-test-subj="stat-item" >

1,714 @@ -857,10 +857,10 @@ exports[`Stat Items Component rendering kpis with charts it renders the default key="stat-items-field-uniqueDestinationIps" >

2,359 @@ -957,10 +957,10 @@ exports[`Stat Items Component rendering kpis with charts it renders the default >

(({ children }) => { - if (typeof children === 'string') { - return

{children}

; - } else { - return
{children}
; +const SubtitleItem = React.memo( + ({ children, dataTestSubj = 'header-panel-subtitle' }) => { + if (typeof children === 'string') { + return ( +

+ {children} +

+ ); + } else { + return ( +
+ {children} +
+ ); + } } -}); +); SubtitleItem.displayName = 'SubtitleItem'; export interface SubtitleProps { diff --git a/x-pack/legacy/plugins/siem/public/components/timeline/body/column_headers/events_select/index.tsx b/x-pack/legacy/plugins/siem/public/components/timeline/body/column_headers/events_select/index.tsx index c605e9e4bfe62..747ef8f3ffe47 100644 --- a/x-pack/legacy/plugins/siem/public/components/timeline/body/column_headers/events_select/index.tsx +++ b/x-pack/legacy/plugins/siem/public/components/timeline/body/column_headers/events_select/index.tsx @@ -8,17 +8,17 @@ import { EuiCheckbox, EuiSuperSelect } from '@elastic/eui'; import { noop } from 'lodash/fp'; import * as React from 'react'; import { pure } from 'recompose'; -import styled, { injectGlobal } from 'styled-components'; +import styled, { createGlobalStyle } from 'styled-components'; import { getEventsSelectOptions } from './helpers'; export type CheckState = 'checked' | 'indeterminate' | 'unchecked'; export const EVENTS_SELECT_WIDTH = 60; // px -// SIDE EFFECT: the following `injectGlobal` overrides +// SIDE EFFECT: the following `createGlobalStyle` overrides // the style of the select items // eslint-disable-next-line -injectGlobal` +createGlobalStyle` .eventsSelectItem { width: 100% !important; diff --git a/x-pack/legacy/plugins/siem/public/components/timeline/body/column_headers/header/__snapshots__/index.test.tsx.snap b/x-pack/legacy/plugins/siem/public/components/timeline/body/column_headers/header/__snapshots__/index.test.tsx.snap index b009ec78aac59..64c2b6ed10692 100644 --- a/x-pack/legacy/plugins/siem/public/components/timeline/body/column_headers/header/__snapshots__/index.test.tsx.snap +++ b/x-pack/legacy/plugins/siem/public/components/timeline/body/column_headers/header/__snapshots__/index.test.tsx.snap @@ -3,7 +3,7 @@ exports[`Header renders correctly against snapshot 1`] = ` } + handle={} id="@timestamp" onResize={[Function]} positionAbsolute={true} diff --git a/x-pack/legacy/plugins/siem/public/components/timeline/body/column_headers/header/index.test.tsx b/x-pack/legacy/plugins/siem/public/components/timeline/body/column_headers/header/index.test.tsx index 69899ece0cea8..ce465ac4f837e 100644 --- a/x-pack/legacy/plugins/siem/public/components/timeline/body/column_headers/header/index.test.tsx +++ b/x-pack/legacy/plugins/siem/public/components/timeline/body/column_headers/header/index.test.tsx @@ -6,7 +6,6 @@ import { mount, shallow } from 'enzyme'; import toJson from 'enzyme-to-json'; -import 'jest-styled-components'; import * as React from 'react'; import { Direction } from '../../../../../graphql/types'; diff --git a/x-pack/legacy/plugins/siem/public/components/timeline/body/column_headers/index.tsx b/x-pack/legacy/plugins/siem/public/components/timeline/body/column_headers/index.tsx index c4239c0eb7f38..aca74b3da645f 100644 --- a/x-pack/legacy/plugins/siem/public/components/timeline/body/column_headers/index.tsx +++ b/x-pack/legacy/plugins/siem/public/components/timeline/body/column_headers/index.tsx @@ -115,7 +115,7 @@ export const ColumnHeaders = React.memo( {dropProvided => ( {columnHeaders.map((header, i) => ( @@ -137,7 +137,7 @@ export const ColumnHeaders = React.memo( {...dragProvided.draggableProps} {...dragProvided.dragHandleProps} data-test-subj="draggable-header" - innerRef={dragProvided.innerRef} + ref={dragProvided.innerRef} isDragging={dragSnapshot.isDragging} position="relative" // Passing the styles directly to the component because the width is being calculated and is recommended by Styled Components for performance: https://github.com/styled-components/styled-components/issues/134#issuecomment-312415291 diff --git a/x-pack/legacy/plugins/siem/public/components/timeline/body/events/stateful_event.tsx b/x-pack/legacy/plugins/siem/public/components/timeline/body/events/stateful_event.tsx index d54fe8df28a85..b3ef4b7b39466 100644 --- a/x-pack/legacy/plugins/siem/public/components/timeline/body/events/stateful_event.tsx +++ b/x-pack/legacy/plugins/siem/public/components/timeline/body/events/stateful_event.tsx @@ -200,7 +200,7 @@ export const StatefulEvent = React.memo( { + ref={c => { if (c != null) { divElement.current = c; } diff --git a/x-pack/legacy/plugins/siem/public/components/timeline/body/index.test.tsx b/x-pack/legacy/plugins/siem/public/components/timeline/body/index.test.tsx index 86a6ebe22799b..0fb4c4f375684 100644 --- a/x-pack/legacy/plugins/siem/public/components/timeline/body/index.test.tsx +++ b/x-pack/legacy/plugins/siem/public/components/timeline/body/index.test.tsx @@ -5,7 +5,6 @@ */ import { mount, ReactWrapper } from 'enzyme'; -import 'jest-styled-components'; import * as React from 'react'; import { mockBrowserFields } from '../../../containers/source/mock'; diff --git a/x-pack/legacy/plugins/siem/public/components/timeline/data_providers/provider_badge.tsx b/x-pack/legacy/plugins/siem/public/components/timeline/data_providers/provider_badge.tsx index b7d0f2ff50bc1..59d15bc43e10c 100644 --- a/x-pack/legacy/plugins/siem/public/components/timeline/data_providers/provider_badge.tsx +++ b/x-pack/legacy/plugins/siem/public/components/timeline/data_providers/provider_badge.tsx @@ -53,7 +53,7 @@ interface ProviderBadgeProps { isEnabled: boolean; isExcluded: boolean; providerId: string; - togglePopover?: () => void; + togglePopover: () => void; val: string | number; operator: QueryOperator; } diff --git a/x-pack/legacy/plugins/siem/public/components/timeline/data_providers/provider_item_actions.tsx b/x-pack/legacy/plugins/siem/public/components/timeline/data_providers/provider_item_actions.tsx index ee9e5f2af654a..121f832221d3e 100644 --- a/x-pack/legacy/plugins/siem/public/components/timeline/data_providers/provider_item_actions.tsx +++ b/x-pack/legacy/plugins/siem/public/components/timeline/data_providers/provider_item_actions.tsx @@ -3,8 +3,13 @@ * or more contributor license agreements. Licensed under the Elastic License; * you may not use this file except in compliance with the Elastic License. */ -import { EuiContextMenu, EuiContextMenuPanelDescriptor, EuiPopover } from '@elastic/eui'; -import React from 'react'; +import { + EuiContextMenu, + EuiContextMenuPanelDescriptor, + EuiPopover, + EuiPopoverProps, +} from '@elastic/eui'; +import React, { FunctionComponent } from 'react'; import styled from 'styled-components'; import { BrowserFields } from '../../../containers/source'; @@ -41,7 +46,11 @@ interface OwnProps { value: string | number; } -const MyEuiPopover = styled(EuiPopover)` +const MyEuiPopover = styled((EuiPopover as unknown) as FunctionComponent)< + EuiPopoverProps & { + id?: string; + } +>` height: 100%; user-select: none; `; diff --git a/x-pack/legacy/plugins/siem/public/components/timeline/footer/index.tsx b/x-pack/legacy/plugins/siem/public/components/timeline/footer/index.tsx index a0942cbaba091..93f1e484828d2 100644 --- a/x-pack/legacy/plugins/siem/public/components/timeline/footer/index.tsx +++ b/x-pack/legacy/plugins/siem/public/components/timeline/footer/index.tsx @@ -16,9 +16,10 @@ import { EuiPopover, EuiText, EuiToolTip, + EuiPopoverProps, } from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n/react'; -import React, { useCallback, useEffect, useState } from 'react'; +import React, { FunctionComponent, useCallback, useEffect, useState } from 'react'; import { pure } from 'recompose'; import styled from 'styled-components'; @@ -55,7 +56,12 @@ const LoadingPanelContainer = styled.div` LoadingPanelContainer.displayName = 'LoadingPanelContainer'; -const PopoverRowItems = styled(EuiPopover)` +const PopoverRowItems = styled((EuiPopover as unknown) as FunctionComponent)< + EuiPopoverProps & { + className?: string; + id?: string; + } +>` .euiButtonEmpty__content { padding: 0px 0px; } diff --git a/x-pack/legacy/plugins/siem/public/components/timeline/properties/index.tsx b/x-pack/legacy/plugins/siem/public/components/timeline/properties/index.tsx index 40ba16c0c128a..ccc222673d7bc 100644 --- a/x-pack/legacy/plugins/siem/public/components/timeline/properties/index.tsx +++ b/x-pack/legacy/plugins/siem/public/components/timeline/properties/index.tsx @@ -6,7 +6,7 @@ import { EuiAvatar, EuiFlexItem, EuiIcon } from '@elastic/eui'; import React, { useState, useCallback } from 'react'; -import styled, { injectGlobal } from 'styled-components'; +import styled, { createGlobalStyle } from 'styled-components'; import { Note } from '../../../lib/note'; import { InputsModelId } from '../../../store/inputs/constants'; @@ -22,10 +22,10 @@ type UpdateTitle = ({ id, title }: { id: string; title: string }) => void; type UpdateDescription = ({ id, description }: { id: string; description: string }) => void; type ToggleLock = ({ linkToId }: { linkToId: InputsModelId }) => void; -// SIDE EFFECT: the following `injectGlobal` overrides `EuiPopover` +// SIDE EFFECT: the following `createGlobalStyle` overrides `EuiPopover` // and `EuiToolTip` global styles: // eslint-disable-next-line no-unused-expressions -injectGlobal` +createGlobalStyle` .euiPopover__panel.euiPopover__panel-isOpen { z-index: 9900 !important; } diff --git a/x-pack/legacy/plugins/siem/public/components/timeline/query_bar/index.tsx b/x-pack/legacy/plugins/siem/public/components/timeline/query_bar/index.tsx index 6d76c277711d7..f24ee3155c924 100644 --- a/x-pack/legacy/plugins/siem/public/components/timeline/query_bar/index.tsx +++ b/x-pack/legacy/plugins/siem/public/components/timeline/query_bar/index.tsx @@ -288,6 +288,7 @@ export const QueryBarTimeline = memo( refreshInterval={refreshInterval} savedQuery={savedQuery} onSavedQuery={onSavedQuery} + dataTestSubj={'timelineQueryInput'} /> ); } diff --git a/x-pack/legacy/plugins/siem/public/components/timeline/search_or_filter/search_or_filter.tsx b/x-pack/legacy/plugins/siem/public/components/timeline/search_or_filter/search_or_filter.tsx index db8909adda239..2d953ce3cfc95 100644 --- a/x-pack/legacy/plugins/siem/public/components/timeline/search_or_filter/search_or_filter.tsx +++ b/x-pack/legacy/plugins/siem/public/components/timeline/search_or_filter/search_or_filter.tsx @@ -7,7 +7,7 @@ import { EuiFlexGroup, EuiFlexItem, EuiSuperSelect, EuiToolTip } from '@elastic/eui'; import * as React from 'react'; import { pure } from 'recompose'; -import styled, { injectGlobal } from 'styled-components'; +import styled, { createGlobalStyle } from 'styled-components'; import { StaticIndexPattern } from 'ui/index_patterns'; import { esFilters } from '../../../../../../../../src/plugins/data/public'; @@ -27,7 +27,7 @@ const searchOrFilterPopoverWidth = '352px'; // SIDE EFFECT: the following creates a global class selector // eslint-disable-next-line no-unused-expressions -injectGlobal` +createGlobalStyle` .${timelineSelectModeItemsClassName} { width: 350px !important; } diff --git a/x-pack/legacy/plugins/siem/public/components/timeline/styles.tsx b/x-pack/legacy/plugins/siem/public/components/timeline/styles.tsx index 86c470ef4d3a5..856259f11ced9 100644 --- a/x-pack/legacy/plugins/siem/public/components/timeline/styles.tsx +++ b/x-pack/legacy/plugins/siem/public/components/timeline/styles.tsx @@ -6,7 +6,7 @@ import { EuiLoadingSpinner } from '@elastic/eui'; import { rgba } from 'polished'; -import styled, { css } from 'styled-components'; +import styled from 'styled-components'; /** * OFFSET PIXEL VALUES @@ -18,30 +18,28 @@ export const OFFSET_SCROLLBAR = 17; * TIMELINE BODY */ -export const TimelineBody = styled.div.attrs({ - className: 'siemTimeline__body', -})<{ bodyHeight: number }>` - ${({ bodyHeight, theme }) => css` - height: ${bodyHeight + 'px'}; - overflow: auto; - scrollbar-width: thin; - - &::-webkit-scrollbar { - height: ${theme.eui.euiScrollBar}; - width: ${theme.eui.euiScrollBar}; - } +export const TimelineBody = styled.div.attrs(({ className }) => ({ + className: `siemTimeline__body ${className}`, +}))<{ bodyHeight: number }>` + height: ${({ bodyHeight }) => bodyHeight + 'px'}; + overflow: auto; + scrollbar-width: thin; - &::-webkit-scrollbar-thumb { - background-clip: content-box; - background-color: ${rgba(theme.eui.euiColorDarkShade, 0.5)}; - border: ${theme.eui.euiScrollBarCorner} solid transparent; - } + &::-webkit-scrollbar { + height: ${({ theme }) => theme.eui.euiScrollBar}; + width: ${({ theme }) => theme.eui.euiScrollBar}; + } - &::-webkit-scrollbar-corner, - &::-webkit-scrollbar-track { - background-color: transparent; - } - `} + &::-webkit-scrollbar-thumb { + background-clip: content-box; + background-color: ${({ theme }) => rgba(theme.eui.euiColorDarkShade, 0.5)}; + border: ${({ theme }) => theme.eui.euiScrollBarCorner} solid transparent; + } + + &::-webkit-scrollbar-corner, + &::-webkit-scrollbar-track { + background-color: transparent; + } `; TimelineBody.displayName = 'TimelineBody'; @@ -49,39 +47,38 @@ TimelineBody.displayName = 'TimelineBody'; * EVENTS TABLE */ -export const EventsTable = styled.div.attrs({ - className: 'siemEventsTable', +export const EventsTable = styled.div.attrs(({ className }) => ({ + className: `siemEventsTable ${className}`, role: 'table', -})``; +}))``; EventsTable.displayName = 'EventsTable'; /* EVENTS HEAD */ -export const EventsThead = styled.div.attrs({ - className: 'siemEventsTable__thead', +export const EventsThead = styled.div.attrs(({ className }) => ({ + className: `siemEventsTable__thead ${className}`, role: 'rowgroup', -})` - ${({ theme }) => css` - background-color: ${theme.eui.euiColorEmptyShade}; - border-bottom: ${theme.eui.euiBorderWidthThick} solid ${theme.eui.euiColorLightShade}; - position: sticky; - top: 0; - z-index: ${theme.eui.euiZLevel1}; - `} +}))` + background-color: ${({ theme }) => theme.eui.euiColorEmptyShade}; + border-bottom: ${({ theme }) => theme.eui.euiBorderWidthThick} solid + ${({ theme }) => theme.eui.euiColorLightShade}; + position: sticky; + top: 0; + z-index: ${({ theme }) => theme.eui.euiZLevel1}; `; EventsThead.displayName = 'EventsThead'; -export const EventsTrHeader = styled.div.attrs({ - className: 'siemEventsTable__trHeader', +export const EventsTrHeader = styled.div.attrs(({ className }) => ({ + className: `siemEventsTable__trHeader ${className}`, role: 'row', -})` +}))` display: flex; `; EventsTrHeader.displayName = 'EventsTrHeader'; -export const EventsThGroupActions = styled.div.attrs({ - className: 'siemEventsTable__thGroupActions', -})<{ actionsColumnWidth: number }>` +export const EventsThGroupActions = styled.div.attrs(({ className }) => ({ + className: `siemEventsTable__thGroupActions ${className}`, +}))<{ actionsColumnWidth: number }>` display: flex; flex: 0 0 ${({ actionsColumnWidth }) => actionsColumnWidth + 'px'}; justify-content: space-between; @@ -89,17 +86,17 @@ export const EventsThGroupActions = styled.div.attrs({ `; EventsThGroupActions.displayName = 'EventsThGroupActions'; -export const EventsThGroupData = styled.div.attrs({ - className: 'siemEventsTable__thGroupData', -})` +export const EventsThGroupData = styled.div.attrs(({ className }) => ({ + className: `siemEventsTable__thGroupData ${className}`, +}))` display: flex; `; EventsThGroupData.displayName = 'EventsThGroupData'; -export const EventsTh = styled.div.attrs({ - className: 'siemEventsTable__th', +export const EventsTh = styled.div.attrs(({ className }) => ({ + className: `siemEventsTable__th ${className}`, role: 'columnheader', -})<{ isDragging?: boolean; position?: string }>` +}))<{ isDragging?: boolean; position?: string }>` align-items: center; display: flex; flex-shrink: 0; @@ -118,66 +115,62 @@ export const EventsTh = styled.div.attrs({ `; EventsTh.displayName = 'EventsTh'; -export const EventsThContent = styled.div.attrs({ - className: 'siemEventsTable__thContent', -})<{ textAlign?: string }>` - ${({ textAlign, theme }) => css` - font-size: ${theme.eui.euiFontSizeXS}; - font-weight: ${theme.eui.euiFontWeightSemiBold}; - line-height: ${theme.eui.euiLineHeight}; - min-width: 0; - padding: ${theme.eui.paddingSizes.xs}; - text-align: ${textAlign}; - width: 100%; //Using width: 100% instead of flex: 1 and max-width: 100% for IE11 - `} +export const EventsThContent = styled.div.attrs(({ className }) => ({ + className: `siemEventsTable__thContent ${className}`, +}))<{ textAlign?: string }>` + font-size: ${({ theme }) => theme.eui.euiFontSizeXS}; + font-weight: ${({ theme }) => theme.eui.euiFontWeightSemiBold}; + line-height: $({ theme }) =>theme.eui.euiLineHeight}; + min-width: 0; + padding: ${({ theme }) => theme.eui.paddingSizes.xs}; + text-align: ${({ textAlign }) => textAlign}; + width: 100%; //Using width: 100% instead of flex: 1 and max-width: 100% for IE11 `; EventsThContent.displayName = 'EventsThContent'; /* EVENTS BODY */ -export const EventsTbody = styled.div.attrs({ - className: 'siemEventsTable__tbody', +export const EventsTbody = styled.div.attrs(({ className }) => ({ + className: `siemEventsTable__tbody ${className}`, role: 'rowgroup', -})` +}))` overflow-x: hidden; `; EventsTbody.displayName = 'EventsTbody'; -export const EventsTrGroup = styled.div.attrs({ - className: 'siemEventsTable__trGroup', -})<{ className?: string }>` - ${({ theme }) => css` - border-bottom: ${theme.eui.euiBorderWidthThin} solid ${theme.eui.euiColorLightShade}; +export const EventsTrGroup = styled.div.attrs(({ className }) => ({ + className: `siemEventsTable__trGroup ${className}`, +}))<{ className?: string }>` + border-bottom: ${({ theme }) => theme.eui.euiBorderWidthThin} solid + ${({ theme }) => theme.eui.euiColorLightShade}; - &:hover { - background-color: ${theme.eui.euiTableHoverColor}; - } - `} + &:hover { + background-color: ${({ theme }) => theme.eui.euiTableHoverColor}; + } `; EventsTrGroup.displayName = 'EventsTrGroup'; -export const EventsTrData = styled.div.attrs({ - className: 'siemEventsTable__trData', +export const EventsTrData = styled.div.attrs(({ className }) => ({ + className: `siemEventsTable__trData ${className}`, role: 'row', -})` +}))` display: flex; `; EventsTrData.displayName = 'EventsTrData'; -export const EventsTrSupplement = styled.div.attrs({ - className: 'siemEventsTable__trSupplement', -})<{ className: string }>` - ${({ theme }) => css` - font-size: ${theme.eui.euiFontSizeXS}; - line-height: ${theme.eui.euiLineHeight}; - padding: 0 ${theme.eui.paddingSizes.xs} 0 ${theme.eui.paddingSizes.xl}; - `} +export const EventsTrSupplement = styled.div.attrs(({ className }) => ({ + className: `siemEventsTable__trSupplement ${className}`, +}))<{ className: string }>` + font-size: ${({ theme }) => theme.eui.euiFontSizeXS}; + line-height: ${({ theme }) => theme.eui.euiLineHeight}; + padding: 0 ${({ theme }) => theme.eui.paddingSizes.xs} 0 + ${({ theme }) => theme.eui.paddingSizes.xl}; `; EventsTrSupplement.displayName = 'EventsTrSupplement'; -export const EventsTdGroupActions = styled.div.attrs({ - className: 'siemEventsTable__tdGroupActions', -})<{ actionsColumnWidth: number }>` +export const EventsTdGroupActions = styled.div.attrs(({ className }) => ({ + className: `siemEventsTable__tdGroupActions ${className}`, +}))<{ actionsColumnWidth: number }>` display: flex; justify-content: space-between; flex: 0 0 ${({ actionsColumnWidth }) => actionsColumnWidth + 'px'}; @@ -185,17 +178,17 @@ export const EventsTdGroupActions = styled.div.attrs({ `; EventsTdGroupActions.displayName = 'EventsTdGroupActions'; -export const EventsTdGroupData = styled.div.attrs({ - className: 'siemEventsTable__tdGroupData', -})` +export const EventsTdGroupData = styled.div.attrs(({ className }) => ({ + className: `siemEventsTable__tdGroupData ${className}`, +}))` display: flex; `; EventsTdGroupData.displayName = 'EventsTdGroupData'; -export const EventsTd = styled.div.attrs({ - className: 'siemEventsTable__td', +export const EventsTd = styled.div.attrs(({ className }) => ({ + className: `siemEventsTable__td ${className}`, role: 'cell', -})` +}))` align-items: center; display: flex; flex-shrink: 0; @@ -207,17 +200,15 @@ export const EventsTd = styled.div.attrs({ `; EventsTd.displayName = 'EventsTd'; -export const EventsTdContent = styled.div.attrs({ - className: 'siemEventsTable__tdContent', -})<{ textAlign?: string }>` - ${({ textAlign, theme }) => css` - font-size: ${theme.eui.euiFontSizeXS}; - line-height: ${theme.eui.euiLineHeight}; - min-width: 0; - padding: ${theme.eui.paddingSizes.xs}; - text-align: ${textAlign}; - width: 100%; //Using width: 100% instead of flex: 1 and max-width: 100% for IE11 - `} +export const EventsTdContent = styled.div.attrs(({ className }) => ({ + className: `siemEventsTable__tdContent ${className}`, +}))<{ textAlign?: string }>` + font-size: ${({ theme }) => theme.eui.euiFontSizeXS}; + line-height: ${({ theme }) => theme.eui.euiLineHeight}; + min-width: 0; + padding: ${({ theme }) => theme.eui.paddingSizes.xs}; + text-align: ${({ textAlign }) => textAlign}; + width: 100%; //Using width: 100% instead of flex: 1 and max-width: 100% for IE11 `; EventsTdContent.displayName = 'EventsTdContent'; @@ -225,9 +216,9 @@ EventsTdContent.displayName = 'EventsTdContent'; * EVENTS HEADING */ -export const EventsHeading = styled.div.attrs({ - className: 'siemEventsHeading', -})<{ isLoading: boolean }>` +export const EventsHeading = styled.div.attrs(({ className }) => ({ + className: `siemEventsHeading ${className}`, +}))<{ isLoading: boolean }>` align-items: center; display: flex; @@ -237,81 +228,75 @@ export const EventsHeading = styled.div.attrs({ `; EventsHeading.displayName = 'EventsHeading'; -export const EventsHeadingTitleButton = styled.button.attrs({ - className: 'siemEventsHeading__title siemEventsHeading__title--aggregatable', +export const EventsHeadingTitleButton = styled.button.attrs(({ className }) => ({ + className: `siemEventsHeading__title siemEventsHeading__title--aggregatable ${className}`, type: 'button', -})` - ${({ theme }) => css` - align-items: center; - display: flex; - font-weight: inherit; - min-width: 0; - - &:hover, - &:focus { - color: ${theme.eui.euiColorPrimary}; - text-decoration: underline; - } +}))` + align-items: center; + display: flex; + font-weight: inherit; + min-width: 0; - &:hover { - cursor: pointer; - } + &:hover, + &:focus { + color: ${({ theme }) => theme.eui.euiColorPrimary}; + text-decoration: underline; + } - & > * + * { - margin-left: ${theme.eui.euiSizeXS}; - } - `} + &:hover { + cursor: pointer; + } + + & > * + * { + margin-left: ${({ theme }) => theme.eui.euiSizeXS}; + } `; EventsHeadingTitleButton.displayName = 'EventsHeadingTitleButton'; -export const EventsHeadingTitleSpan = styled.span.attrs({ - className: 'siemEventsHeading__title siemEventsHeading__title--notAggregatable', -})` +export const EventsHeadingTitleSpan = styled.span.attrs(({ className }) => ({ + className: `siemEventsHeading__title siemEventsHeading__title--notAggregatable ${className}`, +}))` min-width: 0; `; EventsHeadingTitleSpan.displayName = 'EventsHeadingTitleSpan'; -export const EventsHeadingExtra = styled.div.attrs({ - className: 'siemEventsHeading__extra', -})<{ className?: string }>` - ${({ theme }) => css` - margin-left: auto; - - &.siemEventsHeading__extra--close { - opacity: 0; - transition: all ${theme.eui.euiAnimSpeedNormal} ease; - visibility: hidden; - - .siemEventsTable__th:hover & { - opacity: 1; - visibility: visible; - } - } - `} -`; -EventsHeadingExtra.displayName = 'EventsHeadingExtra'; +export const EventsHeadingExtra = styled.div.attrs(({ className }) => ({ + className: `siemEventsHeading__extra ${className}`, +}))` + margin-left: auto; -export const EventsHeadingHandle = styled.div.attrs({ - className: 'siemEventsHeading__handle', -})` - ${({ theme }) => css` - background-color: ${theme.eui.euiBorderColor}; - height: 100%; + &.siemEventsHeading__extra--close { opacity: 0; - transition: all ${theme.eui.euiAnimSpeedNormal} ease; + transition: all ${({ theme }) => theme.eui.euiAnimSpeedNormal} ease; visibility: hidden; - width: ${theme.eui.euiBorderWidthThick}; - .siemEventsTable__thead:hover & { + .siemEventsTable__th:hover & { opacity: 1; visibility: visible; } + } +`; +EventsHeadingExtra.displayName = 'EventsHeadingExtra'; - &:hover { - background-color: ${theme.eui.euiColorPrimary}; - cursor: col-resize; - } - `} +export const EventsHeadingHandle = styled.div.attrs(({ className }) => ({ + className: `siemEventsHeading__handle ${className}`, +}))` + background-color: ${({ theme }) => theme.eui.euiBorderColor}; + height: 100%; + opacity: 0; + transition: all ${({ theme }) => theme.eui.euiAnimSpeedNormal} ease; + visibility: hidden; + width: ${({ theme }) => theme.eui.euiBorderWidthThick}; + + .siemEventsTable__thead:hover & { + opacity: 1; + visibility: visible; + } + + &:hover { + background-color: ${({ theme }) => theme.eui.euiColorPrimary}; + cursor: col-resize; + } `; EventsHeadingHandle.displayName = 'EventsHeadingHandle'; diff --git a/x-pack/legacy/plugins/siem/public/components/timeline/timeline.tsx b/x-pack/legacy/plugins/siem/public/components/timeline/timeline.tsx index 59469f96d0720..089fb72ff4c85 100644 --- a/x-pack/legacy/plugins/siem/public/components/timeline/timeline.tsx +++ b/x-pack/legacy/plugins/siem/public/components/timeline/timeline.tsx @@ -137,7 +137,7 @@ export const Timeline = React.memo( gutterSize="none" justifyContent="flexStart" > - + props.theme.eui.textColors.default} + color: ${({ theme }) => theme.eui.textColors.default}; height: 100%; position: relative; `; diff --git a/x-pack/legacy/plugins/siem/public/pages/home/index.tsx b/x-pack/legacy/plugins/siem/public/pages/home/index.tsx index eb816876bdba8..2cc98930767dc 100644 --- a/x-pack/legacy/plugins/siem/public/pages/home/index.tsx +++ b/x-pack/legacy/plugins/siem/public/pages/home/index.tsx @@ -59,7 +59,7 @@ const calculateFlyoutHeight = ({ export const HomePage = pure(() => ( {({ measureRef, windowMeasurement: { height: windowHeight = 0 } }) => ( - +
diff --git a/x-pack/legacy/plugins/siem/public/pages/network/navigation/conditional_flex_group.tsx b/x-pack/legacy/plugins/siem/public/pages/network/navigation/conditional_flex_group.tsx index 80084de743526..0fcd7fa48f73c 100644 --- a/x-pack/legacy/plugins/siem/public/pages/network/navigation/conditional_flex_group.tsx +++ b/x-pack/legacy/plugins/siem/public/pages/network/navigation/conditional_flex_group.tsx @@ -5,14 +5,12 @@ */ import { EuiFlexGroup } from '@elastic/eui'; -import styled, { css } from 'styled-components'; +import styled from 'styled-components'; export const ConditionalFlexGroup = styled(EuiFlexGroup)` - ${() => css` - @media only screen and (min-width: 1441px) { - flex-direction: row; - } - `} + @media only screen and (min-width: 1441px) { + flex-direction: row; + } `; ConditionalFlexGroup.displayName = 'ConditionalFlexGroup'; diff --git a/x-pack/legacy/plugins/spaces/public/views/components/space_card.test.tsx b/x-pack/legacy/plugins/spaces/public/views/components/space_card.test.tsx index 7f04189b50d5e..cb70daead1bd2 100644 --- a/x-pack/legacy/plugins/spaces/public/views/components/space_card.test.tsx +++ b/x-pack/legacy/plugins/spaces/public/views/components/space_card.test.tsx @@ -30,7 +30,7 @@ test('it is clickable', () => { const clickHandler = jest.fn(); const wrapper = mount(); - wrapper.simulate('click'); + wrapper.find('button').simulate('click'); expect(clickHandler).toHaveBeenCalledTimes(1); }); diff --git a/x-pack/legacy/plugins/upgrade_assistant/common/types.ts b/x-pack/legacy/plugins/upgrade_assistant/common/types.ts index 60018173781a0..ce653e461e13b 100644 --- a/x-pack/legacy/plugins/upgrade_assistant/common/types.ts +++ b/x-pack/legacy/plugins/upgrade_assistant/common/types.ts @@ -4,7 +4,6 @@ * you may not use this file except in compliance with the Elastic License. */ -import { Legacy } from 'kibana'; import { SavedObject, SavedObjectAttributes } from 'src/core/server'; export enum ReindexStep { @@ -79,15 +78,6 @@ export interface UIReindex { stop: boolean; } -export interface UpgradeAssistantTelemetryServer extends Legacy.Server { - usage: { - collectorSet: { - makeUsageCollector: any; - register: any; - }; - }; -} - export interface UpgradeAssistantTelemetrySavedObject { ui_open: { overview: number; diff --git a/x-pack/legacy/plugins/upgrade_assistant/index.ts b/x-pack/legacy/plugins/upgrade_assistant/index.ts index 7c38fbf02a564..f1762498246c7 100644 --- a/x-pack/legacy/plugins/upgrade_assistant/index.ts +++ b/x-pack/legacy/plugins/upgrade_assistant/index.ts @@ -3,18 +3,23 @@ * 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 Joi from 'joi'; import { Legacy } from 'kibana'; import { resolve } from 'path'; import mappings from './mappings.json'; -import { initServer } from './server'; +import { plugin } from './server/np_ready'; export function upgradeAssistant(kibana: any) { - return new kibana.Plugin({ + const publicSrc = resolve(__dirname, 'public'); + const npSrc = resolve(publicSrc, 'np_ready'); + + const config: Legacy.PluginSpecOptions = { id: 'upgrade_assistant', configPrefix: 'xpack.upgrade_assistant', require: ['elasticsearch'], uiExports: { + // @ts-ignore managementSections: ['plugins/upgrade_assistant'], savedObjectSchemas: { 'upgrade-assistant-reindex-operation': { @@ -24,10 +29,10 @@ export function upgradeAssistant(kibana: any) { isNamespaceAgnostic: true, }, }, - styleSheetPaths: resolve(__dirname, 'public/index.scss'), + styleSheetPaths: resolve(npSrc, 'application/index.scss'), mappings, }, - publicDir: resolve(__dirname, 'public'), + publicDir: publicSrc, config() { return Joi.object({ @@ -37,7 +42,30 @@ export function upgradeAssistant(kibana: any) { init(server: Legacy.Server) { // Add server routes and initialize the plugin here - initServer(server); + const instance = plugin({} as any); + instance.setup(server.newPlatform.setup.core, { + __LEGACY: { + // Legacy objects + events: server.events, + usage: server.usage, + savedObjects: server.savedObjects, + + // Legacy functions + log: server.log.bind(server), + + // Legacy plugins + plugins: { + elasticsearch: server.plugins.elasticsearch, + xpack_main: server.plugins.xpack_main, + cloud: { + config: { + isCloudEnabled: _.get(server.plugins, 'cloud.config.isCloudEnabled', false), + }, + }, + }, + }, + }); }, - }); + }; + return new kibana.Plugin(config); } diff --git a/x-pack/legacy/plugins/upgrade_assistant/public/app.tsx b/x-pack/legacy/plugins/upgrade_assistant/public/app.tsx deleted file mode 100644 index 3bf3375c43bd9..0000000000000 --- a/x-pack/legacy/plugins/upgrade_assistant/public/app.tsx +++ /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 React from 'react'; - -import { EuiPageHeader, EuiPageHeaderSection, EuiTitle } from '@elastic/eui'; -import { FormattedMessage } from '@kbn/i18n/react'; - -import { NEXT_MAJOR_VERSION } from '../common/version'; -import { UpgradeAssistantTabs } from './components/tabs'; - -export const RootComponent: React.StatelessComponent = () => ( -
- - - -

- -

-
-
-
- -
-); diff --git a/x-pack/legacy/plugins/upgrade_assistant/public/components/_index.scss b/x-pack/legacy/plugins/upgrade_assistant/public/components/_index.scss deleted file mode 100644 index 8026031922301..0000000000000 --- a/x-pack/legacy/plugins/upgrade_assistant/public/components/_index.scss +++ /dev/null @@ -1,2 +0,0 @@ -@import './tabs/checkup/index'; -@import './tabs/overview/index'; diff --git a/x-pack/legacy/plugins/upgrade_assistant/public/components/tabs/checkup/_index.scss b/x-pack/legacy/plugins/upgrade_assistant/public/components/tabs/checkup/_index.scss deleted file mode 100644 index 430d1e0aedf7b..0000000000000 --- a/x-pack/legacy/plugins/upgrade_assistant/public/components/tabs/checkup/_index.scss +++ /dev/null @@ -1 +0,0 @@ -@import './deprecations/index'; diff --git a/x-pack/legacy/plugins/upgrade_assistant/public/components/tabs/checkup/deprecations/reindex/_index.scss b/x-pack/legacy/plugins/upgrade_assistant/public/components/tabs/checkup/deprecations/reindex/_index.scss deleted file mode 100644 index 2d52575cffbbb..0000000000000 --- a/x-pack/legacy/plugins/upgrade_assistant/public/components/tabs/checkup/deprecations/reindex/_index.scss +++ /dev/null @@ -1,2 +0,0 @@ -@import './button'; -@import './flyout/index'; diff --git a/x-pack/legacy/plugins/upgrade_assistant/public/components/tabs/checkup/deprecations/reindex/flyout/_index.scss b/x-pack/legacy/plugins/upgrade_assistant/public/components/tabs/checkup/deprecations/reindex/flyout/_index.scss deleted file mode 100644 index f695ae175feca..0000000000000 --- a/x-pack/legacy/plugins/upgrade_assistant/public/components/tabs/checkup/deprecations/reindex/flyout/_index.scss +++ /dev/null @@ -1,2 +0,0 @@ -@import './step_progress'; -@import './warnings_step'; diff --git a/x-pack/legacy/plugins/upgrade_assistant/public/components/tabs/overview/_index.scss b/x-pack/legacy/plugins/upgrade_assistant/public/components/tabs/overview/_index.scss deleted file mode 100644 index a6bbc6ba13298..0000000000000 --- a/x-pack/legacy/plugins/upgrade_assistant/public/components/tabs/overview/_index.scss +++ /dev/null @@ -1 +0,0 @@ -@import './steps'; \ No newline at end of file diff --git a/x-pack/legacy/plugins/upgrade_assistant/public/index.ts b/x-pack/legacy/plugins/upgrade_assistant/public/index.ts new file mode 100644 index 0000000000000..d22b5d64b6b46 --- /dev/null +++ b/x-pack/legacy/plugins/upgrade_assistant/public/index.ts @@ -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 * from './legacy'; diff --git a/x-pack/legacy/plugins/upgrade_assistant/public/index.tsx b/x-pack/legacy/plugins/upgrade_assistant/public/index.tsx deleted file mode 100644 index 2f631d3771ecb..0000000000000 --- a/x-pack/legacy/plugins/upgrade_assistant/public/index.tsx +++ /dev/null @@ -1,41 +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 { i18n } from '@kbn/i18n'; -import { wrapInI18nContext } from 'ui/i18n'; -// @ts-ignore -import { management } from 'ui/management'; -// @ts-ignore -import { uiModules } from 'ui/modules'; -// @ts-ignore -import routes from 'ui/routes'; -import { NEXT_MAJOR_VERSION } from '../common/version'; -import { RootComponent } from './app'; - -const BASE_PATH = `/management/elasticsearch/upgrade_assistant`; - -function startApp() { - management.getSection('elasticsearch').register('upgrade_assistant', { - visible: true, - display: i18n.translate('xpack.upgradeAssistant.appTitle', { - defaultMessage: '{version} Upgrade Assistant', - values: { version: `${NEXT_MAJOR_VERSION}.0` }, - }), - order: 100, - url: `#${BASE_PATH}`, - }); - - uiModules.get('kibana').directive('upgradeAssistant', (reactDirective: any) => { - return reactDirective(wrapInI18nContext(RootComponent)); - }); - - routes.when(`${BASE_PATH}/:view?`, { - template: - '', - }); -} - -startApp(); diff --git a/x-pack/legacy/plugins/upgrade_assistant/public/legacy.ts b/x-pack/legacy/plugins/upgrade_assistant/public/legacy.ts new file mode 100644 index 0000000000000..3d5144249dfef --- /dev/null +++ b/x-pack/legacy/plugins/upgrade_assistant/public/legacy.ts @@ -0,0 +1,105 @@ +/* + * 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 { ComponentType } from 'react'; +import { i18n } from '@kbn/i18n'; + +/* LEGACY IMPORTS */ +import { npSetup } from 'ui/new_platform'; +import { wrapInI18nContext } from 'ui/i18n'; +import { management } from 'ui/management'; +// @ts-ignore +import { uiModules } from 'ui/modules'; +import routes from 'ui/routes'; +import chrome from 'ui/chrome'; +/* LEGACY IMPORTS */ + +import { NEXT_MAJOR_VERSION } from '../common/version'; +import { plugin } from './np_ready'; + +const BASE_PATH = `/management/elasticsearch/upgrade_assistant`; + +export interface LegacyAppMountParameters { + __LEGACY: { renderToElement: (RootComponent: ComponentType) => void }; +} + +export interface LegacyApp { + mount(ctx: any, params: LegacyAppMountParameters): void; +} + +export interface LegacyManagementPlugin { + sections: { + get( + name: string + ): { + registerApp(app: LegacyApp): void; + }; + }; +} + +// Based on /rfcs/text/0006_management_section_service.md +export interface LegacyPlugins { + management: LegacyManagementPlugin; + __LEGACY: { + XSRF: string; + isCloudEnabled: boolean; + }; +} + +function startApp() { + routes.when(`${BASE_PATH}/:view?`, { + template: + '', + }); + + const legacyPluginsShim: LegacyPlugins = { + __LEGACY: { + XSRF: chrome.getXsrfToken(), + isCloudEnabled: chrome.getInjected('isCloudEnabled', false), + }, + management: { + sections: { + get(_: string) { + return { + registerApp(app) { + management.getSection('elasticsearch').register('upgrade_assistant', { + visible: true, + display: i18n.translate('xpack.upgradeAssistant.appTitle', { + defaultMessage: '{version} Upgrade Assistant', + values: { version: `${NEXT_MAJOR_VERSION}.0` }, + }), + order: 100, + url: `#${BASE_PATH}`, + }); + + app.mount( + {}, + { + __LEGACY: { + // While there is not an NP API for registering management section apps yet + renderToElement: RootComponent => { + uiModules + .get('kibana') + .directive('upgradeAssistant', (reactDirective: any) => { + return reactDirective(wrapInI18nContext(RootComponent)); + }); + }, + }, + } + ); + }, + }; + }, + }, + }, + }; + + const pluginInstance = plugin(); + + pluginInstance.setup(npSetup.core, legacyPluginsShim); +} + +startApp(); diff --git a/x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/app.tsx b/x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/app.tsx new file mode 100644 index 0000000000000..571967ab114c9 --- /dev/null +++ b/x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/app.tsx @@ -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 { EuiPageHeader, EuiPageHeaderSection, EuiTitle } from '@elastic/eui'; +import { FormattedMessage } from '@kbn/i18n/react'; +import { NEXT_MAJOR_VERSION } from '../../../common/version'; +import { UpgradeAssistantTabs } from './components/tabs'; +import { AppContextProvider, ContextValue, AppContext } from './app_context'; + +type AppDependencies = ContextValue; + +export const RootComponent = (deps: AppDependencies) => { + return ( + +
+ + + +

+ +

+
+
+
+ + {({ http }) => } + +
+
+ ); +}; diff --git a/x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/app_context.tsx b/x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/app_context.tsx new file mode 100644 index 0000000000000..a48a4efa3bbdf --- /dev/null +++ b/x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/app_context.tsx @@ -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 { HttpSetup } from 'src/core/public'; +import React, { createContext, useContext } from 'react'; + +export interface ContextValue { + http: HttpSetup; + isCloudEnabled: boolean; + XSRF: string; +} + +export const AppContext = createContext({} as any); + +export const AppContextProvider = ({ + children, + value, +}: { + children: React.ReactNode; + value: ContextValue; +}) => { + return {children}; +}; + +export const useAppContext = () => { + const ctx = useContext(AppContext); + if (!ctx) { + throw new Error('useAppContext must be called from inside AppContext'); + } + return ctx; +}; diff --git a/x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/_index.scss b/x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/_index.scss new file mode 100644 index 0000000000000..bb01107f334f6 --- /dev/null +++ b/x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/_index.scss @@ -0,0 +1,2 @@ +@import 'tabs/checkup/index'; +@import 'tabs/overview/index'; diff --git a/x-pack/legacy/plugins/upgrade_assistant/public/components/error_banner.tsx b/x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/error_banner.tsx similarity index 100% rename from x-pack/legacy/plugins/upgrade_assistant/public/components/error_banner.tsx rename to x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/error_banner.tsx diff --git a/x-pack/legacy/plugins/upgrade_assistant/public/components/latest_minor_banner.tsx b/x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/latest_minor_banner.tsx similarity index 98% rename from x-pack/legacy/plugins/upgrade_assistant/public/components/latest_minor_banner.tsx rename to x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/latest_minor_banner.tsx index 1f24377eba6cd..02f090565ebe6 100644 --- a/x-pack/legacy/plugins/upgrade_assistant/public/components/latest_minor_banner.tsx +++ b/x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/latest_minor_banner.tsx @@ -9,7 +9,7 @@ import React from 'react'; import { EuiCallOut, EuiLink } from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n/react'; -import { CURRENT_MAJOR_VERSION, NEXT_MAJOR_VERSION } from '../../common/version'; +import { CURRENT_MAJOR_VERSION, NEXT_MAJOR_VERSION } from '../../../../common/version'; export const LatestMinorBanner: React.StatelessComponent = () => ( ({ get: jest.fn(), create: jest.fn(), @@ -23,6 +21,13 @@ import { OverviewTab } from './tabs/overview'; // Used to wait for promises to resolve and renders to finish before reading updates const promisesToResolve = () => new Promise(resolve => setTimeout(resolve, 0)); +const mockHttp = { + basePath: { + prepend: () => 'test', + }, + fetch() {}, +}; + describe('UpgradeAssistantTabs', () => { test('renders loading state', async () => { // @ts-ignore @@ -31,7 +36,7 @@ describe('UpgradeAssistantTabs', () => { /* never resolve */ }) ); - const wrapper = mountWithIntl(); + const wrapper = mountWithIntl(); // Should pass down loading status to child component expect(wrapper.find(OverviewTab).prop('loadingState')).toEqual(LoadingState.Loading); }); @@ -44,7 +49,7 @@ describe('UpgradeAssistantTabs', () => { indices: [], }, }); - const wrapper = mountWithIntl(); + const wrapper = mountWithIntl(); expect(axios.get).toHaveBeenCalled(); await promisesToResolve(); wrapper.update(); @@ -55,7 +60,7 @@ describe('UpgradeAssistantTabs', () => { test('network failure', async () => { // @ts-ignore axios.get.mockRejectedValue(new Error(`oh no!`)); - const wrapper = mountWithIntl(); + const wrapper = mountWithIntl(); await promisesToResolve(); wrapper.update(); // Should pass down error status to child component @@ -65,7 +70,7 @@ describe('UpgradeAssistantTabs', () => { it('upgrade error', async () => { // @ts-ignore axios.get.mockRejectedValue({ response: { status: 426 } }); - const wrapper = mountWithIntl(); + const wrapper = mountWithIntl(); await promisesToResolve(); wrapper.update(); // Should display an informative message if the cluster is currently mid-upgrade diff --git a/x-pack/legacy/plugins/upgrade_assistant/public/components/tabs.tsx b/x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs.tsx similarity index 93% rename from x-pack/legacy/plugins/upgrade_assistant/public/components/tabs.tsx rename to x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs.tsx index 76cc1e33ca06b..0b154fb20404d 100644 --- a/x-pack/legacy/plugins/upgrade_assistant/public/components/tabs.tsx +++ b/x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs.tsx @@ -16,11 +16,9 @@ import { EuiTabbedContentTab, } from '@elastic/eui'; import { FormattedMessage, injectI18n } from '@kbn/i18n/react'; +import { HttpSetup } from 'src/core/public'; -import chrome from 'ui/chrome'; -import { kfetch } from 'ui/kfetch'; - -import { UpgradeAssistantStatus } from '../../server/lib/es_migration_apis'; +import { UpgradeAssistantStatus } from '../../../../server/np_ready/lib/es_migration_apis'; import { LatestMinorBanner } from './latest_minor_banner'; import { CheckupTab } from './tabs/checkup'; import { OverviewTab } from './tabs/overview'; @@ -41,13 +39,11 @@ interface TabsState { clusterUpgradeState: ClusterUpgradeState; } -export class UpgradeAssistantTabsUI extends React.Component< - ReactIntl.InjectedIntlProps, - TabsState -> { - constructor(props: ReactIntl.InjectedIntlProps) { - super(props); +type Props = ReactIntl.InjectedIntlProps & { http: HttpSetup }; +export class UpgradeAssistantTabsUI extends React.Component { + constructor(props: Props) { + super(props); this.state = { loadingState: LoadingState.Loading, clusterUpgradeState: ClusterUpgradeState.needsUpgrade, @@ -157,7 +153,9 @@ export class UpgradeAssistantTabsUI extends React.Component< private loadData = async () => { try { this.setState({ loadingState: LoadingState.Loading }); - const resp = await axios.get(chrome.addBasePath('/api/upgrade_assistant/status')); + const resp = await axios.get( + this.props.http.basePath.prepend('/api/upgrade_assistant/status') + ); this.setState({ loadingState: LoadingState.Success, checkupData: resp.data, @@ -246,8 +244,7 @@ export class UpgradeAssistantTabsUI extends React.Component< this.setState({ telemetryState: TelemetryState.Running }); - await kfetch({ - pathname: '/api/upgrade_assistant/telemetry/ui_open', + await this.props.http.fetch('/api/upgrade_assistant/telemetry/ui_open', { method: 'PUT', body: JSON.stringify(set({}, tabName, true)), }); diff --git a/x-pack/legacy/plugins/upgrade_assistant/public/components/tabs/__fixtures__/checkup_api_response.json b/x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/__fixtures__/checkup_api_response.json similarity index 100% rename from x-pack/legacy/plugins/upgrade_assistant/public/components/tabs/__fixtures__/checkup_api_response.json rename to x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/__fixtures__/checkup_api_response.json diff --git a/x-pack/legacy/plugins/upgrade_assistant/public/components/tabs/checkup/__snapshots__/checkup_tab.test.tsx.snap b/x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/checkup/__snapshots__/checkup_tab.test.tsx.snap similarity index 100% rename from x-pack/legacy/plugins/upgrade_assistant/public/components/tabs/checkup/__snapshots__/checkup_tab.test.tsx.snap rename to x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/checkup/__snapshots__/checkup_tab.test.tsx.snap diff --git a/x-pack/legacy/plugins/upgrade_assistant/public/components/tabs/checkup/__snapshots__/filter_bar.test.tsx.snap b/x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/checkup/__snapshots__/filter_bar.test.tsx.snap similarity index 100% rename from x-pack/legacy/plugins/upgrade_assistant/public/components/tabs/checkup/__snapshots__/filter_bar.test.tsx.snap rename to x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/checkup/__snapshots__/filter_bar.test.tsx.snap diff --git a/x-pack/legacy/plugins/upgrade_assistant/public/components/tabs/checkup/__snapshots__/group_by_bar.test.tsx.snap b/x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/checkup/__snapshots__/group_by_bar.test.tsx.snap similarity index 100% rename from x-pack/legacy/plugins/upgrade_assistant/public/components/tabs/checkup/__snapshots__/group_by_bar.test.tsx.snap rename to x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/checkup/__snapshots__/group_by_bar.test.tsx.snap diff --git a/x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/checkup/_index.scss b/x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/checkup/_index.scss new file mode 100644 index 0000000000000..d64400a8abdcf --- /dev/null +++ b/x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/checkup/_index.scss @@ -0,0 +1 @@ +@import 'deprecations/index'; diff --git a/x-pack/legacy/plugins/upgrade_assistant/public/components/tabs/checkup/checkup_tab.test.tsx b/x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/checkup/checkup_tab.test.tsx similarity index 98% rename from x-pack/legacy/plugins/upgrade_assistant/public/components/tabs/checkup/checkup_tab.test.tsx rename to x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/checkup/checkup_tab.test.tsx index 1805cb49e6ee6..9ba5441604ddc 100644 --- a/x-pack/legacy/plugins/upgrade_assistant/public/components/tabs/checkup/checkup_tab.test.tsx +++ b/x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/checkup/checkup_tab.test.tsx @@ -11,8 +11,6 @@ import { LoadingState } from '../../types'; import AssistanceData from '../__fixtures__/checkup_api_response.json'; import { CheckupTab } from './checkup_tab'; -jest.mock('ui/kfetch'); - const defaultProps = { checkupLabel: 'index', deprecations: AssistanceData.indices, diff --git a/x-pack/legacy/plugins/upgrade_assistant/public/components/tabs/checkup/checkup_tab.tsx b/x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/checkup/checkup_tab.tsx similarity index 99% rename from x-pack/legacy/plugins/upgrade_assistant/public/components/tabs/checkup/checkup_tab.tsx rename to x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/checkup/checkup_tab.tsx index 5b8fd21f9c1fc..9aa40663125ae 100644 --- a/x-pack/legacy/plugins/upgrade_assistant/public/components/tabs/checkup/checkup_tab.tsx +++ b/x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/checkup/checkup_tab.tsx @@ -20,7 +20,7 @@ import { } from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n/react'; -import { NEXT_MAJOR_VERSION } from '../../../../common/version'; +import { NEXT_MAJOR_VERSION } from '../../../../../../common/version'; import { LoadingErrorBanner } from '../../error_banner'; import { GroupByOption, diff --git a/x-pack/legacy/plugins/upgrade_assistant/public/components/tabs/checkup/constants.tsx b/x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/checkup/constants.tsx similarity index 100% rename from x-pack/legacy/plugins/upgrade_assistant/public/components/tabs/checkup/constants.tsx rename to x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/checkup/constants.tsx diff --git a/x-pack/legacy/plugins/upgrade_assistant/public/components/tabs/checkup/controls.tsx b/x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/checkup/controls.tsx similarity index 100% rename from x-pack/legacy/plugins/upgrade_assistant/public/components/tabs/checkup/controls.tsx rename to x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/checkup/controls.tsx diff --git a/x-pack/legacy/plugins/upgrade_assistant/public/components/tabs/checkup/deprecations/_cell.scss b/x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/checkup/deprecations/_cell.scss similarity index 100% rename from x-pack/legacy/plugins/upgrade_assistant/public/components/tabs/checkup/deprecations/_cell.scss rename to x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/checkup/deprecations/_cell.scss diff --git a/x-pack/legacy/plugins/upgrade_assistant/public/components/tabs/checkup/deprecations/_index.scss b/x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/checkup/deprecations/_deprecations.scss similarity index 88% rename from x-pack/legacy/plugins/upgrade_assistant/public/components/tabs/checkup/deprecations/_index.scss rename to x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/checkup/deprecations/_deprecations.scss index e370aeac0dfa2..445ef6269afb9 100644 --- a/x-pack/legacy/plugins/upgrade_assistant/public/components/tabs/checkup/deprecations/_index.scss +++ b/x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/checkup/deprecations/_deprecations.scss @@ -1,6 +1,3 @@ -@import './cell'; -@import './reindex/index'; - .upgDeprecations { // Pull the container through the padding of EuiPageContent margin-left: -$euiSizeL; diff --git a/x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/checkup/deprecations/_index.scss b/x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/checkup/deprecations/_index.scss new file mode 100644 index 0000000000000..55aff6b379db5 --- /dev/null +++ b/x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/checkup/deprecations/_index.scss @@ -0,0 +1,3 @@ +@import 'cell'; +@import 'deprecations'; +@import 'reindex/index'; diff --git a/x-pack/legacy/plugins/upgrade_assistant/public/components/tabs/checkup/deprecations/cell.tsx b/x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/checkup/deprecations/cell.tsx similarity index 89% rename from x-pack/legacy/plugins/upgrade_assistant/public/components/tabs/checkup/deprecations/cell.tsx rename to x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/checkup/deprecations/cell.tsx index 29a0076d00d0e..98672eb249c9b 100644 --- a/x-pack/legacy/plugins/upgrade_assistant/public/components/tabs/checkup/deprecations/cell.tsx +++ b/x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/checkup/deprecations/cell.tsx @@ -17,6 +17,7 @@ import { } from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n/react'; import { ReindexButton } from './reindex'; +import { AppContext } from '../../../../app_context'; interface DeprecationCellProps { items?: Array<{ title?: string; body: string }>; @@ -77,7 +78,11 @@ export const DeprecationCell: StatelessComponent = ({ {reindexIndexName && ( - + + {({ http, XSRF }) => ( + + )} + )} diff --git a/x-pack/legacy/plugins/upgrade_assistant/public/components/tabs/checkup/deprecations/count_summary.tsx b/x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/checkup/deprecations/count_summary.tsx similarity index 93% rename from x-pack/legacy/plugins/upgrade_assistant/public/components/tabs/checkup/deprecations/count_summary.tsx rename to x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/checkup/deprecations/count_summary.tsx index a66244b0e7886..d3166292822d7 100644 --- a/x-pack/legacy/plugins/upgrade_assistant/public/components/tabs/checkup/deprecations/count_summary.tsx +++ b/x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/checkup/deprecations/count_summary.tsx @@ -8,7 +8,7 @@ import React, { Fragment, StatelessComponent } from 'react'; import { EuiText } from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n/react'; -import { EnrichedDeprecationInfo } from '../../../../../server/lib/es_migration_apis'; +import { EnrichedDeprecationInfo } from '../../../../../../../server/np_ready/lib/es_migration_apis'; export const DeprecationCountSummary: StatelessComponent<{ deprecations: EnrichedDeprecationInfo[]; diff --git a/x-pack/legacy/plugins/upgrade_assistant/public/components/tabs/checkup/deprecations/grouped.test.tsx b/x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/checkup/deprecations/grouped.test.tsx similarity index 98% rename from x-pack/legacy/plugins/upgrade_assistant/public/components/tabs/checkup/deprecations/grouped.test.tsx rename to x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/checkup/deprecations/grouped.test.tsx index 6c541742a539b..28f5f6894b78f 100644 --- a/x-pack/legacy/plugins/upgrade_assistant/public/components/tabs/checkup/deprecations/grouped.test.tsx +++ b/x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/checkup/deprecations/grouped.test.tsx @@ -11,12 +11,10 @@ import { mountWithIntl, shallowWithIntl } from 'test_utils/enzyme_helpers'; import { EuiBadge, EuiPagination } from '@elastic/eui'; import { DeprecationInfo } from 'src/legacy/core_plugins/elasticsearch'; -import { EnrichedDeprecationInfo } from '../../../../../server/lib/es_migration_apis'; +import { EnrichedDeprecationInfo } from '../../../../../../../server/np_ready/lib/es_migration_apis'; import { GroupByOption, LevelFilterOption } from '../../../types'; import { DeprecationAccordion, filterDeps, GroupedDeprecations } from './grouped'; -jest.mock('ui/kfetch'); - describe('filterDeps', () => { test('filters on levels', () => { const fd = filterDeps(LevelFilterOption.critical); diff --git a/x-pack/legacy/plugins/upgrade_assistant/public/components/tabs/checkup/deprecations/grouped.tsx b/x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/checkup/deprecations/grouped.tsx similarity index 98% rename from x-pack/legacy/plugins/upgrade_assistant/public/components/tabs/checkup/deprecations/grouped.tsx rename to x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/checkup/deprecations/grouped.tsx index 9ce0b8a8cefd3..9f53c96bce5c6 100644 --- a/x-pack/legacy/plugins/upgrade_assistant/public/components/tabs/checkup/deprecations/grouped.tsx +++ b/x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/checkup/deprecations/grouped.tsx @@ -19,7 +19,7 @@ import { import { FormattedMessage } from '@kbn/i18n/react'; import { DeprecationInfo } from 'src/legacy/core_plugins/elasticsearch'; -import { EnrichedDeprecationInfo } from '../../../../../server/lib/es_migration_apis'; +import { EnrichedDeprecationInfo } from '../../../../../../../server/np_ready/lib/es_migration_apis'; import { GroupByOption, LevelFilterOption } from '../../../types'; import { DeprecationCountSummary } from './count_summary'; diff --git a/x-pack/legacy/plugins/upgrade_assistant/public/components/tabs/checkup/deprecations/health.tsx b/x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/checkup/deprecations/health.tsx similarity index 100% rename from x-pack/legacy/plugins/upgrade_assistant/public/components/tabs/checkup/deprecations/health.tsx rename to x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/checkup/deprecations/health.tsx diff --git a/x-pack/legacy/plugins/upgrade_assistant/public/components/tabs/checkup/deprecations/index.tsx b/x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/checkup/deprecations/index.tsx similarity index 100% rename from x-pack/legacy/plugins/upgrade_assistant/public/components/tabs/checkup/deprecations/index.tsx rename to x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/checkup/deprecations/index.tsx diff --git a/x-pack/legacy/plugins/upgrade_assistant/public/components/tabs/checkup/deprecations/index_table.test.tsx b/x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/checkup/deprecations/index_table.test.tsx similarity index 98% rename from x-pack/legacy/plugins/upgrade_assistant/public/components/tabs/checkup/deprecations/index_table.test.tsx rename to x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/checkup/deprecations/index_table.test.tsx index 040459309f728..8c211704c7aff 100644 --- a/x-pack/legacy/plugins/upgrade_assistant/public/components/tabs/checkup/deprecations/index_table.test.tsx +++ b/x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/checkup/deprecations/index_table.test.tsx @@ -9,8 +9,6 @@ import { shallowWithIntl } from 'test_utils/enzyme_helpers'; import { IndexDeprecationTableProps, IndexDeprecationTableUI } from './index_table'; -jest.mock('ui/kfetch'); - describe('IndexDeprecationTable', () => { const defaultProps = { indices: [ diff --git a/x-pack/legacy/plugins/upgrade_assistant/public/components/tabs/checkup/deprecations/index_table.tsx b/x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/checkup/deprecations/index_table.tsx similarity index 92% rename from x-pack/legacy/plugins/upgrade_assistant/public/components/tabs/checkup/deprecations/index_table.tsx rename to x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/checkup/deprecations/index_table.tsx index 5a1deb59c270e..eba906edc0509 100644 --- a/x-pack/legacy/plugins/upgrade_assistant/public/components/tabs/checkup/deprecations/index_table.tsx +++ b/x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/checkup/deprecations/index_table.tsx @@ -10,6 +10,7 @@ import React from 'react'; import { EuiBasicTable } from '@elastic/eui'; import { injectI18n } from '@kbn/i18n/react'; import { ReindexButton } from './reindex'; +import { AppContext } from '../../../../app_context'; const PAGE_SIZES = [10, 25, 50, 100, 250, 500, 1000]; @@ -143,7 +144,13 @@ export class IndexDeprecationTableUI extends React.Component< actions: [ { render(indexDep: IndexDeprecationDetails) { - return ; + return ( + + {({ XSRF, http }) => ( + + )} + + ); }, }, ], diff --git a/x-pack/legacy/plugins/upgrade_assistant/public/components/tabs/checkup/deprecations/list.test.tsx b/x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/checkup/deprecations/list.test.tsx similarity index 96% rename from x-pack/legacy/plugins/upgrade_assistant/public/components/tabs/checkup/deprecations/list.test.tsx rename to x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/checkup/deprecations/list.test.tsx index 6be89f411f580..78ded73593464 100644 --- a/x-pack/legacy/plugins/upgrade_assistant/public/components/tabs/checkup/deprecations/list.test.tsx +++ b/x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/checkup/deprecations/list.test.tsx @@ -7,12 +7,10 @@ import { shallow } from 'enzyme'; import React from 'react'; -import { EnrichedDeprecationInfo } from '../../../../../server/lib/es_migration_apis'; +import { EnrichedDeprecationInfo } from '../../../../../../../server/np_ready/lib/es_migration_apis'; import { GroupByOption } from '../../../types'; import { DeprecationList } from './list'; -jest.mock('ui/kfetch'); - describe('DeprecationList', () => { describe('group by message', () => { const defaultProps = { diff --git a/x-pack/legacy/plugins/upgrade_assistant/public/components/tabs/checkup/deprecations/list.tsx b/x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/checkup/deprecations/list.tsx similarity index 97% rename from x-pack/legacy/plugins/upgrade_assistant/public/components/tabs/checkup/deprecations/list.tsx rename to x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/checkup/deprecations/list.tsx index cb38b848b3bd7..256a0580c7617 100644 --- a/x-pack/legacy/plugins/upgrade_assistant/public/components/tabs/checkup/deprecations/list.tsx +++ b/x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/checkup/deprecations/list.tsx @@ -7,7 +7,7 @@ import React, { StatelessComponent } from 'react'; import { DeprecationInfo } from 'src/legacy/core_plugins/elasticsearch'; -import { EnrichedDeprecationInfo } from '../../../../../server/lib/es_migration_apis'; +import { EnrichedDeprecationInfo } from '../../../../../../../server/np_ready/lib/es_migration_apis'; import { GroupByOption } from '../../../types'; import { COLOR_MAP, LEVEL_MAP } from '../constants'; diff --git a/x-pack/legacy/plugins/upgrade_assistant/public/components/tabs/checkup/deprecations/reindex/_button.scss b/x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/checkup/deprecations/reindex/_button.scss similarity index 100% rename from x-pack/legacy/plugins/upgrade_assistant/public/components/tabs/checkup/deprecations/reindex/_button.scss rename to x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/checkup/deprecations/reindex/_button.scss diff --git a/x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/checkup/deprecations/reindex/_index.scss b/x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/checkup/deprecations/reindex/_index.scss new file mode 100644 index 0000000000000..014edc96b0565 --- /dev/null +++ b/x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/checkup/deprecations/reindex/_index.scss @@ -0,0 +1,2 @@ +@import 'button'; +@import 'flyout/index'; diff --git a/x-pack/legacy/plugins/upgrade_assistant/public/components/tabs/checkup/deprecations/reindex/button.tsx b/x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/checkup/deprecations/reindex/button.tsx similarity index 95% rename from x-pack/legacy/plugins/upgrade_assistant/public/components/tabs/checkup/deprecations/reindex/button.tsx rename to x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/checkup/deprecations/reindex/button.tsx index 6addd3dae642a..2a28018a3ae81 100644 --- a/x-pack/legacy/plugins/upgrade_assistant/public/components/tabs/checkup/deprecations/reindex/button.tsx +++ b/x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/checkup/deprecations/reindex/button.tsx @@ -10,14 +10,16 @@ import { Subscription } from 'rxjs'; import { EuiButton, EuiLoadingSpinner } from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n/react'; -import { kfetch } from 'ui/kfetch'; -import { ReindexStatus, UIReindexOption } from '../../../../../../common/types'; +import { HttpSetup } from 'src/core/public'; +import { ReindexStatus, UIReindexOption } from '../../../../../../../../common/types'; import { LoadingState } from '../../../../types'; import { ReindexFlyout } from './flyout'; import { ReindexPollingService, ReindexState } from './polling_service'; interface ReindexButtonProps { indexName: string; + xsrf: string; + http: HttpSetup; } interface ReindexButtonState { @@ -152,7 +154,8 @@ export class ReindexButton extends React.Component { diff --git a/x-pack/legacy/plugins/upgrade_assistant/public/components/tabs/checkup/deprecations/reindex/flyout/warnings_step.tsx b/x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/checkup/deprecations/reindex/flyout/warnings_step.tsx similarity index 99% rename from x-pack/legacy/plugins/upgrade_assistant/public/components/tabs/checkup/deprecations/reindex/flyout/warnings_step.tsx rename to x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/checkup/deprecations/reindex/flyout/warnings_step.tsx index 1465812c4803d..b6e577d913cac 100644 --- a/x-pack/legacy/plugins/upgrade_assistant/public/components/tabs/checkup/deprecations/reindex/flyout/warnings_step.tsx +++ b/x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/checkup/deprecations/reindex/flyout/warnings_step.tsx @@ -21,7 +21,7 @@ import { EuiText, } from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n/react'; -import { ReindexWarning } from '../../../../../../../common/types'; +import { ReindexWarning } from '../../../../../../../../../common/types'; interface CheckedIds { [id: string]: boolean; diff --git a/x-pack/legacy/plugins/upgrade_assistant/public/components/tabs/checkup/deprecations/reindex/index.tsx b/x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/checkup/deprecations/reindex/index.tsx similarity index 100% rename from x-pack/legacy/plugins/upgrade_assistant/public/components/tabs/checkup/deprecations/reindex/index.tsx rename to x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/checkup/deprecations/reindex/index.tsx diff --git a/x-pack/legacy/plugins/upgrade_assistant/public/components/tabs/checkup/deprecations/reindex/polling_service.test.mocks.ts b/x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/checkup/deprecations/reindex/polling_service.test.mocks.ts similarity index 87% rename from x-pack/legacy/plugins/upgrade_assistant/public/components/tabs/checkup/deprecations/reindex/polling_service.test.mocks.ts rename to x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/checkup/deprecations/reindex/polling_service.test.mocks.ts index f70822aef102c..dc7a758839fe5 100644 --- a/x-pack/legacy/plugins/upgrade_assistant/public/components/tabs/checkup/deprecations/reindex/polling_service.test.mocks.ts +++ b/x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/checkup/deprecations/reindex/polling_service.test.mocks.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { ReindexStatus, ReindexStep } from '../../../../../../common/types'; +import { ReindexStatus, ReindexStep } from '../../../../../../../../common/types'; export const mockClient = { post: jest.fn().mockResolvedValue({ diff --git a/x-pack/legacy/plugins/upgrade_assistant/public/components/tabs/checkup/deprecations/reindex/polling_service.test.ts b/x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/checkup/deprecations/reindex/polling_service.test.ts similarity index 75% rename from x-pack/legacy/plugins/upgrade_assistant/public/components/tabs/checkup/deprecations/reindex/polling_service.test.ts rename to x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/checkup/deprecations/reindex/polling_service.test.ts index 9f47f51bc8cde..cb2a0856f0f2e 100644 --- a/x-pack/legacy/plugins/upgrade_assistant/public/components/tabs/checkup/deprecations/reindex/polling_service.test.ts +++ b/x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/checkup/deprecations/reindex/polling_service.test.ts @@ -6,8 +6,9 @@ import { mockClient } from './polling_service.test.mocks'; -import { ReindexStatus, ReindexStep } from '../../../../../../common/types'; +import { ReindexStatus, ReindexStep } from '../../../../../../../../common/types'; import { ReindexPollingService } from './polling_service'; +import { httpServiceMock } from 'src/core/public/http/http_service.mock'; describe('ReindexPollingService', () => { beforeEach(() => { @@ -24,7 +25,11 @@ describe('ReindexPollingService', () => { }, }); - const service = new ReindexPollingService('myIndex'); + const service = new ReindexPollingService( + 'myIndex', + 'myXsrf', + httpServiceMock.createSetupContract() + ); service.updateStatus(); await new Promise(resolve => setTimeout(resolve, 1200)); // wait for poll interval @@ -45,7 +50,11 @@ describe('ReindexPollingService', () => { }, }); - const service = new ReindexPollingService('myIndex'); + const service = new ReindexPollingService( + 'myIndex', + 'myXsrf', + httpServiceMock.createSetupContract() + ); service.updateStatus(); await new Promise(resolve => setTimeout(resolve, 1200)); // wait for poll interval @@ -66,7 +75,11 @@ describe('ReindexPollingService', () => { }, }); - const service = new ReindexPollingService('myIndex'); + const service = new ReindexPollingService( + 'myIndex', + 'myXsrf', + httpServiceMock.createSetupContract() + ); service.updateStatus(); await new Promise(resolve => setTimeout(resolve, 1200)); // wait for poll interval @@ -76,7 +89,11 @@ describe('ReindexPollingService', () => { describe('startReindex', () => { it('posts to endpoint', async () => { - const service = new ReindexPollingService('myIndex'); + const service = new ReindexPollingService( + 'myIndex', + 'myXsrf', + httpServiceMock.createSetupContract() + ); await service.startReindex(); expect(mockClient.post).toHaveBeenCalledWith('/api/upgrade_assistant/reindex/myIndex'); @@ -85,7 +102,11 @@ describe('ReindexPollingService', () => { describe('cancelReindex', () => { it('posts to cancel endpoint', async () => { - const service = new ReindexPollingService('myIndex'); + const service = new ReindexPollingService( + 'myIndex', + 'myXsrf', + httpServiceMock.createSetupContract() + ); await service.cancelReindex(); expect(mockClient.post).toHaveBeenCalledWith('/api/upgrade_assistant/reindex/myIndex/cancel'); diff --git a/x-pack/legacy/plugins/upgrade_assistant/public/components/tabs/checkup/deprecations/reindex/polling_service.ts b/x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/checkup/deprecations/reindex/polling_service.ts similarity index 82% rename from x-pack/legacy/plugins/upgrade_assistant/public/components/tabs/checkup/deprecations/reindex/polling_service.ts rename to x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/checkup/deprecations/reindex/polling_service.ts index 3977a169f4aca..879fafe610982 100644 --- a/x-pack/legacy/plugins/upgrade_assistant/public/components/tabs/checkup/deprecations/reindex/polling_service.ts +++ b/x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/checkup/deprecations/reindex/polling_service.ts @@ -3,31 +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 axios from 'axios'; -import chrome from 'ui/chrome'; +import axios, { AxiosInstance } from 'axios'; import { BehaviorSubject } from 'rxjs'; + +import { HttpSetup } from 'src/core/public'; import { IndexGroup, ReindexOperation, ReindexStatus, ReindexStep, ReindexWarning, -} from '../../../../../../common/types'; +} from '../../../../../../../../common/types'; import { LoadingState } from '../../../../types'; const POLL_INTERVAL = 1000; -const XSRF = chrome.getXsrfToken(); - -export const APIClient = axios.create({ - headers: { - Accept: 'application/json', - credentials: 'same-origin', - 'Content-Type': 'application/json', - 'kbn-version': XSRF, - 'kbn-xsrf': XSRF, - }, -}); export interface ReindexState { loadingState: LoadingState; @@ -55,13 +45,24 @@ interface StatusResponse { export class ReindexPollingService { public status$: BehaviorSubject; private pollTimeout?: NodeJS.Timeout; + private APIClient: AxiosInstance; - constructor(private indexName: string) { + constructor(private indexName: string, private xsrf: string, private http: HttpSetup) { this.status$ = new BehaviorSubject({ loadingState: LoadingState.Loading, errorMessage: null, reindexTaskPercComplete: null, }); + + this.APIClient = axios.create({ + headers: { + Accept: 'application/json', + credentials: 'same-origin', + 'Content-Type': 'application/json', + 'kbn-version': this.xsrf, + 'kbn-xsrf': this.xsrf, + }, + }); } public updateStatus = async () => { @@ -69,8 +70,8 @@ export class ReindexPollingService { this.stopPolling(); try { - const { data } = await APIClient.get( - chrome.addBasePath(`/api/upgrade_assistant/reindex/${this.indexName}`) + const { data } = await this.APIClient.get( + this.http.basePath.prepend(`/api/upgrade_assistant/reindex/${this.indexName}`) ); this.updateWithResponse(data); @@ -106,8 +107,8 @@ export class ReindexPollingService { errorMessage: null, cancelLoadingState: undefined, }); - const { data } = await APIClient.post( - chrome.addBasePath(`/api/upgrade_assistant/reindex/${this.indexName}`) + const { data } = await this.APIClient.post( + this.http.basePath.prepend(`/api/upgrade_assistant/reindex/${this.indexName}`) ); this.updateWithResponse({ reindexOp: data }); @@ -124,8 +125,8 @@ export class ReindexPollingService { cancelLoadingState: LoadingState.Loading, }); - await APIClient.post( - chrome.addBasePath(`/api/upgrade_assistant/reindex/${this.indexName}/cancel`) + await this.APIClient.post( + this.http.basePath.prepend(`/api/upgrade_assistant/reindex/${this.indexName}/cancel`) ); } catch (e) { this.status$.next({ diff --git a/x-pack/legacy/plugins/upgrade_assistant/public/components/tabs/checkup/filter_bar.test.tsx b/x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/checkup/filter_bar.test.tsx similarity index 100% rename from x-pack/legacy/plugins/upgrade_assistant/public/components/tabs/checkup/filter_bar.test.tsx rename to x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/checkup/filter_bar.test.tsx diff --git a/x-pack/legacy/plugins/upgrade_assistant/public/components/tabs/checkup/filter_bar.tsx b/x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/checkup/filter_bar.tsx similarity index 100% rename from x-pack/legacy/plugins/upgrade_assistant/public/components/tabs/checkup/filter_bar.tsx rename to x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/checkup/filter_bar.tsx diff --git a/x-pack/legacy/plugins/upgrade_assistant/public/components/tabs/checkup/group_by_bar.test.tsx b/x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/checkup/group_by_bar.test.tsx similarity index 100% rename from x-pack/legacy/plugins/upgrade_assistant/public/components/tabs/checkup/group_by_bar.test.tsx rename to x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/checkup/group_by_bar.test.tsx diff --git a/x-pack/legacy/plugins/upgrade_assistant/public/components/tabs/checkup/group_by_bar.tsx b/x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/checkup/group_by_bar.tsx similarity index 100% rename from x-pack/legacy/plugins/upgrade_assistant/public/components/tabs/checkup/group_by_bar.tsx rename to x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/checkup/group_by_bar.tsx diff --git a/x-pack/legacy/plugins/upgrade_assistant/public/components/tabs/checkup/index.tsx b/x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/checkup/index.tsx similarity index 100% rename from x-pack/legacy/plugins/upgrade_assistant/public/components/tabs/checkup/index.tsx rename to x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/checkup/index.tsx diff --git a/x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/overview/_index.scss b/x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/overview/_index.scss new file mode 100644 index 0000000000000..c64a8f5a5326d --- /dev/null +++ b/x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/overview/_index.scss @@ -0,0 +1 @@ +@import 'steps'; diff --git a/x-pack/legacy/plugins/upgrade_assistant/public/components/tabs/overview/_steps.scss b/x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/overview/_steps.scss similarity index 100% rename from x-pack/legacy/plugins/upgrade_assistant/public/components/tabs/overview/_steps.scss rename to x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/overview/_steps.scss diff --git a/x-pack/legacy/plugins/upgrade_assistant/public/components/tabs/overview/deprecation_logging_toggle.tsx b/x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/overview/deprecation_logging_toggle.tsx similarity index 87% rename from x-pack/legacy/plugins/upgrade_assistant/public/components/tabs/overview/deprecation_logging_toggle.tsx rename to x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/overview/deprecation_logging_toggle.tsx index 8d107331eb65f..97eb284c7b771 100644 --- a/x-pack/legacy/plugins/upgrade_assistant/public/components/tabs/overview/deprecation_logging_toggle.tsx +++ b/x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/overview/deprecation_logging_toggle.tsx @@ -10,19 +10,25 @@ import React from 'react'; import { EuiLoadingSpinner, EuiSwitch } from '@elastic/eui'; import { injectI18n } from '@kbn/i18n/react'; -import chrome from 'ui/chrome'; +import { HttpSetup } from 'src/core/public'; + import { LoadingState } from '../../types'; +interface DeprecationLoggingTabProps extends ReactIntl.InjectedIntlProps { + xsrf: string; + http: HttpSetup; +} + interface DeprecationLoggingTabState { loadingState: LoadingState; loggingEnabled?: boolean; } export class DeprecationLoggingToggleUI extends React.Component< - ReactIntl.InjectedIntlProps, + DeprecationLoggingTabProps, DeprecationLoggingTabState > { - constructor(props: ReactIntl.InjectedIntlProps) { + constructor(props: DeprecationLoggingTabProps) { super(props); this.state = { @@ -83,7 +89,7 @@ export class DeprecationLoggingToggleUI extends React.Component< try { this.setState({ loadingState: LoadingState.Loading }); const resp = await axios.get( - chrome.addBasePath('/api/upgrade_assistant/deprecation_logging') + this.props.http.basePath.prepend('/api/upgrade_assistant/deprecation_logging') ); this.setState({ loadingState: LoadingState.Success, @@ -96,18 +102,19 @@ export class DeprecationLoggingToggleUI extends React.Component< private toggleLogging = async () => { try { + const { http, xsrf } = this.props; // Optimistically toggle the UI const newEnabled = !this.state.loggingEnabled; this.setState({ loadingState: LoadingState.Loading, loggingEnabled: newEnabled }); const resp = await axios.put( - chrome.addBasePath('/api/upgrade_assistant/deprecation_logging'), + http.basePath.prepend('/api/upgrade_assistant/deprecation_logging'), { isEnabled: newEnabled, }, { headers: { - 'kbn-xsrf': chrome.getXsrfToken(), + 'kbn-xsrf': xsrf, }, } ); diff --git a/x-pack/legacy/plugins/upgrade_assistant/public/components/tabs/overview/index.tsx b/x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/overview/index.tsx similarity index 96% rename from x-pack/legacy/plugins/upgrade_assistant/public/components/tabs/overview/index.tsx rename to x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/overview/index.tsx index 834f5f4afe5f6..51968a9b864ae 100644 --- a/x-pack/legacy/plugins/upgrade_assistant/public/components/tabs/overview/index.tsx +++ b/x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/overview/index.tsx @@ -19,7 +19,7 @@ import { } from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n/react'; -import { NEXT_MAJOR_VERSION } from '../../../../common/version'; +import { NEXT_MAJOR_VERSION } from '../../../../../../common/version'; import { LoadingErrorBanner } from '../../error_banner'; import { LoadingState, UpgradeAssistantTabProps } from '../../types'; import { Steps } from './steps'; diff --git a/x-pack/legacy/plugins/upgrade_assistant/public/components/tabs/overview/steps.tsx b/x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/overview/steps.tsx similarity index 96% rename from x-pack/legacy/plugins/upgrade_assistant/public/components/tabs/overview/steps.tsx rename to x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/overview/steps.tsx index d43a86d2b0e06..d1e88ba8b4b0c 100644 --- a/x-pack/legacy/plugins/upgrade_assistant/public/components/tabs/overview/steps.tsx +++ b/x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/overview/steps.tsx @@ -18,11 +18,11 @@ import { } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import { FormattedMessage, injectI18n } from '@kbn/i18n/react'; -import chrome from 'ui/chrome'; -import { CURRENT_MAJOR_VERSION, NEXT_MAJOR_VERSION } from '../../../../common/version'; +import { CURRENT_MAJOR_VERSION, NEXT_MAJOR_VERSION } from '../../../../../../common/version'; import { UpgradeAssistantTabProps } from '../../types'; import { DeprecationLoggingToggle } from './deprecation_logging_toggle'; +import { useAppContext } from '../../../app_context'; // Leaving these here even if unused so they are picked up for i18n static analysis // Keep this until last minor release (when next major is also released). @@ -54,7 +54,7 @@ const WAIT_FOR_RELEASE_STEP = { // Swap in this step for the one above it on the last minor release. // @ts-ignore -const START_UPGRADE_STEP = { +const START_UPGRADE_STEP = (isCloudEnabled: boolean) => ({ title: i18n.translate('xpack.upgradeAssistant.overviewTab.steps.startUpgradeStep.stepTitle', { defaultMessage: 'Start your upgrade', }), @@ -62,7 +62,7 @@ const START_UPGRADE_STEP = {

- {chrome.getInjected('isCloudEnabled', false) ? ( + {isCloudEnabled ? ( ), -}; +}); export const StepsUI: StatelessComponent = ({ checkupData, setSelectedTabIndex, intl }) => { @@ -100,6 +100,9 @@ export const StepsUI: StatelessComponent - + ), @@ -264,6 +267,7 @@ export const StepsUI: StatelessComponent ); diff --git a/x-pack/legacy/plugins/upgrade_assistant/public/components/types.ts b/x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/types.ts similarity index 94% rename from x-pack/legacy/plugins/upgrade_assistant/public/components/types.ts rename to x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/types.ts index dc31308a1ea34..2d9a373f20b7e 100644 --- a/x-pack/legacy/plugins/upgrade_assistant/public/components/types.ts +++ b/x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/types.ts @@ -9,7 +9,7 @@ import React from 'react'; import { EnrichedDeprecationInfo, UpgradeAssistantStatus, -} from '../../server/lib/es_migration_apis'; +} from '../../../../server/np_ready/lib/es_migration_apis'; export interface UpgradeAssistantTabProps { alertBanner?: React.ReactNode; diff --git a/x-pack/legacy/plugins/upgrade_assistant/public/index.scss b/x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/index.scss similarity index 66% rename from x-pack/legacy/plugins/upgrade_assistant/public/index.scss rename to x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/index.scss index 999cca93fcd7a..6000af5498cd6 100644 --- a/x-pack/legacy/plugins/upgrade_assistant/public/index.scss +++ b/x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/index.scss @@ -1,3 +1,3 @@ @import 'src/legacy/ui/public/styles/_styling_constants'; -@import './components/index'; +@import 'components/index'; diff --git a/x-pack/legacy/plugins/upgrade_assistant/public/np_ready/index.ts b/x-pack/legacy/plugins/upgrade_assistant/public/np_ready/index.ts new file mode 100644 index 0000000000000..020d6972f8280 --- /dev/null +++ b/x-pack/legacy/plugins/upgrade_assistant/public/np_ready/index.ts @@ -0,0 +1,11 @@ +/* + * 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 { UpgradeAssistantUIPlugin } from './plugin'; + +export const plugin = () => { + return new UpgradeAssistantUIPlugin(); +}; diff --git a/x-pack/legacy/plugins/upgrade_assistant/public/np_ready/plugin.ts b/x-pack/legacy/plugins/upgrade_assistant/public/np_ready/plugin.ts new file mode 100644 index 0000000000000..16a0c9632fb25 --- /dev/null +++ b/x-pack/legacy/plugins/upgrade_assistant/public/np_ready/plugin.ts @@ -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 { Plugin, CoreSetup } from 'src/core/public'; +import { RootComponent } from './application/app'; +import { LegacyPlugins } from '../legacy'; + +export class UpgradeAssistantUIPlugin implements Plugin { + async setup( + { http }: CoreSetup, + { management, __LEGACY: { XSRF, isCloudEnabled } }: LegacyPlugins + ) { + const appRegistrar = management.sections.get('kibana'); + return appRegistrar.registerApp({ + mount(__, { __LEGACY: { renderToElement } }) { + return renderToElement(() => RootComponent({ http, XSRF, isCloudEnabled })); + }, + }); + } + async start() {} + async stop() {} +} diff --git a/x-pack/legacy/plugins/upgrade_assistant/server/index.ts b/x-pack/legacy/plugins/upgrade_assistant/server/index.ts index 5fcdbe136a4f2..8b0704283509d 100644 --- a/x-pack/legacy/plugins/upgrade_assistant/server/index.ts +++ b/x-pack/legacy/plugins/upgrade_assistant/server/index.ts @@ -4,31 +4,4 @@ * you may not use this file except in compliance with the Elastic License. */ -import { Legacy } from 'kibana'; -import { UpgradeAssistantTelemetryServer } from '../common/types'; -import { credentialStoreFactory } from './lib/reindexing/credential_store'; -import { makeUpgradeAssistantUsageCollector } from './lib/telemetry'; -import { registerClusterCheckupRoutes } from './routes/cluster_checkup'; -import { registerDeprecationLoggingRoutes } from './routes/deprecation_logging'; -import { registerReindexIndicesRoutes, registerReindexWorker } from './routes/reindex_indices'; -import { registerTelemetryRoutes } from './routes/telemetry'; - -export function initServer(server: Legacy.Server) { - registerClusterCheckupRoutes(server); - registerDeprecationLoggingRoutes(server); - - // The ReindexWorker uses a map of request headers that contain the authentication credentials - // for a given reindex. We cannot currently store these in an the .kibana index b/c we do not - // want to expose these credentials to any unauthenticated users. We also want to avoid any need - // to add a user for a special index just for upgrading. This in-memory cache allows us to - // process jobs without the browser staying on the page, but will require that jobs go into - // a paused state if no Kibana nodes have the required credentials. - const credentialStore = credentialStoreFactory(); - - const worker = registerReindexWorker(server, credentialStore); - registerReindexIndicesRoutes(server, worker, credentialStore); - - // Bootstrap the needed routes and the collector for the telemetry - registerTelemetryRoutes(server as UpgradeAssistantTelemetryServer); - makeUpgradeAssistantUsageCollector(server as UpgradeAssistantTelemetryServer); -} +export { plugin } from './np_ready'; diff --git a/x-pack/legacy/plugins/upgrade_assistant/server/lib/es_version_precheck.test.ts b/x-pack/legacy/plugins/upgrade_assistant/server/lib/es_version_precheck.test.ts deleted file mode 100644 index 9a0fca6d4139c..0000000000000 --- a/x-pack/legacy/plugins/upgrade_assistant/server/lib/es_version_precheck.test.ts +++ /dev/null @@ -1,125 +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 { SemVer } from 'semver'; -import { CURRENT_VERSION } from '../../common/version'; -import { - EsVersionPrecheck, - getAllNodeVersions, - verifyAllMatchKibanaVersion, -} from './es_version_precheck'; - -describe('getAllNodeVersions', () => { - it('returns a list of unique node versions', async () => { - const callCluster = jest.fn().mockResolvedValue({ - nodes: { - node1: { version: '7.0.0' }, - node2: { version: '7.0.0' }, - node3: { version: '6.0.0' }, - }, - }); - - await expect(getAllNodeVersions(callCluster)).resolves.toEqual([ - new SemVer('6.0.0'), - new SemVer('7.0.0'), - ]); - }); -}); - -describe('verifyAllMatchKibanaVersion', () => { - it('throws if any are higher version', () => { - expect(() => - verifyAllMatchKibanaVersion([new SemVer('99999.0.0')]) - ).toThrowErrorMatchingInlineSnapshot( - `"There are some nodes running a different version of Elasticsearch"` - ); - }); - - it('throws if any are lower version', () => { - expect(() => - verifyAllMatchKibanaVersion([new SemVer('0.0.0')]) - ).toThrowErrorMatchingInlineSnapshot( - `"There are some nodes running a different version of Elasticsearch"` - ); - }); - - it('does not throw if all are same major', () => { - const versions = [ - CURRENT_VERSION, - CURRENT_VERSION.inc('minor'), - CURRENT_VERSION.inc('minor').inc('minor'), - ]; - - expect(() => verifyAllMatchKibanaVersion(versions)).not.toThrow(); - }); -}); - -describe('EsVersionPrecheck', () => { - it('throws a 403 when callCluster fails with a 403', async () => { - const fakeCallWithRequest = jest.fn().mockRejectedValue({ status: 403 }); - const fakeGetCluster = jest.fn(() => ({ callWithRequest: fakeCallWithRequest })); - const fakeRequest = { - server: { plugins: { elasticsearch: { getCluster: fakeGetCluster } } }, - } as any; - - await expect(EsVersionPrecheck.method(fakeRequest, {} as any)).rejects.toHaveProperty( - 'output.statusCode', - 403 - ); - }); - - it('throws a 426 message w/ allNodesUpgraded = false when nodes are not on same version', async () => { - const fakeCallWithRequest = jest.fn().mockResolvedValue({ - nodes: { - node1: { version: CURRENT_VERSION.raw }, - node2: { version: new SemVer(CURRENT_VERSION.raw).inc('major').raw }, - }, - }); - const fakeGetCluster = jest.fn(() => ({ callWithRequest: fakeCallWithRequest })); - const fakeRequest = { - server: { plugins: { elasticsearch: { getCluster: fakeGetCluster } } }, - } as any; - - const result = EsVersionPrecheck.method(fakeRequest, {} as any); - await expect(result).rejects.toHaveProperty('output.statusCode', 426); - await expect(result).rejects.toHaveProperty( - 'output.payload.attributes.allNodesUpgraded', - false - ); - }); - - it('throws a 426 message w/ allNodesUpgraded = true when nodes are on next version', async () => { - const fakeCallWithRequest = jest.fn().mockResolvedValue({ - nodes: { - node1: { version: new SemVer(CURRENT_VERSION.raw).inc('major').raw }, - node2: { version: new SemVer(CURRENT_VERSION.raw).inc('major').raw }, - }, - }); - const fakeGetCluster = jest.fn(() => ({ callWithRequest: fakeCallWithRequest })); - const fakeRequest = { - server: { plugins: { elasticsearch: { getCluster: fakeGetCluster } } }, - } as any; - - const result = EsVersionPrecheck.method(fakeRequest, {} as any); - await expect(result).rejects.toHaveProperty('output.statusCode', 426); - await expect(result).rejects.toHaveProperty('output.payload.attributes.allNodesUpgraded', true); - }); - - it('returns true when nodes are on same version', async () => { - const fakeCallWithRequest = jest.fn().mockResolvedValue({ - nodes: { - node1: { version: CURRENT_VERSION.raw }, - node2: { version: CURRENT_VERSION.raw }, - }, - }); - const fakeGetCluster = jest.fn(() => ({ callWithRequest: fakeCallWithRequest })); - const fakeRequest = { - server: { plugins: { elasticsearch: { getCluster: fakeGetCluster } } }, - } as any; - - await expect(EsVersionPrecheck.method(fakeRequest, {} as any)).resolves.toBe(true); - }); -}); diff --git a/x-pack/legacy/plugins/upgrade_assistant/server/lib/es_version_precheck.ts b/x-pack/legacy/plugins/upgrade_assistant/server/lib/es_version_precheck.ts deleted file mode 100644 index d84d5f5444472..0000000000000 --- a/x-pack/legacy/plugins/upgrade_assistant/server/lib/es_version_precheck.ts +++ /dev/null @@ -1,75 +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 Boom from 'boom'; -import { Request, RouteOptionsPreObject } from 'hapi'; -import { uniq } from 'lodash'; -import { SemVer } from 'semver'; - -import { CallCluster } from 'src/legacy/core_plugins/elasticsearch'; -import { CURRENT_VERSION } from '../../common/version'; - -/** - * Returns an array of all the unique Elasticsearch Node Versions in the Elasticsearch cluster. - * @param request - */ -export const getAllNodeVersions = async (callCluster: CallCluster) => { - // Get the version information for all nodes in the cluster. - const { nodes } = (await callCluster('nodes.info', { - filterPath: 'nodes.*.version', - })) as { nodes: { [nodeId: string]: { version: string } } }; - - const versionStrings = Object.values(nodes).map(({ version }) => version); - - return uniq(versionStrings) - .sort() - .map(version => new SemVer(version)); -}; - -export const verifyAllMatchKibanaVersion = (allNodeVersions: SemVer[]) => { - // Determine if all nodes in the cluster are running the same major version as Kibana. - const numDifferentVersion = allNodeVersions.filter( - esNodeVersion => esNodeVersion.major !== CURRENT_VERSION.major - ).length; - const numSameVersion = allNodeVersions.filter( - esNodeVersion => esNodeVersion.major === CURRENT_VERSION.major - ).length; - - if (numDifferentVersion) { - const error = new Boom(`There are some nodes running a different version of Elasticsearch`, { - // 426 means "Upgrade Required" and is used when semver compatibility is not met. - statusCode: 426, - }); - - error.output.payload.attributes = { allNodesUpgraded: !numSameVersion }; - throw error; - } -}; - -export const EsVersionPrecheck = { - assign: 'esVersionCheck', - async method(request: Request) { - const { callWithRequest } = request.server.plugins.elasticsearch.getCluster('admin'); - const callCluster = callWithRequest.bind(callWithRequest, request) as CallCluster; - - let allNodeVersions: SemVer[]; - - try { - allNodeVersions = await getAllNodeVersions(callCluster); - } catch (e) { - if (e.status === 403) { - throw Boom.forbidden(e.message); - } - - throw e; - } - - // This will throw if there is an issue - verifyAllMatchKibanaVersion(allNodeVersions); - - return true; - }, -} as RouteOptionsPreObject; diff --git a/x-pack/legacy/plugins/upgrade_assistant/server/np_ready/index.ts b/x-pack/legacy/plugins/upgrade_assistant/server/np_ready/index.ts new file mode 100644 index 0000000000000..cf1b78e1e3920 --- /dev/null +++ b/x-pack/legacy/plugins/upgrade_assistant/server/np_ready/index.ts @@ -0,0 +1,11 @@ +/* + * 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 { PluginInitializerContext } from 'src/core/server'; +import { UpgradeAssistantServerPlugin } from './plugin'; + +export const plugin = (ctx: PluginInitializerContext) => { + return new UpgradeAssistantServerPlugin(); +}; diff --git a/x-pack/legacy/plugins/upgrade_assistant/server/lib/__fixtures__/fake_deprecations.json b/x-pack/legacy/plugins/upgrade_assistant/server/np_ready/lib/__fixtures__/fake_deprecations.json similarity index 100% rename from x-pack/legacy/plugins/upgrade_assistant/server/lib/__fixtures__/fake_deprecations.json rename to x-pack/legacy/plugins/upgrade_assistant/server/np_ready/lib/__fixtures__/fake_deprecations.json diff --git a/x-pack/legacy/plugins/upgrade_assistant/server/lib/__mocks__/es_version_precheck.ts b/x-pack/legacy/plugins/upgrade_assistant/server/np_ready/lib/__mocks__/es_version_precheck.ts similarity index 100% rename from x-pack/legacy/plugins/upgrade_assistant/server/lib/__mocks__/es_version_precheck.ts rename to x-pack/legacy/plugins/upgrade_assistant/server/np_ready/lib/__mocks__/es_version_precheck.ts diff --git a/x-pack/legacy/plugins/upgrade_assistant/server/lib/__snapshots__/es_migration_apis.test.ts.snap b/x-pack/legacy/plugins/upgrade_assistant/server/np_ready/lib/__snapshots__/es_migration_apis.test.ts.snap similarity index 100% rename from x-pack/legacy/plugins/upgrade_assistant/server/lib/__snapshots__/es_migration_apis.test.ts.snap rename to x-pack/legacy/plugins/upgrade_assistant/server/np_ready/lib/__snapshots__/es_migration_apis.test.ts.snap diff --git a/x-pack/legacy/plugins/upgrade_assistant/server/lib/es_deprecation_logging_apis.test.ts b/x-pack/legacy/plugins/upgrade_assistant/server/np_ready/lib/es_deprecation_logging_apis.test.ts similarity index 100% rename from x-pack/legacy/plugins/upgrade_assistant/server/lib/es_deprecation_logging_apis.test.ts rename to x-pack/legacy/plugins/upgrade_assistant/server/np_ready/lib/es_deprecation_logging_apis.test.ts diff --git a/x-pack/legacy/plugins/upgrade_assistant/server/lib/es_deprecation_logging_apis.ts b/x-pack/legacy/plugins/upgrade_assistant/server/np_ready/lib/es_deprecation_logging_apis.ts similarity index 94% rename from x-pack/legacy/plugins/upgrade_assistant/server/lib/es_deprecation_logging_apis.ts rename to x-pack/legacy/plugins/upgrade_assistant/server/np_ready/lib/es_deprecation_logging_apis.ts index 2cf0a8f5020fd..199d389408442 100644 --- a/x-pack/legacy/plugins/upgrade_assistant/server/lib/es_deprecation_logging_apis.ts +++ b/x-pack/legacy/plugins/upgrade_assistant/server/np_ready/lib/es_deprecation_logging_apis.ts @@ -5,8 +5,8 @@ */ import { get } from 'lodash'; -import { Legacy } from 'kibana'; import { CallClusterWithRequest } from 'src/legacy/core_plugins/elasticsearch'; +import { RequestShim } from '../types'; interface DeprecationLoggingStatus { isEnabled: boolean; @@ -14,7 +14,7 @@ interface DeprecationLoggingStatus { export async function getDeprecationLoggingStatus( callWithRequest: CallClusterWithRequest, - req: Legacy.Request + req: RequestShim ): Promise { const response = await callWithRequest(req, 'cluster.getSettings', { includeDefaults: true, @@ -27,7 +27,7 @@ export async function getDeprecationLoggingStatus( export async function setDeprecationLogging( callWithRequest: CallClusterWithRequest, - req: Legacy.Request, + req: RequestShim, isEnabled: boolean ): Promise { const response = await callWithRequest(req, 'cluster.putSettings', { diff --git a/x-pack/legacy/plugins/upgrade_assistant/server/lib/es_migration_apis.test.ts b/x-pack/legacy/plugins/upgrade_assistant/server/np_ready/lib/es_migration_apis.test.ts similarity index 100% rename from x-pack/legacy/plugins/upgrade_assistant/server/lib/es_migration_apis.test.ts rename to x-pack/legacy/plugins/upgrade_assistant/server/np_ready/lib/es_migration_apis.test.ts diff --git a/x-pack/legacy/plugins/upgrade_assistant/server/lib/es_migration_apis.ts b/x-pack/legacy/plugins/upgrade_assistant/server/np_ready/lib/es_migration_apis.ts similarity index 96% rename from x-pack/legacy/plugins/upgrade_assistant/server/lib/es_migration_apis.ts rename to x-pack/legacy/plugins/upgrade_assistant/server/np_ready/lib/es_migration_apis.ts index 8ed85d19c411a..b52c4c374266f 100644 --- a/x-pack/legacy/plugins/upgrade_assistant/server/lib/es_migration_apis.ts +++ b/x-pack/legacy/plugins/upgrade_assistant/server/np_ready/lib/es_migration_apis.ts @@ -4,15 +4,14 @@ * you may not use this file except in compliance with the Elastic License. */ -import _ from 'lodash'; - -import { Request } from 'hapi'; import { CallClusterWithRequest, DeprecationAPIResponse, DeprecationInfo, } from 'src/legacy/core_plugins/elasticsearch'; +import { RequestShim } from '../types'; + export interface EnrichedDeprecationInfo extends DeprecationInfo { index?: string; node?: string; @@ -27,7 +26,7 @@ export interface UpgradeAssistantStatus { export async function getUpgradeAssistantStatus( callWithRequest: CallClusterWithRequest, - req: Request, + req: RequestShim, isCloudEnabled: boolean ): Promise { const deprecations = await callWithRequest(req, 'transport.request', { diff --git a/x-pack/legacy/plugins/upgrade_assistant/server/np_ready/lib/es_version_precheck.test.ts b/x-pack/legacy/plugins/upgrade_assistant/server/np_ready/lib/es_version_precheck.test.ts new file mode 100644 index 0000000000000..bbabe557df4d4 --- /dev/null +++ b/x-pack/legacy/plugins/upgrade_assistant/server/np_ready/lib/es_version_precheck.test.ts @@ -0,0 +1,151 @@ +/* + * 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 { SemVer } from 'semver'; +import { IScopedClusterClient, kibanaResponseFactory } from 'src/core/server'; +import { CURRENT_VERSION } from '../../../common/version'; +import { + esVersionCheck, + getAllNodeVersions, + verifyAllMatchKibanaVersion, +} from './es_version_precheck'; + +describe('getAllNodeVersions', () => { + it('returns a list of unique node versions', async () => { + const adminClient = ({ + callAsInternalUser: jest.fn().mockResolvedValue({ + nodes: { + node1: { version: '7.0.0' }, + node2: { version: '7.0.0' }, + node3: { version: '6.0.0' }, + }, + }), + } as unknown) as IScopedClusterClient; + + await expect(getAllNodeVersions(adminClient)).resolves.toEqual([ + new SemVer('6.0.0'), + new SemVer('7.0.0'), + ]); + }); +}); + +describe('verifyAllMatchKibanaVersion', () => { + it('detects higher version nodes', () => { + const result = verifyAllMatchKibanaVersion([new SemVer('99999.0.0')]); + expect(result.allNodesMatch).toBe(false); + expect(result.allNodesUpgraded).toBe(true); + }); + + it('detects lower version nodes', () => { + const result = verifyAllMatchKibanaVersion([new SemVer('0.0.0')]); + expect(result.allNodesMatch).toBe(false); + expect(result.allNodesUpgraded).toBe(true); + }); + + it('detects if all are on same major correctly', () => { + const versions = [ + CURRENT_VERSION, + CURRENT_VERSION.inc('minor'), + CURRENT_VERSION.inc('minor').inc('minor'), + ]; + + const result = verifyAllMatchKibanaVersion(versions); + expect(result.allNodesMatch).toBe(true); + expect(result.allNodesUpgraded).toBe(false); + }); + + it('detects partial matches', () => { + const versions = [ + new SemVer('0.0.0'), + CURRENT_VERSION.inc('minor'), + CURRENT_VERSION.inc('minor').inc('minor'), + ]; + + const result = verifyAllMatchKibanaVersion(versions); + expect(result.allNodesMatch).toBe(false); + expect(result.allNodesUpgraded).toBe(false); + }); +}); + +describe('EsVersionPrecheck', () => { + it('returns a 403 when callCluster fails with a 403', async () => { + const fakeCall = jest.fn().mockRejectedValue({ status: 403 }); + + const ctx = { + core: { + elasticsearch: { + adminClient: { + callAsInternalUser: fakeCall, + }, + }, + }, + } as any; + + const result = await esVersionCheck(ctx, kibanaResponseFactory); + expect(result).toHaveProperty('status', 403); + }); + + it('returns a 426 message w/ allNodesUpgraded = false when nodes are not on same version', async () => { + const ctx = { + core: { + elasticsearch: { + adminClient: { + callAsInternalUser: jest.fn().mockResolvedValue({ + nodes: { + node1: { version: CURRENT_VERSION.raw }, + node2: { version: new SemVer(CURRENT_VERSION.raw).inc('major').raw }, + }, + }), + }, + }, + }, + } as any; + + const result = await esVersionCheck(ctx, kibanaResponseFactory); + expect(result).toHaveProperty('status', 426); + expect(result).toHaveProperty('payload.attributes.allNodesUpgraded', false); + }); + + it('returns a 426 message w/ allNodesUpgraded = true when nodes are on next version', async () => { + const ctx = { + core: { + elasticsearch: { + adminClient: { + callAsInternalUser: jest.fn().mockResolvedValue({ + nodes: { + node1: { version: new SemVer(CURRENT_VERSION.raw).inc('major').raw }, + node2: { version: new SemVer(CURRENT_VERSION.raw).inc('major').raw }, + }, + }), + }, + }, + }, + } as any; + + const result = await esVersionCheck(ctx, kibanaResponseFactory); + expect(result).toHaveProperty('status', 426); + expect(result).toHaveProperty('payload.attributes.allNodesUpgraded', true); + }); + + it('returns undefined when nodes are on same version', async () => { + const ctx = { + core: { + elasticsearch: { + adminClient: { + callAsInternalUser: jest.fn().mockResolvedValue({ + nodes: { + node1: { version: CURRENT_VERSION.raw }, + node2: { version: CURRENT_VERSION.raw }, + }, + }), + }, + }, + }, + } as any; + + await expect(esVersionCheck(ctx, kibanaResponseFactory)).resolves.toBe(undefined); + }); +}); diff --git a/x-pack/legacy/plugins/upgrade_assistant/server/np_ready/lib/es_version_precheck.ts b/x-pack/legacy/plugins/upgrade_assistant/server/np_ready/lib/es_version_precheck.ts new file mode 100644 index 0000000000000..2fb3effe43793 --- /dev/null +++ b/x-pack/legacy/plugins/upgrade_assistant/server/np_ready/lib/es_version_precheck.ts @@ -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 { uniq } from 'lodash'; +import { SemVer } from 'semver'; +import { + IScopedClusterClient, + KibanaRequest, + KibanaResponseFactory, + RequestHandler, + RequestHandlerContext, +} from 'src/core/server'; +import { CURRENT_VERSION } from '../../../common/version'; + +/** + * Returns an array of all the unique Elasticsearch Node Versions in the Elasticsearch cluster. + */ +export const getAllNodeVersions = async (adminClient: IScopedClusterClient) => { + // Get the version information for all nodes in the cluster. + const { nodes } = (await adminClient.callAsInternalUser('nodes.info', { + filterPath: 'nodes.*.version', + })) as { nodes: { [nodeId: string]: { version: string } } }; + + const versionStrings = Object.values(nodes).map(({ version }) => version); + + return uniq(versionStrings) + .sort() + .map(version => new SemVer(version)); +}; + +export const verifyAllMatchKibanaVersion = (allNodeVersions: SemVer[]) => { + // Determine if all nodes in the cluster are running the same major version as Kibana. + const numDifferentVersion = allNodeVersions.filter( + esNodeVersion => esNodeVersion.major !== CURRENT_VERSION.major + ).length; + + const numSameVersion = allNodeVersions.filter( + esNodeVersion => esNodeVersion.major === CURRENT_VERSION.major + ).length; + + if (numDifferentVersion) { + return { + allNodesMatch: false, + // If Kibana is talking to nodes and none have the same major version as Kibana, they must a be of + // a higher major version. + allNodesUpgraded: numSameVersion === 0, + }; + } + return { + allNodesMatch: true, + allNodesUpgraded: false, + }; +}; + +/** + * This is intended as controller/handler level code so it knows about HTTP + */ +export const esVersionCheck = async ( + ctx: RequestHandlerContext, + response: KibanaResponseFactory +) => { + const { adminClient } = ctx.core.elasticsearch; + let allNodeVersions: SemVer[]; + + try { + allNodeVersions = await getAllNodeVersions(adminClient); + } catch (e) { + if (e.status === 403) { + return response.forbidden({ body: e.message }); + } + + throw e; + } + + const result = verifyAllMatchKibanaVersion(allNodeVersions); + if (!result.allNodesMatch) { + return response.customError({ + // 426 means "Upgrade Required" and is used when semver compatibility is not met. + statusCode: 426, + body: { + message: 'There are some nodes running a different version of Elasticsearch', + attributes: { + allNodesUpgraded: result.allNodesUpgraded, + }, + }, + }); + } +}; + +export const versionCheckHandlerWrapper = (handler: RequestHandler) => async ( + ctx: RequestHandlerContext, + request: KibanaRequest, + response: KibanaResponseFactory +) => { + const errorResponse = await esVersionCheck(ctx, response); + if (errorResponse) { + return errorResponse; + } + return handler(ctx, request, response); +}; diff --git a/x-pack/legacy/plugins/upgrade_assistant/server/lib/reindexing/credential_store.test.ts b/x-pack/legacy/plugins/upgrade_assistant/server/np_ready/lib/reindexing/credential_store.test.ts similarity index 95% rename from x-pack/legacy/plugins/upgrade_assistant/server/lib/reindexing/credential_store.test.ts rename to x-pack/legacy/plugins/upgrade_assistant/server/np_ready/lib/reindexing/credential_store.test.ts index ce892df0de946..06fa755472238 100644 --- a/x-pack/legacy/plugins/upgrade_assistant/server/lib/reindexing/credential_store.test.ts +++ b/x-pack/legacy/plugins/upgrade_assistant/server/np_ready/lib/reindexing/credential_store.test.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { ReindexSavedObject } from '../../../common/types'; +import { ReindexSavedObject } from '../../../../common/types'; import { Credential, credentialStoreFactory } from './credential_store'; describe('credentialStore', () => { diff --git a/x-pack/legacy/plugins/upgrade_assistant/server/lib/reindexing/credential_store.ts b/x-pack/legacy/plugins/upgrade_assistant/server/np_ready/lib/reindexing/credential_store.ts similarity index 96% rename from x-pack/legacy/plugins/upgrade_assistant/server/lib/reindexing/credential_store.ts rename to x-pack/legacy/plugins/upgrade_assistant/server/np_ready/lib/reindexing/credential_store.ts index 32f5ec9977b72..a051d16b5779f 100644 --- a/x-pack/legacy/plugins/upgrade_assistant/server/lib/reindexing/credential_store.ts +++ b/x-pack/legacy/plugins/upgrade_assistant/server/np_ready/lib/reindexing/credential_store.ts @@ -8,7 +8,7 @@ import { createHash } from 'crypto'; import { Request } from 'hapi'; import stringify from 'json-stable-stringify'; -import { ReindexSavedObject } from '../../../common/types'; +import { ReindexSavedObject } from '../../../../common/types'; export type Credential = Request['headers']; diff --git a/x-pack/legacy/plugins/upgrade_assistant/server/lib/reindexing/index.ts b/x-pack/legacy/plugins/upgrade_assistant/server/np_ready/lib/reindexing/index.ts similarity index 100% rename from x-pack/legacy/plugins/upgrade_assistant/server/lib/reindexing/index.ts rename to x-pack/legacy/plugins/upgrade_assistant/server/np_ready/lib/reindexing/index.ts diff --git a/x-pack/legacy/plugins/upgrade_assistant/server/lib/reindexing/index_settings.test.ts b/x-pack/legacy/plugins/upgrade_assistant/server/np_ready/lib/reindexing/index_settings.test.ts similarity index 99% rename from x-pack/legacy/plugins/upgrade_assistant/server/lib/reindexing/index_settings.test.ts rename to x-pack/legacy/plugins/upgrade_assistant/server/np_ready/lib/reindexing/index_settings.test.ts index 9ec06b72f02e2..7b346cc87edf6 100644 --- a/x-pack/legacy/plugins/upgrade_assistant/server/lib/reindexing/index_settings.test.ts +++ b/x-pack/legacy/plugins/upgrade_assistant/server/np_ready/lib/reindexing/index_settings.test.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { CURRENT_MAJOR_VERSION, PREV_MAJOR_VERSION } from '../../../common/version'; +import { CURRENT_MAJOR_VERSION, PREV_MAJOR_VERSION } from '../../../../common/version'; import { generateNewIndexName, getReindexWarnings, diff --git a/x-pack/legacy/plugins/upgrade_assistant/server/lib/reindexing/index_settings.ts b/x-pack/legacy/plugins/upgrade_assistant/server/np_ready/lib/reindexing/index_settings.ts similarity index 97% rename from x-pack/legacy/plugins/upgrade_assistant/server/lib/reindexing/index_settings.ts rename to x-pack/legacy/plugins/upgrade_assistant/server/np_ready/lib/reindexing/index_settings.ts index f6dc471d0945d..0b95bc628fbb4 100644 --- a/x-pack/legacy/plugins/upgrade_assistant/server/lib/reindexing/index_settings.ts +++ b/x-pack/legacy/plugins/upgrade_assistant/server/np_ready/lib/reindexing/index_settings.ts @@ -5,8 +5,8 @@ */ import { flow, omit } from 'lodash'; -import { ReindexWarning } from '../../../common/types'; -import { CURRENT_MAJOR_VERSION, PREV_MAJOR_VERSION } from '../../../common/version'; +import { ReindexWarning } from '../../../../common/types'; +import { CURRENT_MAJOR_VERSION, PREV_MAJOR_VERSION } from '../../../../common/version'; import { FlatSettings } from './types'; export interface ParsedIndexName { diff --git a/x-pack/legacy/plugins/upgrade_assistant/server/lib/reindexing/reindex_actions.test.ts b/x-pack/legacy/plugins/upgrade_assistant/server/np_ready/lib/reindexing/reindex_actions.test.ts similarity index 99% rename from x-pack/legacy/plugins/upgrade_assistant/server/lib/reindexing/reindex_actions.test.ts rename to x-pack/legacy/plugins/upgrade_assistant/server/np_ready/lib/reindexing/reindex_actions.test.ts index 4569fdfa33a83..3fb855958a5d0 100644 --- a/x-pack/legacy/plugins/upgrade_assistant/server/lib/reindexing/reindex_actions.test.ts +++ b/x-pack/legacy/plugins/upgrade_assistant/server/np_ready/lib/reindexing/reindex_actions.test.ts @@ -13,8 +13,8 @@ import { ReindexSavedObject, ReindexStatus, ReindexStep, -} from '../../../common/types'; -import { CURRENT_MAJOR_VERSION, PREV_MAJOR_VERSION } from '../../../common/version'; +} from '../../../../common/types'; +import { CURRENT_MAJOR_VERSION, PREV_MAJOR_VERSION } from '../../../../common/version'; import { LOCK_WINDOW, ReindexActions, reindexActionsFactory } from './reindex_actions'; describe('ReindexActions', () => { diff --git a/x-pack/legacy/plugins/upgrade_assistant/server/lib/reindexing/reindex_actions.ts b/x-pack/legacy/plugins/upgrade_assistant/server/np_ready/lib/reindexing/reindex_actions.ts similarity index 99% rename from x-pack/legacy/plugins/upgrade_assistant/server/lib/reindexing/reindex_actions.ts rename to x-pack/legacy/plugins/upgrade_assistant/server/np_ready/lib/reindexing/reindex_actions.ts index a162186ff0059..6683f80c8e779 100644 --- a/x-pack/legacy/plugins/upgrade_assistant/server/lib/reindexing/reindex_actions.ts +++ b/x-pack/legacy/plugins/upgrade_assistant/server/np_ready/lib/reindexing/reindex_actions.ts @@ -7,7 +7,7 @@ import moment from 'moment'; import { CallCluster } from 'src/legacy/core_plugins/elasticsearch'; -import { SavedObjectsFindResponse, SavedObjectsClientContract } from 'src/core/server'; +import { SavedObjectsFindResponse, SavedObjectsClientContract } from 'kibana/server'; import { IndexGroup, REINDEX_OP_TYPE, @@ -15,7 +15,7 @@ import { ReindexSavedObject, ReindexStatus, ReindexStep, -} from '../../../common/types'; +} from '../../../../common/types'; import { generateNewIndexName } from './index_settings'; import { FlatSettings } from './types'; diff --git a/x-pack/legacy/plugins/upgrade_assistant/server/lib/reindexing/reindex_service.test.ts b/x-pack/legacy/plugins/upgrade_assistant/server/np_ready/lib/reindexing/reindex_service.test.ts similarity index 99% rename from x-pack/legacy/plugins/upgrade_assistant/server/lib/reindexing/reindex_service.test.ts rename to x-pack/legacy/plugins/upgrade_assistant/server/np_ready/lib/reindexing/reindex_service.test.ts index 1216a8d2c4c24..9cd41c8cbe826 100644 --- a/x-pack/legacy/plugins/upgrade_assistant/server/lib/reindexing/reindex_service.test.ts +++ b/x-pack/legacy/plugins/upgrade_assistant/server/np_ready/lib/reindexing/reindex_service.test.ts @@ -10,8 +10,8 @@ import { ReindexSavedObject, ReindexStatus, ReindexStep, -} from '../../../common/types'; -import { CURRENT_MAJOR_VERSION, PREV_MAJOR_VERSION } from '../../../common/version'; +} from '../../../../common/types'; +import { CURRENT_MAJOR_VERSION, PREV_MAJOR_VERSION } from '../../../../common/version'; import { isMlIndex, isWatcherIndex, diff --git a/x-pack/legacy/plugins/upgrade_assistant/server/lib/reindexing/reindex_service.ts b/x-pack/legacy/plugins/upgrade_assistant/server/np_ready/lib/reindexing/reindex_service.ts similarity index 99% rename from x-pack/legacy/plugins/upgrade_assistant/server/lib/reindexing/reindex_service.ts rename to x-pack/legacy/plugins/upgrade_assistant/server/np_ready/lib/reindexing/reindex_service.ts index 41a4552b722de..0e6095f98b6ff 100644 --- a/x-pack/legacy/plugins/upgrade_assistant/server/lib/reindexing/reindex_service.ts +++ b/x-pack/legacy/plugins/upgrade_assistant/server/np_ready/lib/reindexing/reindex_service.ts @@ -8,14 +8,14 @@ import Boom from 'boom'; import { Server } from 'hapi'; import { CallCluster } from 'src/legacy/core_plugins/elasticsearch'; -import { XPackInfo } from '../../../../xpack_main/server/lib/xpack_info'; +import { XPackInfo } from '../../../../../xpack_main/server/lib/xpack_info'; import { IndexGroup, ReindexSavedObject, ReindexStatus, ReindexStep, ReindexWarning, -} from '../../../common/types'; +} from '../../../../common/types'; import { generateNewIndexName, getReindexWarnings, diff --git a/x-pack/legacy/plugins/upgrade_assistant/server/lib/reindexing/types.ts b/x-pack/legacy/plugins/upgrade_assistant/server/np_ready/lib/reindexing/types.ts similarity index 100% rename from x-pack/legacy/plugins/upgrade_assistant/server/lib/reindexing/types.ts rename to x-pack/legacy/plugins/upgrade_assistant/server/np_ready/lib/reindexing/types.ts diff --git a/x-pack/legacy/plugins/upgrade_assistant/server/lib/reindexing/worker.ts b/x-pack/legacy/plugins/upgrade_assistant/server/np_ready/lib/reindexing/worker.ts similarity index 97% rename from x-pack/legacy/plugins/upgrade_assistant/server/lib/reindexing/worker.ts rename to x-pack/legacy/plugins/upgrade_assistant/server/np_ready/lib/reindexing/worker.ts index 669eea623851c..628a47be9f5e7 100644 --- a/x-pack/legacy/plugins/upgrade_assistant/server/lib/reindexing/worker.ts +++ b/x-pack/legacy/plugins/upgrade_assistant/server/np_ready/lib/reindexing/worker.ts @@ -5,11 +5,11 @@ */ import { CallCluster, CallClusterWithRequest } from 'src/legacy/core_plugins/elasticsearch'; import { Request, Server } from 'src/legacy/server/kbn_server'; -import { SavedObjectsClientContract } from 'src/core/server'; +import { SavedObjectsClientContract } from 'kibana/server'; import moment from 'moment'; -import { XPackInfo } from '../../../../xpack_main/server/lib/xpack_info'; -import { ReindexSavedObject, ReindexStatus } from '../../../common/types'; +import { XPackInfo } from '../../../../../xpack_main/server/lib/xpack_info'; +import { ReindexSavedObject, ReindexStatus } from '../../../../common/types'; import { CredentialStore } from './credential_store'; import { reindexActionsFactory } from './reindex_actions'; import { ReindexService, reindexServiceFactory } from './reindex_service'; diff --git a/x-pack/legacy/plugins/upgrade_assistant/server/lib/telemetry/es_ui_open_apis.test.ts b/x-pack/legacy/plugins/upgrade_assistant/server/np_ready/lib/telemetry/es_ui_open_apis.test.ts similarity index 98% rename from x-pack/legacy/plugins/upgrade_assistant/server/lib/telemetry/es_ui_open_apis.test.ts rename to x-pack/legacy/plugins/upgrade_assistant/server/np_ready/lib/telemetry/es_ui_open_apis.test.ts index 94df444e2c1bb..4c378ba25430e 100644 --- a/x-pack/legacy/plugins/upgrade_assistant/server/lib/telemetry/es_ui_open_apis.test.ts +++ b/x-pack/legacy/plugins/upgrade_assistant/server/np_ready/lib/telemetry/es_ui_open_apis.test.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { UPGRADE_ASSISTANT_DOC_ID, UPGRADE_ASSISTANT_TYPE } from '../../../common/types'; +import { UPGRADE_ASSISTANT_DOC_ID, UPGRADE_ASSISTANT_TYPE } from '../../../../common/types'; import { upsertUIOpenOption } from './es_ui_open_apis'; /** diff --git a/x-pack/legacy/plugins/upgrade_assistant/server/lib/telemetry/es_ui_open_apis.ts b/x-pack/legacy/plugins/upgrade_assistant/server/np_ready/lib/telemetry/es_ui_open_apis.ts similarity index 75% rename from x-pack/legacy/plugins/upgrade_assistant/server/lib/telemetry/es_ui_open_apis.ts rename to x-pack/legacy/plugins/upgrade_assistant/server/np_ready/lib/telemetry/es_ui_open_apis.ts index 7036dcc4ea1a7..b52b3b812b7f9 100644 --- a/x-pack/legacy/plugins/upgrade_assistant/server/lib/telemetry/es_ui_open_apis.ts +++ b/x-pack/legacy/plugins/upgrade_assistant/server/np_ready/lib/telemetry/es_ui_open_apis.ts @@ -4,19 +4,15 @@ * you may not use this file except in compliance with the Elastic License. */ -import { Legacy } from 'kibana'; import { UIOpen, UIOpenOption, UPGRADE_ASSISTANT_DOC_ID, UPGRADE_ASSISTANT_TYPE, - UpgradeAssistantTelemetryServer, -} from '../../../common/types'; +} from '../../../../common/types'; +import { RequestShim, ServerShim } from '../../types'; -async function incrementUIOpenOptionCounter( - server: UpgradeAssistantTelemetryServer, - uiOpenOptionCounter: UIOpenOption -) { +async function incrementUIOpenOptionCounter(server: ServerShim, uiOpenOptionCounter: UIOpenOption) { const { getSavedObjectsRepository } = server.savedObjects; const { callWithInternalUser } = server.plugins.elasticsearch.getCluster('admin'); const internalRepository = getSavedObjectsRepository(callWithInternalUser); @@ -28,10 +24,7 @@ async function incrementUIOpenOptionCounter( ); } -export async function upsertUIOpenOption( - server: UpgradeAssistantTelemetryServer, - req: Legacy.Request -): Promise { +export async function upsertUIOpenOption(server: ServerShim, req: RequestShim): Promise { const { overview, cluster, indices } = req.payload as UIOpen; if (overview) { diff --git a/x-pack/legacy/plugins/upgrade_assistant/server/lib/telemetry/es_ui_reindex_apis.test.ts b/x-pack/legacy/plugins/upgrade_assistant/server/np_ready/lib/telemetry/es_ui_reindex_apis.test.ts similarity index 98% rename from x-pack/legacy/plugins/upgrade_assistant/server/lib/telemetry/es_ui_reindex_apis.test.ts rename to x-pack/legacy/plugins/upgrade_assistant/server/np_ready/lib/telemetry/es_ui_reindex_apis.test.ts index a8a78470aabbe..26302de74743f 100644 --- a/x-pack/legacy/plugins/upgrade_assistant/server/lib/telemetry/es_ui_reindex_apis.test.ts +++ b/x-pack/legacy/plugins/upgrade_assistant/server/np_ready/lib/telemetry/es_ui_reindex_apis.test.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { UPGRADE_ASSISTANT_DOC_ID, UPGRADE_ASSISTANT_TYPE } from '../../../common/types'; +import { UPGRADE_ASSISTANT_DOC_ID, UPGRADE_ASSISTANT_TYPE } from '../../../../common/types'; import { upsertUIReindexOption } from './es_ui_reindex_apis'; /** diff --git a/x-pack/legacy/plugins/upgrade_assistant/server/lib/telemetry/es_ui_reindex_apis.ts b/x-pack/legacy/plugins/upgrade_assistant/server/np_ready/lib/telemetry/es_ui_reindex_apis.ts similarity index 86% rename from x-pack/legacy/plugins/upgrade_assistant/server/lib/telemetry/es_ui_reindex_apis.ts rename to x-pack/legacy/plugins/upgrade_assistant/server/np_ready/lib/telemetry/es_ui_reindex_apis.ts index 3cb965523a80b..626d51b298e72 100644 --- a/x-pack/legacy/plugins/upgrade_assistant/server/lib/telemetry/es_ui_reindex_apis.ts +++ b/x-pack/legacy/plugins/upgrade_assistant/server/np_ready/lib/telemetry/es_ui_reindex_apis.ts @@ -4,17 +4,16 @@ * you may not use this file except in compliance with the Elastic License. */ -import { Legacy } from 'kibana'; import { UIReindex, UIReindexOption, UPGRADE_ASSISTANT_DOC_ID, UPGRADE_ASSISTANT_TYPE, - UpgradeAssistantTelemetryServer, -} from '../../../common/types'; +} from '../../../../common/types'; +import { RequestShim, ServerShim } from '../../types'; async function incrementUIReindexOptionCounter( - server: UpgradeAssistantTelemetryServer, + server: ServerShim, uiOpenOptionCounter: UIReindexOption ) { const { getSavedObjectsRepository } = server.savedObjects; @@ -29,8 +28,8 @@ async function incrementUIReindexOptionCounter( } export async function upsertUIReindexOption( - server: UpgradeAssistantTelemetryServer, - req: Legacy.Request + server: ServerShim, + req: RequestShim ): Promise { const { close, open, start, stop } = req.payload as UIReindex; diff --git a/x-pack/legacy/plugins/upgrade_assistant/server/lib/telemetry/index.ts b/x-pack/legacy/plugins/upgrade_assistant/server/np_ready/lib/telemetry/index.ts similarity index 100% rename from x-pack/legacy/plugins/upgrade_assistant/server/lib/telemetry/index.ts rename to x-pack/legacy/plugins/upgrade_assistant/server/np_ready/lib/telemetry/index.ts diff --git a/x-pack/legacy/plugins/upgrade_assistant/server/lib/telemetry/usage_collector.test.ts b/x-pack/legacy/plugins/upgrade_assistant/server/np_ready/lib/telemetry/usage_collector.test.ts similarity index 100% rename from x-pack/legacy/plugins/upgrade_assistant/server/lib/telemetry/usage_collector.test.ts rename to x-pack/legacy/plugins/upgrade_assistant/server/np_ready/lib/telemetry/usage_collector.test.ts diff --git a/x-pack/legacy/plugins/upgrade_assistant/server/lib/telemetry/usage_collector.ts b/x-pack/legacy/plugins/upgrade_assistant/server/np_ready/lib/telemetry/usage_collector.ts similarity index 87% rename from x-pack/legacy/plugins/upgrade_assistant/server/lib/telemetry/usage_collector.ts rename to x-pack/legacy/plugins/upgrade_assistant/server/np_ready/lib/telemetry/usage_collector.ts index 3a9b11a57f070..47a2cd5d51fd4 100644 --- a/x-pack/legacy/plugins/upgrade_assistant/server/lib/telemetry/usage_collector.ts +++ b/x-pack/legacy/plugins/upgrade_assistant/server/np_ready/lib/telemetry/usage_collector.ts @@ -13,8 +13,8 @@ import { UpgradeAssistantTelemetry, UpgradeAssistantTelemetrySavedObject, UpgradeAssistantTelemetrySavedObjectAttributes, - UpgradeAssistantTelemetryServer, -} from '../../../common/types'; +} from '../../../../common/types'; +import { ServerShim } from '../../types'; import { isDeprecationLoggingEnabled } from '../es_deprecation_logging_apis'; async function getSavedObjectAttributesFromRepo( @@ -43,7 +43,7 @@ async function getDeprecationLoggingStatusValue(callCluster: any): Promise { const { getSavedObjectsRepository } = server.savedObjects; const savedObjectsRepository = getSavedObjectsRepository(callCluster); @@ -97,13 +97,12 @@ export async function fetchUpgradeAssistantMetrics( }; } -export function makeUpgradeAssistantUsageCollector(server: UpgradeAssistantTelemetryServer) { - const kbnServer = server as UpgradeAssistantTelemetryServer; - const upgradeAssistantUsageCollector = kbnServer.usage.collectorSet.makeUsageCollector({ +export function makeUpgradeAssistantUsageCollector(server: ServerShim) { + const upgradeAssistantUsageCollector = server.usage.collectorSet.makeUsageCollector({ type: UPGRADE_ASSISTANT_TYPE, isReady: () => true, fetch: async (callCluster: any) => fetchUpgradeAssistantMetrics(callCluster, server), }); - kbnServer.usage.collectorSet.register(upgradeAssistantUsageCollector); + server.usage.collectorSet.register(upgradeAssistantUsageCollector); } diff --git a/x-pack/legacy/plugins/upgrade_assistant/server/np_ready/plugin.ts b/x-pack/legacy/plugins/upgrade_assistant/server/np_ready/plugin.ts new file mode 100644 index 0000000000000..7bc33142ca321 --- /dev/null +++ b/x-pack/legacy/plugins/upgrade_assistant/server/np_ready/plugin.ts @@ -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 { Plugin, CoreSetup, CoreStart } from 'src/core/server'; +import { ServerShim, ServerShimWithRouter } from './types'; +import { credentialStoreFactory } from './lib/reindexing/credential_store'; +import { makeUpgradeAssistantUsageCollector } from './lib/telemetry'; +import { registerClusterCheckupRoutes } from './routes/cluster_checkup'; +import { registerDeprecationLoggingRoutes } from './routes/deprecation_logging'; +import { registerReindexIndicesRoutes, registerReindexWorker } from './routes/reindex_indices'; + +import { registerTelemetryRoutes } from './routes/telemetry'; + +export class UpgradeAssistantServerPlugin implements Plugin { + setup({ http }: CoreSetup, { __LEGACY }: { __LEGACY: ServerShim }) { + const router = http.createRouter(); + const shimWithRouter: ServerShimWithRouter = { ...__LEGACY, router }; + registerClusterCheckupRoutes(shimWithRouter); + registerDeprecationLoggingRoutes(shimWithRouter); + + // The ReindexWorker uses a map of request headers that contain the authentication credentials + // for a given reindex. We cannot currently store these in an the .kibana index b/c we do not + // want to expose these credentials to any unauthenticated users. We also want to avoid any need + // to add a user for a special index just for upgrading. This in-memory cache allows us to + // process jobs without the browser staying on the page, but will require that jobs go into + // a paused state if no Kibana nodes have the required credentials. + const credentialStore = credentialStoreFactory(); + + const worker = registerReindexWorker(__LEGACY, credentialStore); + registerReindexIndicesRoutes(shimWithRouter, worker, credentialStore); + + // Bootstrap the needed routes and the collector for the telemetry + registerTelemetryRoutes(shimWithRouter); + makeUpgradeAssistantUsageCollector(__LEGACY); + } + + start(core: CoreStart, plugins: any) {} + + stop(): void {} +} diff --git a/x-pack/legacy/plugins/upgrade_assistant/server/np_ready/routes/__mocks__/request.mock.ts b/x-pack/legacy/plugins/upgrade_assistant/server/np_ready/routes/__mocks__/request.mock.ts new file mode 100644 index 0000000000000..d09a66dbb4326 --- /dev/null +++ b/x-pack/legacy/plugins/upgrade_assistant/server/np_ready/routes/__mocks__/request.mock.ts @@ -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 const createRequestMock = (opts?: { + headers?: any; + params?: Record; + payload?: Record; +}) => { + return Object.assign({ headers: {} }, opts || {}); +}; diff --git a/x-pack/legacy/plugins/upgrade_assistant/server/np_ready/routes/__mocks__/routes.mock.ts b/x-pack/legacy/plugins/upgrade_assistant/server/np_ready/routes/__mocks__/routes.mock.ts new file mode 100644 index 0000000000000..3769bc389123e --- /dev/null +++ b/x-pack/legacy/plugins/upgrade_assistant/server/np_ready/routes/__mocks__/routes.mock.ts @@ -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 { RequestHandler } from 'kibana/server'; + +/** + * Creates a very crude mock of the new platform router implementation. This enables use to test + * controller/handler logic without making HTTP requests to an actual server. This does not enable + * us to test whether our paths actual match, only the response codes of controllers given certain + * inputs. This should be replaced by a more wholistic solution (like functional tests) eventually. + * + * This also bypasses any validation installed on the route. + */ +export const createMockRouter = () => { + const paths: Record>> = {}; + + const assign = (method: string) => ( + { path }: { path: string }, + handler: RequestHandler + ) => { + paths[method] = { + ...(paths[method] || {}), + ...{ [path]: handler }, + }; + }; + + return { + getHandler({ method, pathPattern }: { method: string; pathPattern: string }) { + return paths[method][pathPattern]; + }, + get: assign('get'), + post: assign('post'), + put: assign('put'), + patch: assign('patch'), + }; +}; + +export type MockRouter = ReturnType; diff --git a/x-pack/legacy/plugins/upgrade_assistant/server/routes/cluster_checkup.test.ts b/x-pack/legacy/plugins/upgrade_assistant/server/np_ready/routes/cluster_checkup.test.ts similarity index 53% rename from x-pack/legacy/plugins/upgrade_assistant/server/routes/cluster_checkup.test.ts rename to x-pack/legacy/plugins/upgrade_assistant/server/np_ready/routes/cluster_checkup.test.ts index 04a05dc2b0e9c..6afb9d2a5e935 100644 --- a/x-pack/legacy/plugins/upgrade_assistant/server/routes/cluster_checkup.test.ts +++ b/x-pack/legacy/plugins/upgrade_assistant/server/np_ready/routes/cluster_checkup.test.ts @@ -3,33 +3,20 @@ * or more contributor license agreements. Licensed under the Elastic License; * you may not use this file except in compliance with the Elastic License. */ +import { kibanaResponseFactory } from 'src/core/server'; +import { createMockRouter, MockRouter } from './__mocks__/routes.mock'; +import { createRequestMock } from './__mocks__/request.mock'; -import Boom from 'boom'; -import { Server } from 'hapi'; - -jest.mock('../lib/es_version_precheck'); -import { EsVersionPrecheck } from '../lib/es_version_precheck'; -import { registerClusterCheckupRoutes } from './cluster_checkup'; +jest.mock('../lib/es_version_precheck', () => ({ + versionCheckHandlerWrapper: (a: any) => a, +})); // Need to require to get mock on named export to work. // eslint-disable-next-line @typescript-eslint/no-var-requires const MigrationApis = require('../lib/es_migration_apis'); MigrationApis.getUpgradeAssistantStatus = jest.fn(); -function register(plugins = {}) { - const server = new Server(); - server.plugins = { - elasticsearch: { - getCluster: () => ({ callWithRequest: jest.fn() } as any), - } as any, - ...plugins, - } as any; - server.config = () => ({ get: () => '' } as any); - - registerClusterCheckupRoutes(server); - - return server; -} +import { registerClusterCheckupRoutes } from './cluster_checkup'; /** * Since these route callbacks are so thin, these serve simply as integration tests @@ -37,50 +24,65 @@ function register(plugins = {}) { * more thoroughly in the es_migration_apis test. */ describe('cluster checkup API', () => { - const spy = jest.spyOn(MigrationApis, 'getUpgradeAssistantStatus'); - afterEach(() => jest.clearAllMocks()); - describe('with cloud enabled', () => { - it('is provided to getUpgradeAssistantStatus', async () => { - const server = register({ + let mockRouter: MockRouter; + let serverShim: any; + let ctxMock: any; + + beforeEach(() => { + mockRouter = createMockRouter(); + ctxMock = { + core: {}, + }; + serverShim = { + router: mockRouter, + plugins: { cloud: { config: { isCloudEnabled: true, }, }, - }); + elasticsearch: { + getCluster: () => ({ callWithRequest: jest.fn() } as any), + } as any, + }, + }; + registerClusterCheckupRoutes(serverShim); + }); + + describe('with cloud enabled', () => { + it('is provided to getUpgradeAssistantStatus', async () => { + const spy = jest.spyOn(MigrationApis, 'getUpgradeAssistantStatus'); MigrationApis.getUpgradeAssistantStatus.mockResolvedValue({ cluster: [], indices: [], nodes: [], }); - await server.inject({ - method: 'GET', - url: '/api/upgrade_assistant/status', - }); + await serverShim.router.getHandler({ + method: 'get', + pathPattern: '/api/upgrade_assistant/status', + })(ctxMock, createRequestMock(), kibanaResponseFactory); expect(spy.mock.calls[0][2]).toBe(true); }); }); describe('GET /api/upgrade_assistant/reindex/{indexName}.json', () => { - const server = register(); - it('returns state', async () => { MigrationApis.getUpgradeAssistantStatus.mockResolvedValue({ cluster: [], indices: [], nodes: [], }); - const resp = await server.inject({ - method: 'GET', - url: '/api/upgrade_assistant/status', - }); + const resp = await serverShim.router.getHandler({ + method: 'get', + pathPattern: '/api/upgrade_assistant/status', + })(ctxMock, createRequestMock(), kibanaResponseFactory); - expect(resp.statusCode).toEqual(200); - expect(resp.payload).toMatchInlineSnapshot( + expect(resp.status).toEqual(200); + expect(JSON.stringify(resp.payload)).toMatchInlineSnapshot( `"{\\"cluster\\":[],\\"indices\\":[],\\"nodes\\":[]}"` ); }); @@ -90,35 +92,23 @@ describe('cluster checkup API', () => { e.status = 403; MigrationApis.getUpgradeAssistantStatus.mockRejectedValue(e); - const resp = await server.inject({ - method: 'GET', - url: '/api/upgrade_assistant/status', - }); + const resp = await serverShim.router.getHandler({ + method: 'get', + pathPattern: '/api/upgrade_assistant/status', + })(ctxMock, createRequestMock(), kibanaResponseFactory); - expect(resp.statusCode).toEqual(403); + expect(resp.status).toEqual(403); }); it('returns an 500 error if it throws', async () => { MigrationApis.getUpgradeAssistantStatus.mockRejectedValue(new Error(`scary error!`)); - const resp = await server.inject({ - method: 'GET', - url: '/api/upgrade_assistant/status', - }); - expect(resp.statusCode).toEqual(500); - }); - - it('returns a 426 if EsVersionCheck throws', async () => { - (EsVersionPrecheck.method as jest.Mock).mockRejectedValue( - new Boom(`blah`, { statusCode: 426 }) - ); - - const resp = await server.inject({ - method: 'GET', - url: '/api/upgrade_assistant/status', - }); + const resp = await serverShim.router.getHandler({ + method: 'get', + pathPattern: '/api/upgrade_assistant/status', + })(ctxMock, createRequestMock(), kibanaResponseFactory); - expect(resp.statusCode).toEqual(426); + expect(resp.status).toEqual(500); }); }); }); diff --git a/x-pack/legacy/plugins/upgrade_assistant/server/np_ready/routes/cluster_checkup.ts b/x-pack/legacy/plugins/upgrade_assistant/server/np_ready/routes/cluster_checkup.ts new file mode 100644 index 0000000000000..3cfa567755b0f --- /dev/null +++ b/x-pack/legacy/plugins/upgrade_assistant/server/np_ready/routes/cluster_checkup.ts @@ -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 _ from 'lodash'; +import { ServerShimWithRouter } from '../types'; +import { getUpgradeAssistantStatus } from '../lib/es_migration_apis'; +import { versionCheckHandlerWrapper } from '../lib/es_version_precheck'; + +import { createRequestShim } from './create_request_shim'; + +export function registerClusterCheckupRoutes(server: ServerShimWithRouter) { + const { callWithRequest } = server.plugins.elasticsearch.getCluster('admin'); + const isCloudEnabled = _.get(server.plugins, 'cloud.config.isCloudEnabled', false); + + server.router.get( + { + path: '/api/upgrade_assistant/status', + validate: false, + }, + versionCheckHandlerWrapper(async (ctx, request, response) => { + const reqShim = createRequestShim(request); + try { + return response.ok({ + body: await getUpgradeAssistantStatus(callWithRequest, reqShim, isCloudEnabled), + }); + } catch (e) { + if (e.status === 403) { + return response.forbidden(e.message); + } + + return response.internalError({ body: e }); + } + }) + ); +} diff --git a/x-pack/legacy/plugins/upgrade_assistant/server/np_ready/routes/create_request_shim.ts b/x-pack/legacy/plugins/upgrade_assistant/server/np_ready/routes/create_request_shim.ts new file mode 100644 index 0000000000000..b1a5c8b72d0e0 --- /dev/null +++ b/x-pack/legacy/plugins/upgrade_assistant/server/np_ready/routes/create_request_shim.ts @@ -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 { KibanaRequest } from 'kibana/server'; +import { RequestShim } from '../types'; + +export const createRequestShim = (req: KibanaRequest): RequestShim => { + return { + headers: req.headers as Record, + payload: req.body || (req as any).payload, + params: req.params, + }; +}; diff --git a/x-pack/legacy/plugins/upgrade_assistant/server/np_ready/routes/deprecation_logging.test.ts b/x-pack/legacy/plugins/upgrade_assistant/server/np_ready/routes/deprecation_logging.test.ts new file mode 100644 index 0000000000000..c488f999b538e --- /dev/null +++ b/x-pack/legacy/plugins/upgrade_assistant/server/np_ready/routes/deprecation_logging.test.ts @@ -0,0 +1,91 @@ +/* + * 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 { kibanaResponseFactory } from 'src/core/server'; +import { createMockRouter, MockRouter } from './__mocks__/routes.mock'; +import { createRequestMock } from './__mocks__/request.mock'; + +jest.mock('../lib/es_version_precheck', () => ({ + versionCheckHandlerWrapper: (a: any) => a, +})); + +import { registerDeprecationLoggingRoutes } from './deprecation_logging'; + +/** + * Since these route callbacks are so thin, these serve simply as integration tests + * to ensure they're wired up to the lib functions correctly. Business logic is tested + * more thoroughly in the es_deprecation_logging_apis test. + */ +describe('deprecation logging API', () => { + let mockRouter: MockRouter; + let serverShim: any; + let callWithRequest: any; + const ctxMock: any = {}; + + beforeEach(() => { + mockRouter = createMockRouter(); + callWithRequest = jest.fn(); + serverShim = { + router: mockRouter, + plugins: { + cloud: { + config: { + isCloudEnabled: true, + }, + }, + elasticsearch: { + getCluster: () => ({ callWithRequest } as any), + } as any, + }, + }; + registerDeprecationLoggingRoutes(serverShim); + }); + + describe('GET /api/upgrade_assistant/deprecation_logging', () => { + it('returns isEnabled', async () => { + callWithRequest.mockResolvedValue({ default: { logger: { deprecation: 'WARN' } } }); + const resp = await serverShim.router.getHandler({ + method: 'get', + pathPattern: '/api/upgrade_assistant/deprecation_logging', + })(ctxMock, createRequestMock(), kibanaResponseFactory); + + expect(resp.status).toEqual(200); + expect(resp.payload).toEqual({ isEnabled: true }); + }); + + it('returns an error if it throws', async () => { + callWithRequest.mockRejectedValue(new Error(`scary error!`)); + const resp = await serverShim.router.getHandler({ + method: 'get', + pathPattern: '/api/upgrade_assistant/deprecation_logging', + })(ctxMock, createRequestMock(), kibanaResponseFactory); + + expect(resp.status).toEqual(500); + }); + }); + + describe('PUT /api/upgrade_assistant/deprecation_logging', () => { + it('returns isEnabled', async () => { + callWithRequest.mockResolvedValue({ default: { logger: { deprecation: 'ERROR' } } }); + const resp = await serverShim.router.getHandler({ + method: 'get', + pathPattern: '/api/upgrade_assistant/deprecation_logging', + })(ctxMock, createRequestMock(), kibanaResponseFactory); + + expect(resp.payload).toEqual({ isEnabled: false }); + }); + + it('returns an error if it throws', async () => { + callWithRequest.mockRejectedValue(new Error(`scary error!`)); + const resp = await serverShim.router.getHandler({ + method: 'put', + pathPattern: '/api/upgrade_assistant/deprecation_logging', + })(ctxMock, { body: { isEnabled: false } }, kibanaResponseFactory); + + expect(resp.status).toEqual(500); + }); + }); +}); diff --git a/x-pack/legacy/plugins/upgrade_assistant/server/np_ready/routes/deprecation_logging.ts b/x-pack/legacy/plugins/upgrade_assistant/server/np_ready/routes/deprecation_logging.ts new file mode 100644 index 0000000000000..7e19ef3fb6047 --- /dev/null +++ b/x-pack/legacy/plugins/upgrade_assistant/server/np_ready/routes/deprecation_logging.ts @@ -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 { schema } from '@kbn/config-schema'; + +import { + getDeprecationLoggingStatus, + setDeprecationLogging, +} from '../lib/es_deprecation_logging_apis'; +import { versionCheckHandlerWrapper } from '../lib/es_version_precheck'; +import { ServerShimWithRouter } from '../types'; +import { createRequestShim } from './create_request_shim'; + +export function registerDeprecationLoggingRoutes(server: ServerShimWithRouter) { + const { callWithRequest } = server.plugins.elasticsearch.getCluster('admin'); + + server.router.get( + { + path: '/api/upgrade_assistant/deprecation_logging', + validate: false, + }, + versionCheckHandlerWrapper(async (ctx, request, response) => { + const reqShim = createRequestShim(request); + try { + const result = await getDeprecationLoggingStatus(callWithRequest, reqShim); + return response.ok({ body: result }); + } catch (e) { + return response.internalError({ body: e }); + } + }) + ); + + server.router.put( + { + path: '/api/upgrade_assistant/deprecation_logging', + validate: { + body: schema.object({ + isEnabled: schema.boolean(), + }), + }, + }, + versionCheckHandlerWrapper(async (ctx, request, response) => { + const reqShim = createRequestShim(request); + try { + const { isEnabled } = reqShim.payload as { isEnabled: boolean }; + return response.ok({ + body: await setDeprecationLogging(callWithRequest, reqShim, isEnabled), + }); + } catch (e) { + return response.internalError({ body: e }); + } + }) + ); +} diff --git a/x-pack/legacy/plugins/upgrade_assistant/server/routes/reindex_indices.test.ts b/x-pack/legacy/plugins/upgrade_assistant/server/np_ready/routes/reindex_indices.test.ts similarity index 58% rename from x-pack/legacy/plugins/upgrade_assistant/server/routes/reindex_indices.test.ts rename to x-pack/legacy/plugins/upgrade_assistant/server/np_ready/routes/reindex_indices.test.ts index 264c98526622c..d520324239656 100644 --- a/x-pack/legacy/plugins/upgrade_assistant/server/routes/reindex_indices.test.ts +++ b/x-pack/legacy/plugins/upgrade_assistant/server/np_ready/routes/reindex_indices.test.ts @@ -4,7 +4,10 @@ * you may not use this file except in compliance with the Elastic License. */ -import { Server } from 'hapi'; +import { savedObjectsClientMock } from 'src/core/server/mocks'; +import { kibanaResponseFactory } from 'src/core/server'; +import { createMockRouter, MockRouter } from './__mocks__/routes.mock'; +import { createRequestMock } from './__mocks__/request.mock'; const mockReindexService = { hasRequiredPrivileges: jest.fn(), @@ -18,14 +21,22 @@ const mockReindexService = { cancelReindexing: jest.fn(), }; -jest.mock('../lib/es_version_precheck'); +jest.mock('../lib/es_version_precheck', () => ({ + versionCheckHandlerWrapper: (a: any) => a, +})); + jest.mock('../lib/reindexing', () => { return { reindexServiceFactory: () => mockReindexService, }; }); -import { IndexGroup, ReindexSavedObject, ReindexStatus, ReindexWarning } from '../../common/types'; +import { + IndexGroup, + ReindexSavedObject, + ReindexStatus, + ReindexWarning, +} from '../../../common/types'; import { credentialStoreFactory } from '../lib/reindexing/credential_store'; import { registerReindexIndicesRoutes } from './reindex_indices'; @@ -35,28 +46,36 @@ import { registerReindexIndicesRoutes } from './reindex_indices'; * more thoroughly in the es_migration_apis test. */ describe('reindex API', () => { - const server = new Server(); - server.plugins = { - elasticsearch: { - getCluster: () => ({ callWithRequest: jest.fn() } as any), - } as any, - xpack_main: { - info: {}, - }, - } as any; - server.config = () => ({ get: () => '' } as any); - server.decorate('request', 'getSavedObjectsClient', () => jest.fn()); + let serverShim: any; + let mockRouter: MockRouter; + let ctxMock: any; const credentialStore = credentialStoreFactory(); - const worker = { includes: jest.fn(), forceRefresh: jest.fn(), } as any; - registerReindexIndicesRoutes(server, worker, credentialStore); - beforeEach(() => { + ctxMock = { + core: { + savedObjects: savedObjectsClientMock.create(), + }, + }; + mockRouter = createMockRouter(); + serverShim = { + router: mockRouter, + plugins: { + xpack_main: { + info: jest.fn(), + }, + elasticsearch: { + getCluster: () => ({ callWithRequest: jest.fn() } as any), + } as any, + }, + }; + registerReindexIndicesRoutes(serverShim, worker, credentialStore); + mockReindexService.hasRequiredPrivileges.mockResolvedValue(true); mockReindexService.detectReindexWarnings.mockReset(); mockReindexService.getIndexGroup.mockReset(); @@ -73,6 +92,8 @@ describe('reindex API', () => { credentialStore.clear(); }); + afterEach(() => jest.clearAllMocks()); + describe('GET /api/upgrade_assistant/reindex/{indexName}', () => { it('returns the attributes of the reindex operation and reindex warnings', async () => { mockReindexService.findReindexOperation.mockResolvedValueOnce({ @@ -80,18 +101,18 @@ describe('reindex API', () => { }); mockReindexService.detectReindexWarnings.mockResolvedValueOnce([ReindexWarning.allField]); - const resp = await server.inject({ - method: 'GET', - url: `/api/upgrade_assistant/reindex/wowIndex`, - }); + const resp = await serverShim.router.getHandler({ + method: 'get', + pathPattern: '/api/upgrade_assistant/reindex/{indexName}', + })(ctxMock, createRequestMock({ params: { indexName: 'wowIndex' } }), kibanaResponseFactory); // It called into the service correctly expect(mockReindexService.findReindexOperation).toHaveBeenCalledWith('wowIndex'); expect(mockReindexService.detectReindexWarnings).toHaveBeenCalledWith('wowIndex'); // It returned the right results - expect(resp.statusCode).toEqual(200); - const data = JSON.parse(resp.payload); + expect(resp.status).toEqual(200); + const data = resp.payload; expect(data.reindexOp).toEqual({ indexName: 'wowIndex', status: ReindexStatus.inProgress }); expect(data.warnings).toEqual([0]); }); @@ -100,13 +121,13 @@ describe('reindex API', () => { mockReindexService.findReindexOperation.mockResolvedValueOnce(null); mockReindexService.detectReindexWarnings.mockResolvedValueOnce(null); - const resp = await server.inject({ - method: 'GET', - url: `/api/upgrade_assistant/reindex/anIndex`, - }); + const resp = await serverShim.router.getHandler({ + method: 'get', + pathPattern: '/api/upgrade_assistant/reindex/{indexName}', + })(ctxMock, createRequestMock({ params: { indexName: 'anIndex' } }), kibanaResponseFactory); - expect(resp.statusCode).toEqual(200); - const data = JSON.parse(resp.payload); + expect(resp.status).toEqual(200); + const data = resp.payload; expect(data.reindexOp).toBeNull(); expect(data.warnings).toBeNull(); }); @@ -116,13 +137,13 @@ describe('reindex API', () => { mockReindexService.detectReindexWarnings.mockResolvedValueOnce([]); mockReindexService.getIndexGroup.mockReturnValue(IndexGroup.ml); - const resp = await server.inject({ - method: 'GET', - url: `/api/upgrade_assistant/reindex/.ml-state`, - }); + const resp = await serverShim.router.getHandler({ + method: 'get', + pathPattern: '/api/upgrade_assistant/reindex/{indexName}', + })(ctxMock, createRequestMock({ params: { indexName: 'anIndex' } }), kibanaResponseFactory); - expect(resp.statusCode).toEqual(200); - const data = JSON.parse(resp.payload); + expect(resp.status).toEqual(200); + const data = resp.payload; expect(data.indexGroup).toEqual(IndexGroup.ml); }); }); @@ -133,17 +154,17 @@ describe('reindex API', () => { attributes: { indexName: 'theIndex' }, }); - const resp = await server.inject({ - method: 'POST', - url: '/api/upgrade_assistant/reindex/theIndex', - }); + const resp = await serverShim.router.getHandler({ + method: 'post', + pathPattern: '/api/upgrade_assistant/reindex/{indexName}', + })(ctxMock, createRequestMock({ params: { indexName: 'theIndex' } }), kibanaResponseFactory); // It called create correctly expect(mockReindexService.createReindexOperation).toHaveBeenCalledWith('theIndex'); // It returned the right results - expect(resp.statusCode).toEqual(200); - const data = JSON.parse(resp.payload); + expect(resp.status).toEqual(200); + const data = resp.payload; expect(data).toEqual({ indexName: 'theIndex' }); }); @@ -152,10 +173,10 @@ describe('reindex API', () => { attributes: { indexName: 'theIndex' }, }); - await server.inject({ - method: 'POST', - url: '/api/upgrade_assistant/reindex/theIndex', - }); + await serverShim.router.getHandler({ + method: 'post', + pathPattern: '/api/upgrade_assistant/reindex/{indexName}', + })(ctxMock, createRequestMock({ params: { indexName: 'theIndex' } }), kibanaResponseFactory); expect(worker.forceRefresh).toHaveBeenCalled(); }); @@ -166,13 +187,19 @@ describe('reindex API', () => { } as ReindexSavedObject; mockReindexService.createReindexOperation.mockResolvedValueOnce(reindexOp); - await server.inject({ - method: 'POST', - url: '/api/upgrade_assistant/reindex/theIndex', - headers: { - 'kbn-auth-x': 'HERE!', - }, - }); + await serverShim.router.getHandler({ + method: 'post', + pathPattern: '/api/upgrade_assistant/reindex/{indexName}', + })( + ctxMock, + createRequestMock({ + headers: { + 'kbn-auth-x': 'HERE!', + }, + params: { indexName: 'theIndex' }, + }), + kibanaResponseFactory + ); expect(credentialStore.get(reindexOp)!['kbn-auth-x']).toEqual('HERE!'); }); @@ -185,30 +212,41 @@ describe('reindex API', () => { attributes: { indexName: 'theIndex', status: ReindexStatus.inProgress }, }); - const resp = await server.inject({ - method: 'POST', - url: '/api/upgrade_assistant/reindex/theIndex', - }); - + const resp = await serverShim.router.getHandler({ + method: 'post', + pathPattern: '/api/upgrade_assistant/reindex/{indexName}', + })( + ctxMock, + createRequestMock({ + params: { indexName: 'theIndex' }, + }), + kibanaResponseFactory + ); // It called resume correctly expect(mockReindexService.resumeReindexOperation).toHaveBeenCalledWith('theIndex'); expect(mockReindexService.createReindexOperation).not.toHaveBeenCalled(); // It returned the right results - expect(resp.statusCode).toEqual(200); - const data = JSON.parse(resp.payload); + expect(resp.status).toEqual(200); + const data = resp.payload; expect(data).toEqual({ indexName: 'theIndex', status: ReindexStatus.inProgress }); }); it('returns a 403 if required privileges fails', async () => { mockReindexService.hasRequiredPrivileges.mockResolvedValueOnce(false); - const resp = await server.inject({ - method: 'POST', - url: '/api/upgrade_assistant/reindex/theIndex', - }); - - expect(resp.statusCode).toEqual(403); + const resp = await serverShim.router.getHandler({ + method: 'post', + pathPattern: '/api/upgrade_assistant/reindex/{indexName}', + })( + ctxMock, + createRequestMock({ + params: { indexName: 'theIndex' }, + }), + kibanaResponseFactory + ); + + expect(resp.status).toEqual(403); }); }); @@ -216,13 +254,19 @@ describe('reindex API', () => { it('returns a 501', async () => { mockReindexService.cancelReindexing.mockResolvedValueOnce({}); - const resp = await server.inject({ - method: 'POST', - url: '/api/upgrade_assistant/reindex/cancelMe/cancel', - }); - - expect(resp.statusCode).toEqual(200); - expect(resp.payload).toMatchInlineSnapshot(`"{\\"acknowledged\\":true}"`); + const resp = await serverShim.router.getHandler({ + method: 'post', + pathPattern: '/api/upgrade_assistant/reindex/{indexName}/cancel', + })( + ctxMock, + createRequestMock({ + params: { indexName: 'cancelMe' }, + }), + kibanaResponseFactory + ); + + expect(resp.status).toEqual(200); + expect(resp.payload).toEqual({ acknowledged: true }); expect(mockReindexService.cancelReindexing).toHaveBeenCalledWith('cancelMe'); }); }); diff --git a/x-pack/legacy/plugins/upgrade_assistant/server/routes/reindex_indices.ts b/x-pack/legacy/plugins/upgrade_assistant/server/np_ready/routes/reindex_indices.ts similarity index 56% rename from x-pack/legacy/plugins/upgrade_assistant/server/routes/reindex_indices.ts rename to x-pack/legacy/plugins/upgrade_assistant/server/np_ready/routes/reindex_indices.ts index 43e4c9899d233..c22f12316bd02 100644 --- a/x-pack/legacy/plugins/upgrade_assistant/server/routes/reindex_indices.ts +++ b/x-pack/legacy/plugins/upgrade_assistant/server/np_ready/routes/reindex_indices.ts @@ -4,18 +4,18 @@ * you may not use this file except in compliance with the Elastic License. */ -import Boom from 'boom'; -import { Server } from 'hapi'; - +import { schema } from '@kbn/config-schema'; import { CallCluster } from 'src/legacy/core_plugins/elasticsearch'; -import { SavedObjectsClientContract } from 'src/core/server'; -import { ReindexStatus } from '../../common/types'; -import { EsVersionPrecheck } from '../lib/es_version_precheck'; +import { SavedObjectsClientContract } from 'kibana/server'; +import { ReindexStatus } from '../../../common/types'; +import { versionCheckHandlerWrapper } from '../lib/es_version_precheck'; import { reindexServiceFactory, ReindexWorker } from '../lib/reindexing'; import { CredentialStore } from '../lib/reindexing/credential_store'; import { reindexActionsFactory } from '../lib/reindexing/reindex_actions'; +import { ServerShim, ServerShimWithRouter } from '../types'; +import { createRequestShim } from './create_request_shim'; -export function registerReindexWorker(server: Server, credentialStore: CredentialStore) { +export function registerReindexWorker(server: ServerShim, credentialStore: CredentialStore) { const { callWithRequest, callWithInternalUser } = server.plugins.elasticsearch.getCluster( 'admin' ); @@ -29,11 +29,8 @@ export function registerReindexWorker(server: Server, credentialStore: Credentia // Cannot pass server.log directly because it's value changes during startup (?). // Use this function to proxy through. - const log: Server['log'] = ( - tags: string | string[], - data?: string | object | (() => any), - timestamp?: number - ) => server.log(tags, data, timestamp); + const log = (tags: string | string[], data?: string | object | (() => any), timestamp?: number) => + server.log(tags, data, timestamp); const worker = new ReindexWorker( savedObjectsClient, @@ -54,7 +51,7 @@ export function registerReindexWorker(server: Server, credentialStore: Credentia } export function registerReindexIndicesRoutes( - server: Server, + server: ServerShimWithRouter, worker: ReindexWorker, credentialStore: CredentialStore ) { @@ -63,16 +60,20 @@ export function registerReindexIndicesRoutes( const BASE_PATH = '/api/upgrade_assistant/reindex'; // Start reindex for an index - server.route({ - path: `${BASE_PATH}/{indexName}`, - method: 'POST', - options: { - pre: [EsVersionPrecheck], + server.router.post( + { + path: `${BASE_PATH}/{indexName}`, + validate: { + params: schema.object({ + indexName: schema.string(), + }), + }, }, - async handler(request) { - const client = request.getSavedObjectsClient(); - const { indexName } = request.params; - const callCluster = callWithRequest.bind(null, request) as CallCluster; + versionCheckHandlerWrapper(async (ctx, request, response) => { + const reqShim = createRequestShim(request); + const { indexName } = reqShim.params; + const { client } = ctx.core.savedObjects; + const callCluster = callWithRequest.bind(null, reqShim) as CallCluster; const reindexActions = reindexActionsFactory(client, callCluster); const reindexService = reindexServiceFactory( callCluster, @@ -83,7 +84,9 @@ export function registerReindexIndicesRoutes( try { if (!(await reindexService.hasRequiredPrivileges(indexName))) { - throw Boom.forbidden(`You do not have adequate privileges to reindex this index.`); + return response.forbidden({ + body: `You do not have adequate privileges to reindex this index.`, + }); } const existingOp = await reindexService.findReindexOperation(indexName); @@ -95,33 +98,33 @@ export function registerReindexIndicesRoutes( : await reindexService.createReindexOperation(indexName); // Add users credentials for the worker to use - credentialStore.set(reindexOp, request.headers); + credentialStore.set(reindexOp, reqShim.headers); // Kick the worker on this node to immediately pickup the new reindex operation. worker.forceRefresh(); - return reindexOp.attributes; + return response.ok({ body: reindexOp.attributes }); } catch (e) { - if (!e.isBoom) { - return Boom.boomify(e, { statusCode: 500 }); - } - - return e; + return response.internalError({ body: e }); } - }, - }); + }) + ); // Get status - server.route({ - path: `${BASE_PATH}/{indexName}`, - method: 'GET', - options: { - pre: [EsVersionPrecheck], + server.router.get( + { + path: `${BASE_PATH}/{indexName}`, + validate: { + params: schema.object({ + indexName: schema.string(), + }), + }, }, - async handler(request) { - const client = request.getSavedObjectsClient(); - const { indexName } = request.params; - const callCluster = callWithRequest.bind(null, request) as CallCluster; + versionCheckHandlerWrapper(async (ctx, request, response) => { + const reqShim = createRequestShim(request); + const { client } = ctx.core.savedObjects; + const { indexName } = reqShim.params; + const callCluster = callWithRequest.bind(null, reqShim) as CallCluster; const reindexActions = reindexActionsFactory(client, callCluster); const reindexService = reindexServiceFactory( callCluster, @@ -139,33 +142,43 @@ export function registerReindexIndicesRoutes( : []; const indexGroup = reindexService.getIndexGroup(indexName); - return { - reindexOp: reindexOp ? reindexOp.attributes : null, - warnings, - indexGroup, - hasRequiredPrivileges, - }; + return response.ok({ + body: { + reindexOp: reindexOp ? reindexOp.attributes : null, + warnings, + indexGroup, + hasRequiredPrivileges, + }, + }); } catch (e) { if (!e.isBoom) { - return Boom.boomify(e, { statusCode: 500 }); + return response.internalError({ body: e }); } - - return e; + return response.customError({ + body: { + message: e.message, + }, + statusCode: e.statusCode, + }); } - }, - }); + }) + ); // Cancel reindex - server.route({ - path: `${BASE_PATH}/{indexName}/cancel`, - method: 'POST', - options: { - pre: [EsVersionPrecheck], + server.router.post( + { + path: `${BASE_PATH}/{indexName}/cancel`, + validate: { + params: schema.object({ + indexName: schema.string(), + }), + }, }, - async handler(request) { - const client = request.getSavedObjectsClient(); - const { indexName } = request.params; - const callCluster = callWithRequest.bind(null, request) as CallCluster; + versionCheckHandlerWrapper(async (ctx, request, response) => { + const reqShim = createRequestShim(request); + const { indexName } = reqShim.params; + const { client } = ctx.core.savedObjects; + const callCluster = callWithRequest.bind(null, reqShim) as CallCluster; const reindexActions = reindexActionsFactory(client, callCluster); const reindexService = reindexServiceFactory( callCluster, @@ -177,14 +190,18 @@ export function registerReindexIndicesRoutes( try { await reindexService.cancelReindexing(indexName); - return { acknowledged: true }; + return response.ok({ body: { acknowledged: true } }); } catch (e) { if (!e.isBoom) { - return Boom.boomify(e, { statusCode: 500 }); + return response.internalError({ body: e }); } - - return e; + return response.customError({ + body: { + message: e.message, + }, + statusCode: e.statusCode, + }); } - }, - }); + }) + ); } diff --git a/x-pack/legacy/plugins/upgrade_assistant/server/np_ready/routes/telemetry.test.ts b/x-pack/legacy/plugins/upgrade_assistant/server/np_ready/routes/telemetry.test.ts new file mode 100644 index 0000000000000..582c75e3701b6 --- /dev/null +++ b/x-pack/legacy/plugins/upgrade_assistant/server/np_ready/routes/telemetry.test.ts @@ -0,0 +1,190 @@ +/* + * 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 { kibanaResponseFactory } from 'src/core/server'; +import { createMockRouter, MockRouter } from './__mocks__/routes.mock'; +import { createRequestMock } from './__mocks__/request.mock'; + +jest.mock('../lib/telemetry/es_ui_open_apis', () => ({ + upsertUIOpenOption: jest.fn(), +})); + +jest.mock('../lib/telemetry/es_ui_reindex_apis', () => ({ + upsertUIReindexOption: jest.fn(), +})); + +import { upsertUIOpenOption } from '../lib/telemetry/es_ui_open_apis'; +import { upsertUIReindexOption } from '../lib/telemetry/es_ui_reindex_apis'; +import { registerTelemetryRoutes } from './telemetry'; + +/** + * Since these route callbacks are so thin, these serve simply as integration tests + * to ensure they're wired up to the lib functions correctly. Business logic is tested + * more thoroughly in the lib/telemetry tests. + */ +describe('Upgrade Assistant Telemetry API', () => { + let serverShim: any; + let mockRouter: MockRouter; + let ctxMock: any; + beforeEach(() => { + ctxMock = {}; + mockRouter = createMockRouter(); + serverShim = { + router: mockRouter, + plugins: { + xpack_main: { + info: jest.fn(), + }, + elasticsearch: { + getCluster: () => ({ callWithRequest: jest.fn() } as any), + } as any, + }, + }; + registerTelemetryRoutes(serverShim); + }); + afterEach(() => jest.clearAllMocks()); + + describe('PUT /api/upgrade_assistant/telemetry/ui_open', () => { + it('returns correct payload with single option', async () => { + const returnPayload = { + overview: true, + cluster: false, + indices: false, + }; + + (upsertUIOpenOption as jest.Mock).mockResolvedValue(returnPayload); + + const resp = await serverShim.router.getHandler({ + method: 'put', + pathPattern: '/api/upgrade_assistant/telemetry/ui_open', + })(ctxMock, createRequestMock(), kibanaResponseFactory); + + expect(resp.payload).toEqual(returnPayload); + }); + + it('returns correct payload with multiple option', async () => { + const returnPayload = { + overview: true, + cluster: true, + indices: true, + }; + + (upsertUIOpenOption as jest.Mock).mockResolvedValue(returnPayload); + + const resp = await serverShim.router.getHandler({ + method: 'put', + pathPattern: '/api/upgrade_assistant/telemetry/ui_open', + })( + ctxMock, + createRequestMock({ + payload: { + overview: true, + cluster: true, + indices: true, + }, + }), + kibanaResponseFactory + ); + + expect(resp.payload).toEqual(returnPayload); + }); + + it('returns an error if it throws', async () => { + (upsertUIOpenOption as jest.Mock).mockRejectedValue(new Error(`scary error!`)); + + const resp = await serverShim.router.getHandler({ + method: 'put', + pathPattern: '/api/upgrade_assistant/telemetry/ui_open', + })( + ctxMock, + createRequestMock({ + payload: { + overview: false, + }, + }), + kibanaResponseFactory + ); + + expect(resp.status).toEqual(500); + }); + }); + + describe('PUT /api/upgrade_assistant/telemetry/ui_reindex', () => { + it('returns correct payload with single option', async () => { + const returnPayload = { + close: false, + open: false, + start: true, + stop: false, + }; + + (upsertUIReindexOption as jest.Mock).mockRejectedValue(returnPayload); + + const resp = await serverShim.router.getHandler({ + method: 'put', + pathPattern: '/api/upgrade_assistant/telemetry/ui_reindex', + })( + ctxMock, + createRequestMock({ + payload: { + overview: false, + }, + }), + kibanaResponseFactory + ); + + expect(resp.payload).toEqual(returnPayload); + }); + + it('returns correct payload with multiple option', async () => { + const returnPayload = { + close: true, + open: true, + start: true, + stop: true, + }; + + (upsertUIReindexOption as jest.Mock).mockRejectedValue(returnPayload); + + const resp = await serverShim.router.getHandler({ + method: 'put', + pathPattern: '/api/upgrade_assistant/telemetry/ui_reindex', + })( + ctxMock, + createRequestMock({ + payload: { + close: true, + open: true, + start: true, + stop: true, + }, + }), + kibanaResponseFactory + ); + + expect(resp.payload).toEqual(returnPayload); + }); + + it('returns an error if it throws', async () => { + (upsertUIReindexOption as jest.Mock).mockRejectedValue(new Error(`scary error!`)); + + const resp = await serverShim.router.getHandler({ + method: 'put', + pathPattern: '/api/upgrade_assistant/telemetry/ui_reindex', + })( + ctxMock, + createRequestMock({ + payload: { + start: false, + }, + }), + kibanaResponseFactory + ); + + expect(resp.status).toEqual(500); + }); + }); +}); diff --git a/x-pack/legacy/plugins/upgrade_assistant/server/np_ready/routes/telemetry.ts b/x-pack/legacy/plugins/upgrade_assistant/server/np_ready/routes/telemetry.ts new file mode 100644 index 0000000000000..f08c49809033d --- /dev/null +++ b/x-pack/legacy/plugins/upgrade_assistant/server/np_ready/routes/telemetry.ts @@ -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 { schema } from '@kbn/config-schema'; +import { upsertUIOpenOption } from '../lib/telemetry/es_ui_open_apis'; +import { upsertUIReindexOption } from '../lib/telemetry/es_ui_reindex_apis'; +import { ServerShimWithRouter } from '../types'; +import { createRequestShim } from './create_request_shim'; + +export function registerTelemetryRoutes(server: ServerShimWithRouter) { + server.router.put( + { + path: '/api/upgrade_assistant/telemetry/ui_open', + validate: { + body: schema.object({ + overview: schema.boolean({ defaultValue: false }), + cluster: schema.boolean({ defaultValue: false }), + indices: schema.boolean({ defaultValue: false }), + }), + }, + }, + async (ctx, request, response) => { + const reqShim = createRequestShim(request); + try { + return response.ok({ body: await upsertUIOpenOption(server, reqShim) }); + } catch (e) { + return response.internalError({ body: e }); + } + } + ); + + server.router.put( + { + path: '/api/upgrade_assistant/telemetry/ui_reindex', + validate: { + body: schema.object({ + close: schema.boolean({ defaultValue: false }), + open: schema.boolean({ defaultValue: false }), + start: schema.boolean({ defaultValue: false }), + stop: schema.boolean({ defaultValue: false }), + }), + }, + }, + async (ctx, request, response) => { + const reqShim = createRequestShim(request); + try { + return response.ok({ body: await upsertUIReindexOption(server, reqShim) }); + } catch (e) { + return response.internalError({ body: e }); + } + } + ); +} diff --git a/x-pack/legacy/plugins/upgrade_assistant/server/np_ready/types.ts b/x-pack/legacy/plugins/upgrade_assistant/server/np_ready/types.ts new file mode 100644 index 0000000000000..dc4ecbc806320 --- /dev/null +++ b/x-pack/legacy/plugins/upgrade_assistant/server/np_ready/types.ts @@ -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 { Legacy } from 'kibana'; +import { IRouter } from 'src/core/server'; +import { ElasticsearchPlugin } from 'src/legacy/core_plugins/elasticsearch'; +import { XPackMainPlugin } from '../../../xpack_main/xpack_main'; + +export interface ServerShim { + usage: { + collectorSet: { + makeUsageCollector: any; + register: any; + }; + }; + plugins: { + elasticsearch: ElasticsearchPlugin; + xpack_main: XPackMainPlugin; + cloud: { + config: { + isCloudEnabled: boolean; + }; + }; + }; + log: any; + events: any; + savedObjects: Legacy.SavedObjectsService; +} + +export interface ServerShimWithRouter extends ServerShim { + router: IRouter; +} + +export interface RequestShim { + headers: Record; + payload: any; + params: any; +} diff --git a/x-pack/legacy/plugins/upgrade_assistant/server/routes/cluster_checkup.ts b/x-pack/legacy/plugins/upgrade_assistant/server/routes/cluster_checkup.ts deleted file mode 100644 index 21c7bc4e5e65d..0000000000000 --- a/x-pack/legacy/plugins/upgrade_assistant/server/routes/cluster_checkup.ts +++ /dev/null @@ -1,38 +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 Boom from 'boom'; -import { Legacy } from 'kibana'; -import _ from 'lodash'; - -import { getUpgradeAssistantStatus } from '../lib/es_migration_apis'; -import { EsVersionPrecheck } from '../lib/es_version_precheck'; - -export function registerClusterCheckupRoutes(server: Legacy.Server) { - const { callWithRequest } = server.plugins.elasticsearch.getCluster('admin'); - const isCloudEnabled = _.get(server.plugins, 'cloud.config.isCloudEnabled', false); - - server.route({ - path: '/api/upgrade_assistant/status', - method: 'GET', - options: { - pre: [EsVersionPrecheck], - }, - async handler(request) { - try { - return await getUpgradeAssistantStatus(callWithRequest, request, isCloudEnabled); - } catch (e) { - if (e.status === 403) { - return Boom.forbidden(e.message); - } - - return Boom.boomify(e, { - statusCode: 500, - }); - } - }, - }); -} diff --git a/x-pack/legacy/plugins/upgrade_assistant/server/routes/deprecation_logging.test.ts b/x-pack/legacy/plugins/upgrade_assistant/server/routes/deprecation_logging.test.ts deleted file mode 100644 index e7918835d461d..0000000000000 --- a/x-pack/legacy/plugins/upgrade_assistant/server/routes/deprecation_logging.test.ts +++ /dev/null @@ -1,78 +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 { Server } from 'hapi'; - -jest.mock('../lib/es_version_precheck'); -import { registerDeprecationLoggingRoutes } from './deprecation_logging'; - -/** - * Since these route callbacks are so thin, these serve simply as integration tests - * to ensure they're wired up to the lib functions correctly. Business logic is tested - * more thoroughly in the es_deprecation_logging_apis test. - */ -describe('deprecation logging API', () => { - const callWithRequest = jest.fn(); - const server = new Server(); - server.plugins = { - elasticsearch: { - getCluster: () => ({ callWithRequest } as any), - } as any, - } as any; - - registerDeprecationLoggingRoutes(server); - - describe('GET /api/upgrade_assistant/deprecation_logging', () => { - it('returns isEnabled', async () => { - callWithRequest.mockResolvedValue({ default: { logger: { deprecation: 'WARN' } } }); - const resp = await server.inject({ - method: 'GET', - url: '/api/upgrade_assistant/deprecation_logging', - }); - - expect(resp.statusCode).toEqual(200); - expect(JSON.parse(resp.payload)).toEqual({ isEnabled: true }); - }); - - it('returns an error if it throws', async () => { - callWithRequest.mockRejectedValue(new Error(`scary error!`)); - const resp = await server.inject({ - method: 'GET', - url: '/api/upgrade_assistant/deprecation_logging', - }); - - expect(resp.statusCode).toEqual(500); - }); - }); - - describe('PUT /api/upgrade_assistant/deprecation_logging', () => { - it('returns isEnabled', async () => { - callWithRequest.mockResolvedValue({ default: { logger: { deprecation: 'ERROR' } } }); - const resp = await server.inject({ - method: 'GET', - url: '/api/upgrade_assistant/deprecation_logging', - payload: { - isEnabled: false, - }, - }); - - expect(JSON.parse(resp.payload)).toEqual({ isEnabled: false }); - }); - - it('returns an error if it throws', async () => { - callWithRequest.mockRejectedValue(new Error(`scary error!`)); - const resp = await server.inject({ - method: 'PUT', - url: '/api/upgrade_assistant/deprecation_logging', - payload: { - isEnabled: false, - }, - }); - - expect(resp.statusCode).toEqual(500); - }); - }); -}); diff --git a/x-pack/legacy/plugins/upgrade_assistant/server/routes/deprecation_logging.ts b/x-pack/legacy/plugins/upgrade_assistant/server/routes/deprecation_logging.ts deleted file mode 100644 index d16a87916ad7d..0000000000000 --- a/x-pack/legacy/plugins/upgrade_assistant/server/routes/deprecation_logging.ts +++ /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 Boom from 'boom'; -import Joi from 'joi'; -import { Legacy } from 'kibana'; - -import { - getDeprecationLoggingStatus, - setDeprecationLogging, -} from '../lib/es_deprecation_logging_apis'; -import { EsVersionPrecheck } from '../lib/es_version_precheck'; - -export function registerDeprecationLoggingRoutes(server: Legacy.Server) { - const { callWithRequest } = server.plugins.elasticsearch.getCluster('admin'); - - server.route({ - path: '/api/upgrade_assistant/deprecation_logging', - method: 'GET', - options: { - pre: [EsVersionPrecheck], - }, - async handler(request) { - try { - return await getDeprecationLoggingStatus(callWithRequest, request); - } catch (e) { - return Boom.boomify(e, { statusCode: 500 }); - } - }, - }); - - server.route({ - path: '/api/upgrade_assistant/deprecation_logging', - method: 'PUT', - options: { - pre: [EsVersionPrecheck], - validate: { - payload: Joi.object({ - isEnabled: Joi.boolean(), - }), - }, - }, - async handler(request) { - try { - const { isEnabled } = request.payload as { isEnabled: boolean }; - return await setDeprecationLogging(callWithRequest, request, isEnabled); - } catch (e) { - return Boom.boomify(e, { statusCode: 500 }); - } - }, - }); -} diff --git a/x-pack/legacy/plugins/upgrade_assistant/server/routes/telemetry.test.js b/x-pack/legacy/plugins/upgrade_assistant/server/routes/telemetry.test.js deleted file mode 100644 index a3706231f2297..0000000000000 --- a/x-pack/legacy/plugins/upgrade_assistant/server/routes/telemetry.test.js +++ /dev/null @@ -1,146 +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. - */ - -jest.mock('../lib/telemetry/es_ui_open_apis', () => ({ - upsertUIOpenOption: jest.fn(), -})); - -jest.mock('../lib/telemetry/es_ui_reindex_apis', () => ({ - upsertUIReindexOption: jest.fn(), -})); - -import { Server } from 'hapi'; -import { upsertUIOpenOption } from '../lib/telemetry/es_ui_open_apis'; -import { upsertUIReindexOption } from '../lib/telemetry/es_ui_reindex_apis'; -import { registerTelemetryRoutes } from './telemetry'; - -/** - * Since these route callbacks are so thin, these serve simply as integration tests - * to ensure they're wired up to the lib functions correctly. Business logic is tested - * more thoroughly in the lib/telemetry tests. - */ -describe('Upgrade Assistant Telemetry API', () => { - const server = new Server(); - - registerTelemetryRoutes(server); - - describe('PUT /api/upgrade_assistant/telemetry/ui_open', () => { - it('returns correct payload with single option', async () => { - const returnPayload = { - overview: true, - cluster: false, - indices: false, - }; - - upsertUIOpenOption.mockResolvedValue(returnPayload); - - const resp = await server.inject({ - method: 'PUT', - url: '/api/upgrade_assistant/telemetry/ui_open', - payload: { - overview: true, - }, - }); - - expect(JSON.parse(resp.payload)).toEqual(returnPayload); - }); - - it('returns correct payload with multiple option', async () => { - const returnPayload = { - overview: true, - cluster: true, - indices: true, - }; - - upsertUIOpenOption.mockResolvedValue(returnPayload); - - const resp = await server.inject({ - method: 'PUT', - url: '/api/upgrade_assistant/telemetry/ui_open', - payload: { - overview: true, - cluster: true, - indices: true, - }, - }); - - expect(JSON.parse(resp.payload)).toEqual(returnPayload); - }); - - it('returns an error if it throws', async () => { - upsertUIOpenOption.mockRejectedValue(new Error(`scary error!`)); - const resp = await server.inject({ - method: 'PUT', - url: '/api/upgrade_assistant/telemetry/ui_open', - payload: { - overview: false, - }, - }); - - expect(resp.statusCode).toEqual(500); - }); - }); - - describe('PUT /api/upgrade_assistant/telemetry/ui_reindex', () => { - it('returns correct payload with single option', async () => { - const returnPayload = { - close: false, - open: false, - start: true, - stop: false, - }; - - upsertUIReindexOption.mockResolvedValue(returnPayload); - - const resp = await server.inject({ - method: 'PUT', - url: '/api/upgrade_assistant/telemetry/ui_reindex', - payload: { - start: true, - }, - }); - - expect(JSON.parse(resp.payload)).toEqual(returnPayload); - }); - - it('returns correct payload with multiple option', async () => { - const returnPayload = { - close: true, - open: true, - start: true, - stop: true, - }; - - upsertUIReindexOption.mockResolvedValue(returnPayload); - - const resp = await server.inject({ - method: 'PUT', - url: '/api/upgrade_assistant/telemetry/ui_reindex', - payload: { - close: true, - open: true, - start: true, - stop: true, - }, - }); - - expect(JSON.parse(resp.payload)).toEqual(returnPayload); - }); - - it('returns an error if it throws', async () => { - upsertUIReindexOption.mockRejectedValue(new Error(`scary error!`)); - const resp = await server.inject({ - method: 'PUT', - url: '/api/upgrade_assistant/telemetry/ui_reindex', - payload: { - start: false, - }, - }); - - expect(resp.statusCode).toEqual(500); - }); - }); -}); diff --git a/x-pack/legacy/plugins/upgrade_assistant/server/routes/telemetry.ts b/x-pack/legacy/plugins/upgrade_assistant/server/routes/telemetry.ts deleted file mode 100644 index 6def6d1e72ea3..0000000000000 --- a/x-pack/legacy/plugins/upgrade_assistant/server/routes/telemetry.ts +++ /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 Boom from 'boom'; -import Joi from 'joi'; -import { UpgradeAssistantTelemetryServer } from '../../common/types'; -import { upsertUIOpenOption } from '../lib/telemetry/es_ui_open_apis'; -import { upsertUIReindexOption } from '../lib/telemetry/es_ui_reindex_apis'; - -export function registerTelemetryRoutes(server: UpgradeAssistantTelemetryServer) { - server.route({ - path: '/api/upgrade_assistant/telemetry/ui_open', - method: 'PUT', - options: { - validate: { - payload: Joi.object({ - overview: Joi.boolean().default(false), - cluster: Joi.boolean().default(false), - indices: Joi.boolean().default(false), - }), - }, - }, - async handler(request) { - try { - return await upsertUIOpenOption(server, request); - } catch (e) { - return Boom.boomify(e, { statusCode: 500 }); - } - }, - }); - - server.route({ - path: '/api/upgrade_assistant/telemetry/ui_reindex', - method: 'PUT', - options: { - validate: { - payload: Joi.object({ - close: Joi.boolean().default(false), - open: Joi.boolean().default(false), - start: Joi.boolean().default(false), - stop: Joi.boolean().default(false), - }), - }, - }, - async handler(request) { - try { - return await upsertUIReindexOption(server, request); - } catch (e) { - return Boom.boomify(e, { statusCode: 500 }); - } - }, - }); -} diff --git a/x-pack/legacy/plugins/uptime/public/apps/index.ts b/x-pack/legacy/plugins/uptime/public/apps/index.ts index 3b328b3ff2326..53a74022778f4 100644 --- a/x-pack/legacy/plugins/uptime/public/apps/index.ts +++ b/x-pack/legacy/plugins/uptime/public/apps/index.ts @@ -8,4 +8,7 @@ import chrome from 'ui/chrome'; import { npStart } from 'ui/new_platform'; import { Plugin } from './plugin'; -new Plugin({ opaqueId: Symbol('uptime'), env: {} as any }, chrome).start(npStart); +new Plugin( + { opaqueId: Symbol('uptime'), env: {} as any, config: { get: () => ({} as any) } }, + chrome +).start(npStart); diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/__tests__/__snapshots__/monitor_ssl_certificate.test.tsx.snap b/x-pack/legacy/plugins/uptime/public/components/functional/__tests__/__snapshots__/monitor_ssl_certificate.test.tsx.snap index 56bc101f59dfa..45c24fd11194d 100644 --- a/x-pack/legacy/plugins/uptime/public/components/functional/__tests__/__snapshots__/monitor_ssl_certificate.test.tsx.snap +++ b/x-pack/legacy/plugins/uptime/public/components/functional/__tests__/__snapshots__/monitor_ssl_certificate.test.tsx.snap @@ -5,8 +5,12 @@ Array [

, -
@@ -40,13 +61,13 @@ exports[`DonutChart component renders a donut chart 1`] = ` class="euiFlexItem" >
Down 32 @@ -91,7 +112,7 @@ exports[`DonutChart component renders a donut chart 1`] = ` class="euiFlexGroup euiFlexGroup--gutterLarge euiFlexGroup--directionRow" >
Up 95 diff --git a/x-pack/legacy/plugins/uptime/public/lib/adapters/framework/__tests__/__snapshots__/kibana_global_help.test.tsx.snap b/x-pack/legacy/plugins/uptime/public/lib/adapters/framework/__tests__/__snapshots__/kibana_global_help.test.tsx.snap deleted file mode 100644 index b3f749b12d9d1..0000000000000 --- a/x-pack/legacy/plugins/uptime/public/lib/adapters/framework/__tests__/__snapshots__/kibana_global_help.test.tsx.snap +++ /dev/null @@ -1,43 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`renderUptimeKibanaGlobalHelp renders links with expected urls 1`] = ` - - - - - For Uptime specific information - - - - - - - - - - -`; diff --git a/x-pack/legacy/plugins/uptime/public/lib/adapters/framework/__tests__/kibana_global_help.test.tsx b/x-pack/legacy/plugins/uptime/public/lib/adapters/framework/__tests__/kibana_global_help.test.tsx deleted file mode 100644 index a4791a41e0347..0000000000000 --- a/x-pack/legacy/plugins/uptime/public/lib/adapters/framework/__tests__/kibana_global_help.test.tsx +++ /dev/null @@ -1,13 +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 { renderUptimeKibanaGlobalHelp } from '../kibana_global_help'; - -describe('renderUptimeKibanaGlobalHelp', () => { - it('renders links with expected urls', () => { - expect(renderUptimeKibanaGlobalHelp('https://elastic.co/', 'master')).toMatchSnapshot(); - }); -}); diff --git a/x-pack/legacy/plugins/uptime/public/lib/adapters/framework/kibana_global_help.tsx b/x-pack/legacy/plugins/uptime/public/lib/adapters/framework/kibana_global_help.tsx deleted file mode 100644 index 8e730dcc29310..0000000000000 --- a/x-pack/legacy/plugins/uptime/public/lib/adapters/framework/kibana_global_help.tsx +++ /dev/null @@ -1,48 +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 { EuiLink, EuiSpacer, EuiHorizontalRule, EuiButton, EuiText } from '@elastic/eui'; -import { i18n } from '@kbn/i18n'; -import { FormattedMessage } from '@kbn/i18n/react'; -import React from 'react'; - -export const renderUptimeKibanaGlobalHelp = (docsSiteUrl: string, docLinkVersion: string) => ( - - - - For Uptime specific information - - - - - - - - - -); diff --git a/x-pack/legacy/plugins/uptime/public/lib/adapters/framework/new_platform_adapter.tsx b/x-pack/legacy/plugins/uptime/public/lib/adapters/framework/new_platform_adapter.tsx index 44191d7e61e0d..94bfe79a6ca6e 100644 --- a/x-pack/legacy/plugins/uptime/public/lib/adapters/framework/new_platform_adapter.tsx +++ b/x-pack/legacy/plugins/uptime/public/lib/adapters/framework/new_platform_adapter.tsx @@ -9,12 +9,12 @@ import React from 'react'; import ReactDOM from 'react-dom'; import { get } from 'lodash'; import { AutocompleteProviderRegister } from 'src/plugins/data/public'; +import { i18n as i18nFormatter } from '@kbn/i18n'; import { CreateGraphQLClient } from './framework_adapter_types'; import { UptimeApp, UptimeAppProps } from '../../../uptime_app'; import { getIntegratedAppAvailability } from './capabilities_adapter'; import { INTEGRATED_SOLUTIONS, PLUGIN } from '../../../../common/constants'; import { getTelemetryMonitorPageLogger, getTelemetryOverviewPageLogger } from '../telemetry'; -import { renderUptimeKibanaGlobalHelp } from './kibana_global_help'; import { UMFrameworkAdapter, BootstrapUptimeApp } from '../../lib'; import { createApolloClient } from './apollo_client_adapter'; @@ -52,12 +52,20 @@ export const getKibanaFrameworkAdapter = ( logMonitorPageLoad: getTelemetryMonitorPageLogger('true', basePath.get()), logOverviewPageLoad: getTelemetryOverviewPageLogger('true', basePath.get()), renderGlobalHelpControls: () => - setHelpExtension((element: HTMLElement) => { - ReactDOM.render( - renderUptimeKibanaGlobalHelp(ELASTIC_WEBSITE_URL, DOC_LINK_VERSION), - element - ); - return () => ReactDOM.unmountComponentAtNode(element); + setHelpExtension({ + appName: i18nFormatter.translate('xpack.uptime.header.appName', { + defaultMessage: 'Uptime', + }), + links: [ + { + linkType: 'documentation', + href: `${ELASTIC_WEBSITE_URL}guide/en/kibana/${DOC_LINK_VERSION}/xpack-uptime.html`, + }, + { + linkType: 'discuss', + href: 'https://discuss.elastic.co/c/uptime', + }, + ], }), routerBasename: basePath.prepend(PLUGIN.ROUTER_BASE_NAME), setBadge, diff --git a/x-pack/package.json b/x-pack/package.json index 5a74d4fd76c9c..38127ed48ab85 100644 --- a/x-pack/package.json +++ b/x-pack/package.json @@ -98,7 +98,7 @@ "@types/reduce-reducers": "^0.3.0", "@types/redux-actions": "^2.2.1", "@types/sinon": "^7.0.13", - "@types/styled-components": "^3.0.2", + "@types/styled-components": "^4.4.0", "@types/supertest": "^2.0.5", "@types/tar-fs": "^1.16.1", "@types/tinycolor2": "^1.4.1", @@ -116,11 +116,12 @@ "cheerio": "0.22.0", "commander": "3.0.0", "copy-webpack-plugin": "^5.0.4", - "cypress": "^3.5.5", + "cypress": "^3.6.1", + "cypress-multi-reporters": "^1.2.3", "enzyme": "^3.10.0", - "enzyme-adapter-react-16": "^1.14.0", - "enzyme-adapter-utils": "^1.12.0", - "enzyme-to-json": "^3.3.4", + "enzyme-adapter-react-16": "^1.15.1", + "enzyme-adapter-utils": "^1.12.1", + "enzyme-to-json": "^3.4.3", "execa": "^3.2.0", "fancy-log": "^1.3.2", "fetch-mock": "^7.3.9", @@ -136,12 +137,12 @@ "hapi": "^17.5.3", "jest": "^24.9.0", "jest-cli": "^24.9.0", - "jest-styled-components": "^6.3.3", + "jest-styled-components": "^7.0.0-beta.2", "jsdom": "^12.2.0", "madge": "3.4.4", - "mocha": "6.2.1", + "marge": "^1.0.1", + "mocha": "^6.2.2", "mocha-junit-reporter": "^1.23.1", - "mocha-multi-reporters": "^1.1.7", "mochawesome": "^4.1.0", "mochawesome-merge": "^2.0.1", "mustache": "^2.3.0", @@ -176,10 +177,9 @@ "@babel/core": "^7.5.5", "@babel/register": "^7.5.5", "@babel/runtime": "^7.5.5", - "@elastic/ctags-langserver": "^0.1.11", "@elastic/datemath": "5.0.2", "@elastic/ems-client": "1.0.5", - "@elastic/eui": "14.9.0", + "@elastic/eui": "16.0.0", "@elastic/filesaver": "1.1.2", "@elastic/javascript-typescript-langserver": "^0.3.3", "@elastic/lsp-extension": "^0.1.2", @@ -334,7 +334,7 @@ "squel": "^5.13.0", "stats-lite": "^2.2.0", "style-it": "^2.1.3", - "styled-components": "3.4.10", + "styled-components": "beta", "suricata-sid-db": "^1.0.2", "tinycolor2": "1.4.1", "tinymath": "1.2.1", @@ -358,10 +358,9 @@ }, "workspaces": { "nohoist": [ - "**/mochawesome", - "**/mochawesome/**", - "**/mocha-multi-reporters", - "**/mocha-multi-reporters/**" + "mochawesome", + "mochawesome-merge", + "cypress-multi-reporters" ] } } diff --git a/x-pack/plugins/licensing/public/plugin.test.ts b/x-pack/plugins/licensing/public/plugin.test.ts index 8ede881cad47e..60dfd1f6cb260 100644 --- a/x-pack/plugins/licensing/public/plugin.test.ts +++ b/x-pack/plugins/licensing/public/plugin.test.ts @@ -38,6 +38,25 @@ describe('licensing plugin', () => { expect(license.uid).toBe('fetched'); }); + + it('data re-fetch call marked as a system api', async () => { + const sessionStorage = coreMock.createStorage(); + plugin = new LicensingPlugin(coreMock.createPluginInitializerContext(), sessionStorage); + + const coreSetup = coreMock.createSetup(); + const fetchedLicense = licenseMock.create(); + coreSetup.http.get.mockResolvedValue(fetchedLicense); + + const { refresh } = await plugin.setup(coreSetup); + + refresh(); + + expect(coreSetup.http.get.mock.calls[0][1]).toMatchObject({ + headers: { + 'kbn-system-api': 'true', + }, + }); + }); }); describe('#license$', () => { @@ -238,7 +257,7 @@ describe('licensing plugin', () => { }, }, request: { - url: 'http://10.10.10.10:5601/api/xpack/v1/info', + url: 'http://10.10.10.10:5601/api/licensing/info', }, }; expect(coreSetup.http.get).toHaveBeenCalledTimes(0); diff --git a/x-pack/plugins/licensing/public/plugin.ts b/x-pack/plugins/licensing/public/plugin.ts index c1b13418aa3e7..79ad6f289b67e 100644 --- a/x-pack/plugins/licensing/public/plugin.ts +++ b/x-pack/plugins/licensing/public/plugin.ts @@ -5,7 +5,7 @@ */ import { Subject, Subscription, merge } from 'rxjs'; -import { takeUntil, tap } from 'rxjs/operators'; +import { takeUntil } from 'rxjs/operators'; import { CoreSetup, Plugin, PluginInitializerContext } from 'src/core/public'; @@ -31,8 +31,9 @@ export class LicensingPlugin implements Plugin { */ private removeInterceptor?: () => void; private licenseFetchSubscription?: Subscription; + private storageSubscription?: Subscription; - private infoEndpoint = '/api/xpack/v1/info'; + private readonly infoEndpoint = '/api/licensing/info'; private prevSignature?: string; constructor( @@ -76,18 +77,16 @@ export class LicensingPlugin implements Plugin { ); this.licenseFetchSubscription = fetchSubscription; - const license$ = update$.pipe( - tap(license => { - if (license.error) { - this.prevSignature = undefined; - // Prevent reusing stale license if the fetch operation fails - this.removeSaved(); - } else { - this.prevSignature = license.signature; - this.save(license); - } - }) - ); + this.storageSubscription = update$.subscribe(license => { + if (license.isAvailable) { + this.prevSignature = license.signature; + this.save(license); + } else { + this.prevSignature = undefined; + // Prevent reusing stale license if the fetch operation fails + this.removeSaved(); + } + }); this.removeInterceptor = core.http.intercept({ response: async httpResponse => { @@ -107,7 +106,7 @@ export class LicensingPlugin implements Plugin { refresh: () => { manualRefresh$.next(); }, - license$, + license$: update$, }; } @@ -124,11 +123,20 @@ export class LicensingPlugin implements Plugin { this.licenseFetchSubscription.unsubscribe(); this.licenseFetchSubscription = undefined; } + if (this.storageSubscription !== undefined) { + this.storageSubscription.unsubscribe(); + this.storageSubscription = undefined; + } } private fetchLicense = async (core: CoreSetup): Promise => { try { - const response = await core.http.get(this.infoEndpoint); + const response = await core.http.get(this.infoEndpoint, { + headers: { + 'kbn-system-api': 'true', + }, + }); + return new License({ license: response.license, features: response.features, diff --git a/x-pack/plugins/licensing/server/plugin.ts b/x-pack/plugins/licensing/server/plugin.ts index 3c93b55723787..d3dc84c05e25c 100644 --- a/x-pack/plugins/licensing/server/plugin.ts +++ b/x-pack/plugins/licensing/server/plugin.ts @@ -24,6 +24,8 @@ import { License } from '../common/license'; import { createLicenseUpdate } from '../common/license_update'; import { ElasticsearchError, RawLicense, RawFeatures } from './types'; +import { registerRoutes } from './routes'; + import { LicenseConfigType } from './licensing_config'; import { createRouteHandlerContext } from './licensing_route_handler_context'; @@ -92,6 +94,7 @@ export class LicensingPlugin implements Plugin { const { refresh, license$ } = this.createLicensePoller(dataClient, config.pollingFrequency); core.http.registerRouteHandlerContext('licensing', createRouteHandlerContext(license$)); + registerRoutes(core.http.createRouter()); return { refresh, diff --git a/x-pack/plugins/licensing/server/routes/index.ts b/x-pack/plugins/licensing/server/routes/index.ts new file mode 100644 index 0000000000000..26b3bc6292dd6 --- /dev/null +++ b/x-pack/plugins/licensing/server/routes/index.ts @@ -0,0 +1,11 @@ +/* + * 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 { IRouter } from 'src/core/server'; +import { registerInfoRoute } from './info'; + +export function registerRoutes(router: IRouter) { + registerInfoRoute(router); +} diff --git a/x-pack/plugins/licensing/server/routes/info.ts b/x-pack/plugins/licensing/server/routes/info.ts new file mode 100644 index 0000000000000..cad873014e271 --- /dev/null +++ b/x-pack/plugins/licensing/server/routes/info.ts @@ -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 { IRouter } from 'src/core/server'; + +export function registerInfoRoute(router: IRouter) { + router.get({ path: '/api/licensing/info', validate: false }, (context, request, response) => { + return response.ok({ + body: context.licensing.license, + }); + }); +} diff --git a/x-pack/plugins/security/server/authentication/providers/kerberos.test.ts b/x-pack/plugins/security/server/authentication/providers/kerberos.test.ts index 4ab47cb95b9a3..27105793fc966 100644 --- a/x-pack/plugins/security/server/authentication/providers/kerberos.test.ts +++ b/x-pack/plugins/security/server/authentication/providers/kerberos.test.ts @@ -574,7 +574,7 @@ describe('KerberosAuthenticationProvider', () => { sinon.assert.calledWithExactly(mockOptions.tokens.invalidate, tokenPair); expect(authenticationResult.redirected()).toBe(true); - expect(authenticationResult.redirectURL).toBe('/logged_out'); + expect(authenticationResult.redirectURL).toBe('/mock-server-basepath/logged_out'); }); }); }); diff --git a/x-pack/plugins/security/server/authentication/providers/kerberos.ts b/x-pack/plugins/security/server/authentication/providers/kerberos.ts index 0e31dd3d51aba..767eab7b4311d 100644 --- a/x-pack/plugins/security/server/authentication/providers/kerberos.ts +++ b/x-pack/plugins/security/server/authentication/providers/kerberos.ts @@ -107,7 +107,7 @@ export class KerberosAuthenticationProvider extends BaseAuthenticationProvider { return DeauthenticationResult.failed(err); } - return DeauthenticationResult.redirectTo('/logged_out'); + return DeauthenticationResult.redirectTo(`${this.options.basePath.serverBasePath}/logged_out`); } /** diff --git a/x-pack/plugins/security/server/authentication/providers/oidc.test.ts b/x-pack/plugins/security/server/authentication/providers/oidc.test.ts index 7e00d8f282f62..c1d7dcca4c78f 100644 --- a/x-pack/plugins/security/server/authentication/providers/oidc.test.ts +++ b/x-pack/plugins/security/server/authentication/providers/oidc.test.ts @@ -598,7 +598,7 @@ describe('OIDCAuthenticationProvider', () => { }); expect(authenticationResult.redirected()).toBe(true); - expect(authenticationResult.redirectURL).toBe('/base-path/logged_out'); + expect(authenticationResult.redirectURL).toBe('/mock-server-basepath/logged_out'); }); it('redirects user to the OpenID Connect Provider if RP initiated SLO is supported.', async () => { diff --git a/x-pack/plugins/security/server/authentication/providers/oidc.ts b/x-pack/plugins/security/server/authentication/providers/oidc.ts index 824189fa77a26..3737123645379 100644 --- a/x-pack/plugins/security/server/authentication/providers/oidc.ts +++ b/x-pack/plugins/security/server/authentication/providers/oidc.ts @@ -431,7 +431,9 @@ export class OIDCAuthenticationProvider extends BaseAuthenticationProvider { return DeauthenticationResult.redirectTo(redirect); } - return DeauthenticationResult.redirectTo(`${this.options.basePath.get(request)}/logged_out`); + return DeauthenticationResult.redirectTo( + `${this.options.basePath.serverBasePath}/logged_out` + ); } catch (err) { this.logger.debug(`Failed to deauthenticate user: ${err.message}`); return DeauthenticationResult.failed(err); diff --git a/x-pack/plugins/security/server/authentication/providers/pki.test.ts b/x-pack/plugins/security/server/authentication/providers/pki.test.ts index 35d827c3a9bd1..76442733e7368 100644 --- a/x-pack/plugins/security/server/authentication/providers/pki.test.ts +++ b/x-pack/plugins/security/server/authentication/providers/pki.test.ts @@ -583,7 +583,7 @@ describe('PKIAuthenticationProvider', () => { expect(mockOptions.tokens.invalidate).toHaveBeenCalledWith({ accessToken: 'foo' }); expect(authenticationResult.redirected()).toBe(true); - expect(authenticationResult.redirectURL).toBe('/logged_out'); + expect(authenticationResult.redirectURL).toBe('/mock-server-basepath/logged_out'); }); }); }); diff --git a/x-pack/plugins/security/server/authentication/providers/pki.ts b/x-pack/plugins/security/server/authentication/providers/pki.ts index fa3e1959ba7de..c7d431422a248 100644 --- a/x-pack/plugins/security/server/authentication/providers/pki.ts +++ b/x-pack/plugins/security/server/authentication/providers/pki.ts @@ -111,7 +111,7 @@ export class PKIAuthenticationProvider extends BaseAuthenticationProvider { return DeauthenticationResult.failed(err); } - return DeauthenticationResult.redirectTo('/logged_out'); + return DeauthenticationResult.redirectTo(`${this.options.basePath.serverBasePath}/logged_out`); } /** diff --git a/x-pack/plugins/security/server/authentication/providers/saml.test.ts b/x-pack/plugins/security/server/authentication/providers/saml.test.ts index 7ef1d934a7d13..27702f70865ea 100644 --- a/x-pack/plugins/security/server/authentication/providers/saml.test.ts +++ b/x-pack/plugins/security/server/authentication/providers/saml.test.ts @@ -1045,7 +1045,7 @@ describe('SAMLAuthenticationProvider', () => { }); expect(authenticationResult.redirected()).toBe(true); - expect(authenticationResult.redirectURL).toBe('/logged_out'); + expect(authenticationResult.redirectURL).toBe('/mock-server-basepath/logged_out'); }); it('redirects to /logged_out if `redirect` field in SAML logout response is not defined.', async () => { @@ -1069,7 +1069,7 @@ describe('SAMLAuthenticationProvider', () => { }); expect(authenticationResult.redirected()).toBe(true); - expect(authenticationResult.redirectURL).toBe('/logged_out'); + expect(authenticationResult.redirectURL).toBe('/mock-server-basepath/logged_out'); }); it('relies on SAML logout if query string is not empty, but does not include SAMLRequest.', async () => { @@ -1095,7 +1095,7 @@ describe('SAMLAuthenticationProvider', () => { }); expect(authenticationResult.redirected()).toBe(true); - expect(authenticationResult.redirectURL).toBe('/logged_out'); + expect(authenticationResult.redirectURL).toBe('/mock-server-basepath/logged_out'); }); it('relies on SAML invalidate call even if access token is presented.', async () => { @@ -1119,7 +1119,7 @@ describe('SAMLAuthenticationProvider', () => { ); expect(authenticationResult.redirected()).toBe(true); - expect(authenticationResult.redirectURL).toBe('/logged_out'); + expect(authenticationResult.redirectURL).toBe('/mock-server-basepath/logged_out'); }); it('redirects to /logged_out if `redirect` field in SAML invalidate response is null.', async () => { @@ -1139,7 +1139,7 @@ describe('SAMLAuthenticationProvider', () => { ); expect(authenticationResult.redirected()).toBe(true); - expect(authenticationResult.redirectURL).toBe('/logged_out'); + expect(authenticationResult.redirectURL).toBe('/mock-server-basepath/logged_out'); }); it('redirects to /logged_out if `redirect` field in SAML invalidate response is not defined.', async () => { @@ -1159,7 +1159,7 @@ describe('SAMLAuthenticationProvider', () => { ); expect(authenticationResult.redirected()).toBe(true); - expect(authenticationResult.redirectURL).toBe('/logged_out'); + expect(authenticationResult.redirectURL).toBe('/mock-server-basepath/logged_out'); }); it('redirects user to the IdP if SLO is supported by IdP in case of SP initiated logout.', async () => { diff --git a/x-pack/plugins/security/server/authentication/providers/saml.ts b/x-pack/plugins/security/server/authentication/providers/saml.ts index a8683796293af..faa19239fcc3b 100644 --- a/x-pack/plugins/security/server/authentication/providers/saml.ts +++ b/x-pack/plugins/security/server/authentication/providers/saml.ts @@ -228,7 +228,9 @@ export class SAMLAuthenticationProvider extends BaseAuthenticationProvider { return DeauthenticationResult.redirectTo(redirect); } - return DeauthenticationResult.redirectTo('/logged_out'); + return DeauthenticationResult.redirectTo( + `${this.options.basePath.serverBasePath}/logged_out` + ); } catch (err) { this.logger.debug(`Failed to deauthenticate user: ${err.message}`); return DeauthenticationResult.failed(err); diff --git a/x-pack/plugins/translations/translations/ja-JP.json b/x-pack/plugins/translations/translations/ja-JP.json index 5b59036b89f49..8312ba3d0c83f 100644 --- a/x-pack/plugins/translations/translations/ja-JP.json +++ b/x-pack/plugins/translations/translations/ja-JP.json @@ -3359,7 +3359,6 @@ "xpack.apm.errorsTable.occurrencesColumnLabel": "オカレンス", "xpack.apm.errorsTable.unhandledLabel": "未対応", "xpack.apm.featureRegistry.apmFeatureName": "APM", - "xpack.apm.feedbackMenu.provideFeedbackTitle": "APM のフィードバックを提供", "xpack.apm.filter.environment.allLabel": "すべて", "xpack.apm.filter.environment.label": "環境", "xpack.apm.filter.environment.notDefinedLabel": "未定義", @@ -5845,7 +5844,6 @@ "xpack.infra.homePage.noMetricsIndicesTitle": "メトリックインデックスがないようです。", "xpack.infra.homePage.toolbar.kqlSearchFieldPlaceholder": "インフラストラクチャーデータを検索… (例: host.name:host-1)", "xpack.infra.homePage.toolbar.showingLastOneMinuteDataText": "指定期間の最後の 1 分間のデータを表示中", - "xpack.infra.infrastructure.infrastructureHelpContent.feedbackLinkText": "インフラストラクチャーのフィードバックを提供", "xpack.infra.infrastructureDescription": "インフラストラクチャーを閲覧します", "xpack.infra.infrastructureMetricsExplorerPage.documentTitle": "{previousTitle} | メトリックエクスプローラー", "xpack.infra.infrastructureSnapshotPage.documentTitle": "{previousTitle} | インベントリ", @@ -5896,7 +5894,6 @@ "xpack.infra.logs.stopStreamingButtonLabel": "ストリーム停止", "xpack.infra.logs.streamingDescription": "新しいエントリーをストリーム中...", "xpack.infra.logs.streamingNewEntriesText": "新しいエントリーをストリーム中", - "xpack.infra.logsPage.logsHelpContent.feedbackLinkText": "ログのフィードバックを提供", "xpack.infra.logsPage.noLoggingIndicesDescription": "追加しましょう!", "xpack.infra.logsPage.noLoggingIndicesInstructionsActionLabel": "セットアップの手順を表示", "xpack.infra.logsPage.noLoggingIndicesTitle": "ログインデックスがないようです。", @@ -6420,8 +6417,6 @@ "xpack.maps.heatmap.colorRampLabel": "色の範囲", "xpack.maps.heatmapLegend.coldLabel": "コールド", "xpack.maps.heatmapLegend.hotLabel": "ホット", - "xpack.maps.helpMenu.docLabel": "Maps ドキュメンテーション", - "xpack.maps.helpMenu.feedbackLinkText": "Maps アプリケーションに関するフィードバックを提供", "xpack.maps.inspector.centerLatLabel": "中央緯度", "xpack.maps.inspector.centerLonLabel": "中央経度", "xpack.maps.inspector.mapboxStyleTitle": "マップボックススタイル", @@ -10367,8 +10362,6 @@ "xpack.siem.certificate.fingerprint.clientCertLabel": "クライアント証明書", "xpack.siem.certificate.fingerprint.serverCertLabel": "サーバー証明書", "xpack.siem.chart.dataNotAvailableTitle": "チャートデータが利用できません", - "xpack.siem.chrome.help.feedback": "フィードバックを送信", - "xpack.siem.chrome.help.title": "SIEM アプリケーションのヘルプ", "xpack.siem.clipboard.copied": "コピー完了", "xpack.siem.clipboard.copy": "コピー", "xpack.siem.clipboard.to.the.clipboard": "クリップボードに", @@ -11799,8 +11792,6 @@ "xpack.uptime.filterBar.options.location.name": "場所", "xpack.uptime.filterBar.options.portLabel": "ポート", "xpack.uptime.filterBar.options.schemeLabel": "スキーム", - "xpack.uptime.header.helpLinkAriaLabel": "ディスカッションページへ移動", - "xpack.uptime.header.helpLinkText": "アップタイムのフィードバックを提供", "xpack.uptime.integrationLink.missingDataMessage": "この統合に必要なデータが見つかりませんでした。", "xpack.uptime.monitorCharts.checkStatus.series.downCountLabel": "ダウンカウント", "xpack.uptime.monitorCharts.checkStatus.series.upCountLabel": "アップカウント", @@ -11862,8 +11853,6 @@ "xpack.uptime.snapshotHistogram.series.upLabel": "アップ", "xpack.uptime.uptimeFeatureCatalogueTitle": "起動時間", "xpack.uptime.emptyState.noDataMessage": "アップタイムデータが見つかりませんでした", - "xpack.uptime.header.docsLinkAriaLabel": "アップタイムドキュメンテーションに移動", - "xpack.uptime.header.documentationLinkText": "アップタイムドキュメンテーション", "xpack.uptime.pingList.collapseRow": "縮小", "xpack.uptime.pingList.durationMsColumnFormatting": "{millis}ミリ秒", "xpack.uptime.pingList.expandedRow.bodySize": "本文サイズは {bodyBytes} です。", @@ -12666,8 +12655,6 @@ "xpack.lens.functions.mergeTables.help": "いくつかの Kibana 表を 1 つの表に結合するのをアシストします", "xpack.lens.functions.renameColumns.help": "データベースの列の名前の変更をアシストします", "xpack.lens.functions.renameColumns.idMap.help": "キーが古い列 ID で値が対応する新しい列 ID となるように JSON エンコーディングされたオブジェクトです。他の列 ID はすべてのそのままです。", - "xpack.lens.helpMenu.docLabel": "レンズドキュメンテーション", - "xpack.lens.helpMenu.feedbackLinkText": "レンズアプリケーションに関するフィードバックを提供", "xpack.lens.indexPattern.avg": "平均", "xpack.lens.indexPattern.avgOf": "{name} の平均", "xpack.lens.indexPattern.cardinality": "ユニークカウント", diff --git a/x-pack/plugins/translations/translations/zh-CN.json b/x-pack/plugins/translations/translations/zh-CN.json index 2b3c788125e6a..f90d2f9522c31 100644 --- a/x-pack/plugins/translations/translations/zh-CN.json +++ b/x-pack/plugins/translations/translations/zh-CN.json @@ -3360,7 +3360,6 @@ "xpack.apm.errorsTable.occurrencesColumnLabel": "发生次数", "xpack.apm.errorsTable.unhandledLabel": "未处理", "xpack.apm.featureRegistry.apmFeatureName": "APM", - "xpack.apm.feedbackMenu.provideFeedbackTitle": "提供 APM 的反馈", "xpack.apm.filter.environment.allLabel": "全部", "xpack.apm.filter.environment.label": "环境", "xpack.apm.filter.environment.notDefinedLabel": "未定义", @@ -5847,7 +5846,6 @@ "xpack.infra.homePage.noMetricsIndicesTitle": "似乎您没有任何指标索引。", "xpack.infra.homePage.toolbar.kqlSearchFieldPlaceholder": "搜索基础设施数据……(例如 host.name:host-1)", "xpack.infra.homePage.toolbar.showingLastOneMinuteDataText": "在选定时间显示过去 1 分钟的数据", - "xpack.infra.infrastructure.infrastructureHelpContent.feedbackLinkText": "提供 Infrastructure 的反馈", "xpack.infra.infrastructureDescription": "浏览您的基础设施", "xpack.infra.infrastructureMetricsExplorerPage.documentTitle": "{previousTitle} | 指标浏览器", "xpack.infra.infrastructureSnapshotPage.documentTitle": "{previousTitle} | 库存", @@ -5898,7 +5896,6 @@ "xpack.infra.logs.stopStreamingButtonLabel": "停止流式传输", "xpack.infra.logs.streamingDescription": "正在流式传输新条目……", "xpack.infra.logs.streamingNewEntriesText": "正在流式传输新条目", - "xpack.infra.logsPage.logsHelpContent.feedbackLinkText": "提供 Logs 的反馈", "xpack.infra.logsPage.noLoggingIndicesDescription": "让我们添加一些!", "xpack.infra.logsPage.noLoggingIndicesInstructionsActionLabel": "查看设置说明", "xpack.infra.logsPage.noLoggingIndicesTitle": "似乎您没有任何日志索引。", @@ -6422,8 +6419,6 @@ "xpack.maps.heatmap.colorRampLabel": "颜色范围", "xpack.maps.heatmapLegend.coldLabel": "冷", "xpack.maps.heatmapLegend.hotLabel": "热", - "xpack.maps.helpMenu.docLabel": "地图文档", - "xpack.maps.helpMenu.feedbackLinkText": "提供 Maps 应用程序的反馈", "xpack.maps.inspector.centerLatLabel": "中心纬度", "xpack.maps.inspector.centerLonLabel": "中心经度", "xpack.maps.inspector.mapboxStyleTitle": "Mapbox 样式", @@ -10457,8 +10452,6 @@ "xpack.siem.certificate.fingerprint.clientCertLabel": "客户端证书", "xpack.siem.certificate.fingerprint.serverCertLabel": "服务器证书", "xpack.siem.chart.dataNotAvailableTitle": "图表数据不可用", - "xpack.siem.chrome.help.feedback": "提交反馈", - "xpack.siem.chrome.help.title": "SIEM 应用程序帮助", "xpack.siem.clipboard.copied": "已复制", "xpack.siem.clipboard.copy": "复制", "xpack.siem.clipboard.to.the.clipboard": "至剪贴板", @@ -11889,8 +11882,6 @@ "xpack.uptime.filterBar.options.location.name": "位置", "xpack.uptime.filterBar.options.portLabel": "端口", "xpack.uptime.filterBar.options.schemeLabel": "方案", - "xpack.uptime.header.helpLinkAriaLabel": "前往我们的讨论页", - "xpack.uptime.header.helpLinkText": "提供运行时间反馈", "xpack.uptime.integrationLink.missingDataMessage": "未找到此集成的所需数据。", "xpack.uptime.monitorCharts.checkStatus.series.downCountLabel": "关闭计数", "xpack.uptime.monitorCharts.checkStatus.series.upCountLabel": "运行计数", @@ -11952,8 +11943,6 @@ "xpack.uptime.snapshotHistogram.series.upLabel": "运行", "xpack.uptime.uptimeFeatureCatalogueTitle": "运行时间", "xpack.uptime.emptyState.noDataMessage": "未找到任何运行时间数据", - "xpack.uptime.header.docsLinkAriaLabel": "前往 Uptime 文档", - "xpack.uptime.header.documentationLinkText": "Uptime 文档", "xpack.uptime.pingList.collapseRow": "折叠", "xpack.uptime.pingList.durationMsColumnFormatting": "{millis} 毫秒", "xpack.uptime.pingList.expandedRow.bodySize": "正文大小为 {bodyBytes}。", @@ -12756,8 +12745,6 @@ "xpack.lens.functions.mergeTables.help": "将任何数目的 kibana 表合并成单个表的助手", "xpack.lens.functions.renameColumns.help": "用于重命名数据表列的助手", "xpack.lens.functions.renameColumns.idMap.help": "旧列 ID 为键且相应新列 ID 为值的 JSON 编码对象。所有其他列 ID 都将保留。", - "xpack.lens.helpMenu.docLabel": "Lens 文档", - "xpack.lens.helpMenu.feedbackLinkText": "提供 Lens 应用程序的反馈", "xpack.lens.indexPattern.avg": "平均值", "xpack.lens.indexPattern.avgOf": "{name} 的平均值", "xpack.lens.indexPattern.cardinality": "唯一计数", diff --git a/x-pack/test/alerting_api_integration/security_and_spaces/tests/actions/builtin_action_types/es_index.ts b/x-pack/test/alerting_api_integration/security_and_spaces/tests/actions/builtin_action_types/es_index.ts index b9b40be3a04b3..648944a9256b2 100644 --- a/x-pack/test/alerting_api_integration/security_and_spaces/tests/actions/builtin_action_types/es_index.ts +++ b/x-pack/test/alerting_api_integration/security_and_spaces/tests/actions/builtin_action_types/es_index.ts @@ -12,7 +12,7 @@ const ES_TEST_INDEX_NAME = 'functional-test-actions-index'; // eslint-disable-next-line import/no-default-export export default function indexTest({ getService }: FtrProviderContext) { - const es = getService('es'); + const es = getService('legacyEs'); const supertest = getService('supertest'); const esArchiver = getService('esArchiver'); diff --git a/x-pack/test/alerting_api_integration/security_and_spaces/tests/actions/execute.ts b/x-pack/test/alerting_api_integration/security_and_spaces/tests/actions/execute.ts index 44970a9260c42..0c05ad3e3e68a 100644 --- a/x-pack/test/alerting_api_integration/security_and_spaces/tests/actions/execute.ts +++ b/x-pack/test/alerting_api_integration/security_and_spaces/tests/actions/execute.ts @@ -18,7 +18,7 @@ import { FtrProviderContext } from '../../../common/ftr_provider_context'; export default function({ getService }: FtrProviderContext) { const supertest = getService('supertest'); const supertestWithoutAuth = getService('supertestWithoutAuth'); - const es = getService('es'); + const es = getService('legacyEs'); const retry = getService('retry'); const esTestIndexTool = new ESTestIndexTool(es, retry); diff --git a/x-pack/test/alerting_api_integration/security_and_spaces/tests/alerting/alerts.ts b/x-pack/test/alerting_api_integration/security_and_spaces/tests/alerting/alerts.ts index 0a300c4ce65da..c43e159bbe8ca 100644 --- a/x-pack/test/alerting_api_integration/security_and_spaces/tests/alerting/alerts.ts +++ b/x-pack/test/alerting_api_integration/security_and_spaces/tests/alerting/alerts.ts @@ -20,7 +20,7 @@ import { // eslint-disable-next-line import/no-default-export export default function alertTests({ getService }: FtrProviderContext) { const supertest = getService('supertest'); - const es = getService('es'); + const es = getService('legacyEs'); const retry = getService('retry'); const supertestWithoutAuth = getService('supertestWithoutAuth'); const esTestIndexTool = new ESTestIndexTool(es, retry); diff --git a/x-pack/test/alerting_api_integration/security_and_spaces/tests/alerting/create.ts b/x-pack/test/alerting_api_integration/security_and_spaces/tests/alerting/create.ts index bd0226d024d1f..d94556d6cedda 100644 --- a/x-pack/test/alerting_api_integration/security_and_spaces/tests/alerting/create.ts +++ b/x-pack/test/alerting_api_integration/security_and_spaces/tests/alerting/create.ts @@ -12,7 +12,7 @@ import { FtrProviderContext } from '../../../common/ftr_provider_context'; // eslint-disable-next-line import/no-default-export export default function createAlertTests({ getService }: FtrProviderContext) { const supertest = getService('supertest'); - const es = getService('es'); + const es = getService('legacyEs'); const supertestWithoutAuth = getService('supertestWithoutAuth'); describe('create', () => { diff --git a/x-pack/test/alerting_api_integration/security_and_spaces/tests/alerting/delete.ts b/x-pack/test/alerting_api_integration/security_and_spaces/tests/alerting/delete.ts index 6d5147e9f87b8..aab683df09740 100644 --- a/x-pack/test/alerting_api_integration/security_and_spaces/tests/alerting/delete.ts +++ b/x-pack/test/alerting_api_integration/security_and_spaces/tests/alerting/delete.ts @@ -12,7 +12,7 @@ import { FtrProviderContext } from '../../../common/ftr_provider_context'; // eslint-disable-next-line import/no-default-export export default function createDeleteTests({ getService }: FtrProviderContext) { const supertest = getService('supertest'); - const es = getService('es'); + const es = getService('legacyEs'); const supertestWithoutAuth = getService('supertestWithoutAuth'); describe('delete', () => { diff --git a/x-pack/test/alerting_api_integration/security_and_spaces/tests/alerting/disable.ts b/x-pack/test/alerting_api_integration/security_and_spaces/tests/alerting/disable.ts index 8a9b7e3fc35c4..d2076e0f92b3c 100644 --- a/x-pack/test/alerting_api_integration/security_and_spaces/tests/alerting/disable.ts +++ b/x-pack/test/alerting_api_integration/security_and_spaces/tests/alerting/disable.ts @@ -11,7 +11,7 @@ import { FtrProviderContext } from '../../../common/ftr_provider_context'; // eslint-disable-next-line import/no-default-export export default function createDisableAlertTests({ getService }: FtrProviderContext) { - const es = getService('es'); + const es = getService('legacyEs'); const supertest = getService('supertest'); const supertestWithoutAuth = getService('supertestWithoutAuth'); diff --git a/x-pack/test/alerting_api_integration/security_and_spaces/tests/alerting/enable.ts b/x-pack/test/alerting_api_integration/security_and_spaces/tests/alerting/enable.ts index 543805fb83b18..528db61dba21c 100644 --- a/x-pack/test/alerting_api_integration/security_and_spaces/tests/alerting/enable.ts +++ b/x-pack/test/alerting_api_integration/security_and_spaces/tests/alerting/enable.ts @@ -11,7 +11,7 @@ import { FtrProviderContext } from '../../../common/ftr_provider_context'; // eslint-disable-next-line import/no-default-export export default function createEnableAlertTests({ getService }: FtrProviderContext) { - const es = getService('es'); + const es = getService('legacyEs'); const supertest = getService('supertest'); const supertestWithoutAuth = getService('supertestWithoutAuth'); diff --git a/x-pack/test/alerting_api_integration/spaces_only/tests/actions/builtin_action_types/es_index.ts b/x-pack/test/alerting_api_integration/spaces_only/tests/actions/builtin_action_types/es_index.ts index 74a1255dacfe5..7e971d033b5c4 100644 --- a/x-pack/test/alerting_api_integration/spaces_only/tests/actions/builtin_action_types/es_index.ts +++ b/x-pack/test/alerting_api_integration/spaces_only/tests/actions/builtin_action_types/es_index.ts @@ -12,7 +12,7 @@ const ES_TEST_INDEX_NAME = 'functional-test-actions-index'; // eslint-disable-next-line import/no-default-export export default function indexTest({ getService }: FtrProviderContext) { - const es = getService('es'); + const es = getService('legacyEs'); const supertest = getService('supertest'); const esArchiver = getService('esArchiver'); diff --git a/x-pack/test/alerting_api_integration/spaces_only/tests/actions/execute.ts b/x-pack/test/alerting_api_integration/spaces_only/tests/actions/execute.ts index ba8a5aa9160a5..e97b6d480c470 100644 --- a/x-pack/test/alerting_api_integration/spaces_only/tests/actions/execute.ts +++ b/x-pack/test/alerting_api_integration/spaces_only/tests/actions/execute.ts @@ -17,7 +17,7 @@ import { FtrProviderContext } from '../../../common/ftr_provider_context'; // eslint-disable-next-line import/no-default-export export default function({ getService }: FtrProviderContext) { const supertest = getService('supertest'); - const es = getService('es'); + const es = getService('legacyEs'); const retry = getService('retry'); const esTestIndexTool = new ESTestIndexTool(es, retry); diff --git a/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/alerts.ts b/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/alerts.ts index badec079d6828..28634c46b6350 100644 --- a/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/alerts.ts +++ b/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/alerts.ts @@ -19,7 +19,7 @@ import { // eslint-disable-next-line import/no-default-export export default function alertTests({ getService }: FtrProviderContext) { const supertestWithoutAuth = getService('supertestWithoutAuth'); - const es = getService('es'); + const es = getService('legacyEs'); const retry = getService('retry'); const esTestIndexTool = new ESTestIndexTool(es, retry); diff --git a/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/create.ts b/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/create.ts index 17ec83b5b4f18..80459690af732 100644 --- a/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/create.ts +++ b/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/create.ts @@ -12,7 +12,7 @@ import { FtrProviderContext } from '../../../common/ftr_provider_context'; // eslint-disable-next-line import/no-default-export export default function createAlertTests({ getService }: FtrProviderContext) { const supertest = getService('supertest'); - const es = getService('es'); + const es = getService('legacyEs'); describe('create', () => { const objectRemover = new ObjectRemover(supertest); diff --git a/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/delete.ts b/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/delete.ts index 3ef501cfaa588..3aea982f948ea 100644 --- a/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/delete.ts +++ b/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/delete.ts @@ -12,7 +12,7 @@ import { FtrProviderContext } from '../../../common/ftr_provider_context'; // eslint-disable-next-line import/no-default-export export default function createDeleteTests({ getService }: FtrProviderContext) { const supertest = getService('supertest'); - const es = getService('es'); + const es = getService('legacyEs'); describe('delete', () => { const objectRemover = new ObjectRemover(supertest); diff --git a/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/disable.ts b/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/disable.ts index 664e74835d415..750f94201216a 100644 --- a/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/disable.ts +++ b/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/disable.ts @@ -11,7 +11,7 @@ import { FtrProviderContext } from '../../../common/ftr_provider_context'; // eslint-disable-next-line import/no-default-export export default function createDisableAlertTests({ getService }: FtrProviderContext) { - const es = getService('es'); + const es = getService('legacyEs'); const supertestWithoutAuth = getService('supertestWithoutAuth'); describe('disable', () => { diff --git a/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/enable.ts b/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/enable.ts index 2a8de1f6e31c3..00cd40c0e80cd 100644 --- a/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/enable.ts +++ b/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/enable.ts @@ -11,7 +11,7 @@ import { FtrProviderContext } from '../../../common/ftr_provider_context'; // eslint-disable-next-line import/no-default-export export default function createEnableAlertTests({ getService }: FtrProviderContext) { - const es = getService('es'); + const es = getService('legacyEs'); const supertestWithoutAuth = getService('supertestWithoutAuth'); describe('enable', () => { diff --git a/x-pack/test/api_integration/apis/beats/assign_tags_to_beats.js b/x-pack/test/api_integration/apis/beats/assign_tags_to_beats.js index 27435d49c252f..e4637d3807d4d 100644 --- a/x-pack/test/api_integration/apis/beats/assign_tags_to_beats.js +++ b/x-pack/test/api_integration/apis/beats/assign_tags_to_beats.js @@ -10,7 +10,7 @@ import { ES_INDEX_NAME } from './constants'; export default function ({ getService }) { const supertest = getService('supertest'); const esArchiver = getService('esArchiver'); - const es = getService('es'); + const es = getService('legacyEs'); const randomness = getService('randomness'); describe('assign_tags_to_beats', () => { diff --git a/x-pack/test/api_integration/apis/beats/create_enrollment_tokens.js b/x-pack/test/api_integration/apis/beats/create_enrollment_tokens.js index 6cd4fdf22bb41..09cfb33e4fad2 100644 --- a/x-pack/test/api_integration/apis/beats/create_enrollment_tokens.js +++ b/x-pack/test/api_integration/apis/beats/create_enrollment_tokens.js @@ -10,7 +10,7 @@ import { ES_INDEX_NAME } from './constants'; export default function ({ getService }) { const supertest = getService('supertest'); - const es = getService('es'); + const es = getService('legacyEs'); describe('create_enrollment_token', () => { it('should create one token by default', async () => { diff --git a/x-pack/test/api_integration/apis/beats/enroll_beat.js b/x-pack/test/api_integration/apis/beats/enroll_beat.js index 4b4767e1d9849..59c42db7c1f81 100644 --- a/x-pack/test/api_integration/apis/beats/enroll_beat.js +++ b/x-pack/test/api_integration/apis/beats/enroll_beat.js @@ -12,7 +12,7 @@ import { ES_INDEX_NAME } from './constants'; export default function ({ getService }) { const supertest = getService('supertest'); const randomness = getService('randomness'); - const es = getService('es'); + const es = getService('legacyEs'); describe('enroll_beat', () => { let validEnrollmentToken; diff --git a/x-pack/test/api_integration/apis/beats/get_beat.js b/x-pack/test/api_integration/apis/beats/get_beat.js index 07cc056e3af99..03667a53920c9 100644 --- a/x-pack/test/api_integration/apis/beats/get_beat.js +++ b/x-pack/test/api_integration/apis/beats/get_beat.js @@ -10,7 +10,7 @@ import { ES_INDEX_NAME } from './constants'; export default function ({ getService }) { const supertest = getService('supertest'); const esArchiver = getService('esArchiver'); - const es = getService('es'); + const es = getService('legacyEs'); describe('get_beat_configuration', () => { const archive = 'beats/list'; diff --git a/x-pack/test/api_integration/apis/beats/index.js b/x-pack/test/api_integration/apis/beats/index.js index da47fdbf77fc7..8ca7390ad5b1f 100644 --- a/x-pack/test/api_integration/apis/beats/index.js +++ b/x-pack/test/api_integration/apis/beats/index.js @@ -7,7 +7,7 @@ import { ES_INDEX_NAME } from './constants'; export default function ({ getService, loadTestFile }) { - const es = getService('es'); + const es = getService('legacyEs'); describe('beats', () => { const cleanup = () => diff --git a/x-pack/test/api_integration/apis/beats/remove_tags_from_beats.js b/x-pack/test/api_integration/apis/beats/remove_tags_from_beats.js index 1548aff1182b3..dde8916dd24d5 100644 --- a/x-pack/test/api_integration/apis/beats/remove_tags_from_beats.js +++ b/x-pack/test/api_integration/apis/beats/remove_tags_from_beats.js @@ -10,7 +10,7 @@ import { ES_INDEX_NAME } from './constants'; export default function ({ getService }) { const supertest = getService('supertest'); const esArchiver = getService('esArchiver'); - const es = getService('es'); + const es = getService('legacyEs'); const randomness = getService('randomness'); describe('remove_tags_from_beats', () => { diff --git a/x-pack/test/api_integration/apis/beats/set_config.js b/x-pack/test/api_integration/apis/beats/set_config.js index 5e15145cf47c8..21a09333dc31a 100644 --- a/x-pack/test/api_integration/apis/beats/set_config.js +++ b/x-pack/test/api_integration/apis/beats/set_config.js @@ -9,7 +9,7 @@ import { ES_INDEX_NAME } from './constants'; export default function ({ getService }) { const supertest = getService('supertest'); - const es = getService('es'); + const es = getService('legacyEs'); const esArchiver = getService('esArchiver'); describe('set_config', () => { diff --git a/x-pack/test/api_integration/apis/beats/set_tag.js b/x-pack/test/api_integration/apis/beats/set_tag.js index ee9a601b25096..630c3772b1661 100644 --- a/x-pack/test/api_integration/apis/beats/set_tag.js +++ b/x-pack/test/api_integration/apis/beats/set_tag.js @@ -9,7 +9,7 @@ import { ES_INDEX_NAME } from './constants'; export default function ({ getService }) { const supertest = getService('supertest'); - const es = getService('es'); + const es = getService('legacyEs'); describe('set_tag', () => { it('should create a tag', async () => { diff --git a/x-pack/test/api_integration/apis/beats/update_beat.js b/x-pack/test/api_integration/apis/beats/update_beat.js index 228d651a590e6..82582b553886c 100644 --- a/x-pack/test/api_integration/apis/beats/update_beat.js +++ b/x-pack/test/api_integration/apis/beats/update_beat.js @@ -11,7 +11,7 @@ import moment from 'moment'; export default function ({ getService }) { const supertest = getService('supertest'); const randomness = getService('randomness'); - const es = getService('es'); + const es = getService('legacyEs'); const esArchiver = getService('esArchiver'); describe('update_beat', () => { diff --git a/x-pack/test/api_integration/apis/es/has_privileges.js b/x-pack/test/api_integration/apis/es/has_privileges.js index 5cbbefd8f2f37..37d6d73499552 100644 --- a/x-pack/test/api_integration/apis/es/has_privileges.js +++ b/x-pack/test/api_integration/apis/es/has_privileges.js @@ -11,7 +11,7 @@ export default function ({ getService }) { describe('has_privileges', () => { before(async () => { - const es = getService('es'); + const es = getService('legacyEs'); await es.shield.postPrivileges({ body: { @@ -104,7 +104,7 @@ export default function ({ getService }) { }); // Create privilege - const es = getService('es'); + const es = getService('legacyEs'); await es.shield.postPrivileges({ body: { [application]: { diff --git a/x-pack/test/api_integration/apis/es/post_privileges.js b/x-pack/test/api_integration/apis/es/post_privileges.js index 4b1695487f832..1c8f723b7a278 100644 --- a/x-pack/test/api_integration/apis/es/post_privileges.js +++ b/x-pack/test/api_integration/apis/es/post_privileges.js @@ -9,7 +9,7 @@ export default function ({ getService }) { describe('post_privileges', () => { it('should allow privileges to be updated', async () => { - const es = getService('es'); + const es = getService('legacyEs'); const application = 'foo'; const response = await es.shield.postPrivileges({ body: { diff --git a/x-pack/test/api_integration/apis/index.js b/x-pack/test/api_integration/apis/index.js index 86ef445899039..ca339e9f407f2 100644 --- a/x-pack/test/api_integration/apis/index.js +++ b/x-pack/test/api_integration/apis/index.js @@ -27,5 +27,6 @@ export default function ({ loadTestFile }) { loadTestFile(require.resolve('./siem')); loadTestFile(require.resolve('./short_urls')); loadTestFile(require.resolve('./lens')); + loadTestFile(require.resolve('./licensing')); }); } diff --git a/x-pack/test/api_integration/apis/lens/telemetry.ts b/x-pack/test/api_integration/apis/lens/telemetry.ts index 6428ef9f478d4..5e6830c8f4689 100644 --- a/x-pack/test/api_integration/apis/lens/telemetry.ts +++ b/x-pack/test/api_integration/apis/lens/telemetry.ts @@ -22,7 +22,7 @@ const COMMON_HEADERS = { // eslint-disable-next-line import/no-default-export export default ({ getService }: FtrProviderContext) => { const supertest = getService('supertest'); - const es: Client = getService('es'); + const es: Client = getService('legacyEs'); const callCluster: CallCluster = (((path: 'search', searchParams: SearchParams) => { return es[path].call(es, searchParams); }) as unknown) as CallCluster; diff --git a/x-pack/test/api_integration/apis/licensing/index.ts b/x-pack/test/api_integration/apis/licensing/index.ts new file mode 100644 index 0000000000000..f14d5102f6f4e --- /dev/null +++ b/x-pack/test/api_integration/apis/licensing/index.ts @@ -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 { FtrProviderContext } from '../../ftr_provider_context'; + +export default function licensingIntegrationTests({ loadTestFile }: FtrProviderContext) { + describe('Licensing', () => { + loadTestFile(require.resolve('./info')); + }); +} diff --git a/x-pack/test/api_integration/apis/licensing/info.ts b/x-pack/test/api_integration/apis/licensing/info.ts new file mode 100644 index 0000000000000..0b48080616fb9 --- /dev/null +++ b/x-pack/test/api_integration/apis/licensing/info.ts @@ -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 expect from '@kbn/expect'; +import { FtrProviderContext } from '../../ftr_provider_context'; + +export default function({ getService }: FtrProviderContext) { + const supertest = getService('supertest'); + + describe('Info', () => { + describe('GET /api/licensing/info', () => { + it('returns licensing information', async () => { + const response = await supertest.get('/api/licensing/info').expect(200); + + expect(response.body).property('features'); + expect(response.body).property('license'); + expect(response.body).property('signature'); + }); + }); + }); +} diff --git a/x-pack/test/api_integration/apis/logstash/cluster/load.js b/x-pack/test/api_integration/apis/logstash/cluster/load.js index a20c524f0a8f8..36b992559e15b 100644 --- a/x-pack/test/api_integration/apis/logstash/cluster/load.js +++ b/x-pack/test/api_integration/apis/logstash/cluster/load.js @@ -8,7 +8,7 @@ import expect from '@kbn/expect'; export default function ({ getService }) { const supertest = getService('supertest'); - const es = getService('es'); + const es = getService('legacyEs'); describe('load', () => { it('should return the ES cluster info', async () => { diff --git a/x-pack/test/api_integration/apis/management/cross_cluster_replication/follower_indices.js b/x-pack/test/api_integration/apis/management/cross_cluster_replication/follower_indices.js index 8ed10ccf31dce..cd128d92498cf 100644 --- a/x-pack/test/api_integration/apis/management/cross_cluster_replication/follower_indices.js +++ b/x-pack/test/api_integration/apis/management/cross_cluster_replication/follower_indices.js @@ -14,7 +14,7 @@ import { registerHelpers as registerFollowerIndicesnHelpers } from './follower_i export default function ({ getService }) { const supertest = getService('supertest'); - const es = getService('es'); + const es = getService('legacyEs'); const { addCluster, deleteAllClusters } = registerRemoteClustersHelpers(supertest); const { diff --git a/x-pack/test/api_integration/apis/management/index_lifecycle_management/indices.js b/x-pack/test/api_integration/apis/management/index_lifecycle_management/indices.js index d0d08101e5444..020d6fc5741b9 100644 --- a/x-pack/test/api_integration/apis/management/index_lifecycle_management/indices.js +++ b/x-pack/test/api_integration/apis/management/index_lifecycle_management/indices.js @@ -13,7 +13,7 @@ import { getPolicyPayload } from './fixtures'; export default function ({ getService }) { const supertest = getService('supertest'); - const es = getService('es'); + const es = getService('legacyEs'); const { getIndex, diff --git a/x-pack/test/api_integration/apis/management/index_lifecycle_management/nodes.js b/x-pack/test/api_integration/apis/management/index_lifecycle_management/nodes.js index 5ce1d7d956d67..bc8b2af401423 100644 --- a/x-pack/test/api_integration/apis/management/index_lifecycle_management/nodes.js +++ b/x-pack/test/api_integration/apis/management/index_lifecycle_management/nodes.js @@ -13,7 +13,7 @@ import { initElasticsearchHelpers } from './lib'; export default function ({ getService }) { const supertest = getService('supertest'); - const es = getService('es'); + const es = getService('legacyEs'); const { getNodesStats } = initElasticsearchHelpers(es); const { loadNodes, getNodeDetails } = registerHelpers({ supertest }); diff --git a/x-pack/test/api_integration/apis/management/index_lifecycle_management/policies.js b/x-pack/test/api_integration/apis/management/index_lifecycle_management/policies.js index c13ae4a15c97e..598db2ddc8a65 100644 --- a/x-pack/test/api_integration/apis/management/index_lifecycle_management/policies.js +++ b/x-pack/test/api_integration/apis/management/index_lifecycle_management/policies.js @@ -15,7 +15,7 @@ import { DEFAULT_POLICY_NAME } from './constants'; export default function ({ getService }) { const supertest = getService('supertest'); - const es = getService('es'); + const es = getService('legacyEs'); const { createIndex, diff --git a/x-pack/test/api_integration/apis/management/index_lifecycle_management/templates.js b/x-pack/test/api_integration/apis/management/index_lifecycle_management/templates.js index 7dcf3c995e3ce..5c6e3d0e89c81 100644 --- a/x-pack/test/api_integration/apis/management/index_lifecycle_management/templates.js +++ b/x-pack/test/api_integration/apis/management/index_lifecycle_management/templates.js @@ -12,7 +12,7 @@ import { registerHelpers as registerPoliciesHelpers } from './policies.helpers'; export default function ({ getService }) { const supertest = getService('supertest'); - const es = getService('es'); + const es = getService('legacyEs'); const { createIndexTemplate, cleanUp: cleanUpEsResources } = initElasticsearchHelpers(es); diff --git a/x-pack/test/api_integration/apis/management/index_management/indices.js b/x-pack/test/api_integration/apis/management/index_management/indices.js index 09215eff20c69..9302b0fe0e16b 100644 --- a/x-pack/test/api_integration/apis/management/index_management/indices.js +++ b/x-pack/test/api_integration/apis/management/index_management/indices.js @@ -11,7 +11,7 @@ import { registerHelpers } from './indices.helpers'; export default function ({ getService }) { const supertest = getService('supertest'); - const es = getService('es'); + const es = getService('legacyEs'); const { createIndex, diff --git a/x-pack/test/api_integration/apis/management/index_management/mapping.js b/x-pack/test/api_integration/apis/management/index_management/mapping.js index 91f995a7d8045..0a2713e9407f1 100644 --- a/x-pack/test/api_integration/apis/management/index_management/mapping.js +++ b/x-pack/test/api_integration/apis/management/index_management/mapping.js @@ -11,7 +11,7 @@ import { registerHelpers } from './mapping.helpers'; export default function ({ getService }) { const supertest = getService('supertest'); - const es = getService('es'); + const es = getService('legacyEs'); const { createIndex, diff --git a/x-pack/test/api_integration/apis/management/index_management/settings.js b/x-pack/test/api_integration/apis/management/index_management/settings.js index dc41f530085b1..d9a9e19fe2490 100644 --- a/x-pack/test/api_integration/apis/management/index_management/settings.js +++ b/x-pack/test/api_integration/apis/management/index_management/settings.js @@ -11,7 +11,7 @@ import { registerHelpers } from './settings.helpers'; export default function ({ getService }) { const supertest = getService('supertest'); - const es = getService('es'); + const es = getService('legacyEs'); const { createIndex, diff --git a/x-pack/test/api_integration/apis/management/index_management/stats.js b/x-pack/test/api_integration/apis/management/index_management/stats.js index 58dac9f5b911a..743b1f596e9d7 100644 --- a/x-pack/test/api_integration/apis/management/index_management/stats.js +++ b/x-pack/test/api_integration/apis/management/index_management/stats.js @@ -11,7 +11,7 @@ import { registerHelpers } from './stats.helpers'; export default function ({ getService }) { const supertest = getService('supertest'); - const es = getService('es'); + const es = getService('legacyEs'); const { createIndex, diff --git a/x-pack/test/api_integration/apis/management/index_management/templates.js b/x-pack/test/api_integration/apis/management/index_management/templates.js index a6a7493218499..00a97e55c013c 100644 --- a/x-pack/test/api_integration/apis/management/index_management/templates.js +++ b/x-pack/test/api_integration/apis/management/index_management/templates.js @@ -11,7 +11,7 @@ import { registerHelpers } from './templates.helpers'; export default function ({ getService }) { const supertest = getService('supertest'); - const es = getService('es'); + const es = getService('legacyEs'); const { cleanUp: cleanUpEsResources, diff --git a/x-pack/test/api_integration/apis/management/rollup/index_patterns_extensions.js b/x-pack/test/api_integration/apis/management/rollup/index_patterns_extensions.js index 25bc503682bc7..78a04b729ba66 100644 --- a/x-pack/test/api_integration/apis/management/rollup/index_patterns_extensions.js +++ b/x-pack/test/api_integration/apis/management/rollup/index_patterns_extensions.js @@ -13,7 +13,7 @@ import { getRandomString } from './lib'; export default function ({ getService }) { const supertest = getService('supertest'); - const es = getService('es'); + const es = getService('legacyEs'); const { createIndexWithMappings, diff --git a/x-pack/test/api_integration/apis/management/rollup/rollup.js b/x-pack/test/api_integration/apis/management/rollup/rollup.js index 5ac4e06adb23a..6e99af2ba8e32 100644 --- a/x-pack/test/api_integration/apis/management/rollup/rollup.js +++ b/x-pack/test/api_integration/apis/management/rollup/rollup.js @@ -11,7 +11,7 @@ import { registerHelpers } from './rollup.test_helpers'; export default function ({ getService }) { const supertest = getService('supertest'); - const es = getService('es'); + const es = getService('legacyEs'); const { createIndexWithMappings, diff --git a/x-pack/test/api_integration/apis/management/rollup/rollup_search.js b/x-pack/test/api_integration/apis/management/rollup/rollup_search.js index 2a38cd563f312..073473f202fa3 100644 --- a/x-pack/test/api_integration/apis/management/rollup/rollup_search.js +++ b/x-pack/test/api_integration/apis/management/rollup/rollup_search.js @@ -12,7 +12,7 @@ import { getRandomString } from './lib'; export default function ({ getService }) { const supertest = getService('supertest'); - const es = getService('es'); + const es = getService('legacyEs'); const { createIndexWithMappings, diff --git a/x-pack/test/api_integration/apis/monitoring/common/mappings_exist.js b/x-pack/test/api_integration/apis/monitoring/common/mappings_exist.js index 6d3dbe68c77ac..2443448ccd062 100644 --- a/x-pack/test/api_integration/apis/monitoring/common/mappings_exist.js +++ b/x-pack/test/api_integration/apis/monitoring/common/mappings_exist.js @@ -13,7 +13,7 @@ import * as beatsMetrics from '../../../../../legacy/plugins/monitoring/server/l import * as apmMetrics from '../../../../../legacy/plugins/monitoring/server/lib/metrics/apm/metrics'; export default function ({ getService }) { - const es = getService('es'); + const es = getService('legacyEs'); const metricSets = [ { diff --git a/x-pack/test/api_integration/apis/security/roles.js b/x-pack/test/api_integration/apis/security/roles.js index d1d4c3c7b7af8..7108656783f52 100644 --- a/x-pack/test/api_integration/apis/security/roles.js +++ b/x-pack/test/api_integration/apis/security/roles.js @@ -7,7 +7,7 @@ import expect from '@kbn/expect'; export default function ({ getService }) { - const es = getService('es'); + const es = getService('legacyEs'); const supertest = getService('supertest'); const config = getService('config'); const basic = config.get('esTestCluster.license') === 'basic'; diff --git a/x-pack/test/api_integration/apis/telemetry/telemetry_optin_notice_seen.ts b/x-pack/test/api_integration/apis/telemetry/telemetry_optin_notice_seen.ts index de03fff7edcf7..582864795015c 100644 --- a/x-pack/test/api_integration/apis/telemetry/telemetry_optin_notice_seen.ts +++ b/x-pack/test/api_integration/apis/telemetry/telemetry_optin_notice_seen.ts @@ -10,7 +10,7 @@ import { TelemetrySavedObjectAttributes } from '../../../../../src/legacy/core_p import { FtrProviderContext } from '../../ftr_provider_context'; export default function optInTest({ getService }: FtrProviderContext) { - const client: Client = getService('es'); + const client: Client = getService('legacyEs'); const supertest = getService('supertest'); describe('/api/telemetry/v2/optIn API Telemetry User has seen OptIn Notice', () => { diff --git a/x-pack/test/api_integration/apis/uptime/graphql/monitor_states.ts b/x-pack/test/api_integration/apis/uptime/graphql/monitor_states.ts index 9dca3f40c6303..c305bb99c28f7 100644 --- a/x-pack/test/api_integration/apis/uptime/graphql/monitor_states.ts +++ b/x-pack/test/api_integration/apis/uptime/graphql/monitor_states.ts @@ -106,7 +106,7 @@ export default function({ getService }: FtrProviderContext) { before(async () => { const index = 'heartbeat-8.0.0'; - const es = getService('es'); + const es = getService('legacyEs'); dateRangeStart = new Date().toISOString(); checks = await makeChecks(es, index, testMonitorId, 1, numIps, {}, d => { if (d.summary) { diff --git a/x-pack/test/api_integration/apis/uptime/index.js b/x-pack/test/api_integration/apis/uptime/index.js index 8f4e4ab9a7ea1..6eb77fb584133 100644 --- a/x-pack/test/api_integration/apis/uptime/index.js +++ b/x-pack/test/api_integration/apis/uptime/index.js @@ -5,7 +5,7 @@ */ export default function ({ getService, loadTestFile }) { - const es = getService('es'); + const es = getService('legacyEs'); describe('uptime', () => { before(() => diff --git a/x-pack/test/api_integration/services/index.ts b/x-pack/test/api_integration/services/index.ts index 7e3b747c81993..4be89172e24f0 100644 --- a/x-pack/test/api_integration/services/index.ts +++ b/x-pack/test/api_integration/services/index.ts @@ -30,7 +30,7 @@ export const services = { esSupertest: kibanaApiIntegrationServices.esSupertest, supertest: kibanaApiIntegrationServices.supertest, - es: LegacyEsProvider, + legacyEs: LegacyEsProvider, esSupertestWithoutAuth: EsSupertestWithoutAuthProvider, infraOpsGraphQLClient: InfraOpsGraphQLClientProvider, infraOpsGraphQLClientFactory: InfraOpsGraphQLClientFactoryProvider, diff --git a/x-pack/test/functional/apps/discover/feature_controls/discover_security.ts b/x-pack/test/functional/apps/discover/feature_controls/discover_security.ts index 67bc8bd38ff1c..7cbab3cdcf4f2 100644 --- a/x-pack/test/functional/apps/discover/feature_controls/discover_security.ts +++ b/x-pack/test/functional/apps/discover/feature_controls/discover_security.ts @@ -25,9 +25,7 @@ export default function({ getPageObjects, getService }: FtrProviderContext) { const savedQueryManagementComponent = getService('savedQueryManagementComponent'); async function setDiscoverTimeRange() { - const fromTime = '2015-09-19 06:31:44.000'; - const toTime = '2015-09-23 18:31:44.000'; - await PageObjects.timePicker.setAbsoluteRange(fromTime, toTime); + await PageObjects.timePicker.setDefaultAbsoluteRange(); } describe('security', () => { diff --git a/x-pack/test/functional/apps/discover/feature_controls/discover_spaces.ts b/x-pack/test/functional/apps/discover/feature_controls/discover_spaces.ts index 243d5a0b6b6d0..4c2a8b4bed306 100644 --- a/x-pack/test/functional/apps/discover/feature_controls/discover_spaces.ts +++ b/x-pack/test/functional/apps/discover/feature_controls/discover_spaces.ts @@ -21,9 +21,7 @@ export default function({ getPageObjects, getService }: FtrProviderContext) { const appsMenu = getService('appsMenu'); async function setDiscoverTimeRange() { - const fromTime = '2015-09-19 06:31:44.000'; - const toTime = '2015-09-23 18:31:44.000'; - await PageObjects.timePicker.setAbsoluteRange(fromTime, toTime); + await PageObjects.timePicker.setDefaultAbsoluteRange(); } describe('spaces', () => { diff --git a/x-pack/test/functional/apps/monitoring/beats/beat_detail.js b/x-pack/test/functional/apps/monitoring/beats/beat_detail.js index d352579e01160..d17e233a484e8 100644 --- a/x-pack/test/functional/apps/monitoring/beats/beat_detail.js +++ b/x-pack/test/functional/apps/monitoring/beats/beat_detail.js @@ -17,8 +17,8 @@ export default function ({ getService, getPageObjects }) { before(async () => { await setup('monitoring/beats', { - from: '2017-12-19 17:14:09.000', - to: '2017-12-19 18:15:09.000', + from: 'Dec 19, 2017 @ 17:14:09.000', + to: 'Dec 19, 2017 @ 18:15:09.000', }); // go to beats detail diff --git a/x-pack/test/functional/apps/monitoring/beats/cluster.js b/x-pack/test/functional/apps/monitoring/beats/cluster.js index 8ee93066254d5..9a2532adfbae8 100644 --- a/x-pack/test/functional/apps/monitoring/beats/cluster.js +++ b/x-pack/test/functional/apps/monitoring/beats/cluster.js @@ -15,8 +15,8 @@ export default function ({ getService, getPageObjects }) { before(async () => { await setup('monitoring/beats', { - from: '2017-12-19 17:14:09.000', - to: '2017-12-19 18:15:09.000', + from: 'Dec 19, 2017 @ 17:14:09.000', + to: 'Dec 19, 2017 @ 18:15:09.000', }); }); diff --git a/x-pack/test/functional/apps/monitoring/beats/listing.js b/x-pack/test/functional/apps/monitoring/beats/listing.js index 700b5d593ecb8..7a27a7b5f219d 100644 --- a/x-pack/test/functional/apps/monitoring/beats/listing.js +++ b/x-pack/test/functional/apps/monitoring/beats/listing.js @@ -17,8 +17,8 @@ export default function ({ getService, getPageObjects }) { before(async () => { await setup('monitoring/beats', { - from: '2017-12-19 17:14:09.000', - to: '2017-12-19 18:15:09.000', + from: 'Dec 19, 2017 @ 17:14:09.000', + to: 'Dec 19, 2017 @ 18:15:09.000', }); // go to beats listing diff --git a/x-pack/test/functional/apps/monitoring/beats/overview.js b/x-pack/test/functional/apps/monitoring/beats/overview.js index 1c8b70a462843..16c198be0432f 100644 --- a/x-pack/test/functional/apps/monitoring/beats/overview.js +++ b/x-pack/test/functional/apps/monitoring/beats/overview.js @@ -17,8 +17,8 @@ export default function ({ getService, getPageObjects }) { before(async () => { await setup('monitoring/beats', { - from: '2017-12-19 17:14:09.000', - to: '2017-12-19 18:15:09.000', + from: 'Dec 19, 2017 @ 17:14:09.000', + to: 'Dec 19, 2017 @ 18:15:09.000', }); // go to beats overview diff --git a/x-pack/test/functional/apps/monitoring/cluster/alerts.js b/x-pack/test/functional/apps/monitoring/cluster/alerts.js index 1e61518947d2e..2a0dbec6f3b9e 100644 --- a/x-pack/test/functional/apps/monitoring/cluster/alerts.js +++ b/x-pack/test/functional/apps/monitoring/cluster/alerts.js @@ -23,8 +23,8 @@ export default function ({ getService, getPageObjects }) { before(async () => { await setup('monitoring/singlecluster-yellow-platinum', { - from: '2017-08-29 17:23:47.528', - to: '2017-08-29 17:25:50.701', + from: 'Aug 29, 2017 @ 17:23:47.528', + to: 'Aug 29, 2017 @ 17:25:50.701', }); // ensure cluster alerts are shown on overview @@ -51,8 +51,8 @@ export default function ({ getService, getPageObjects }) { before(async () => { await setup('monitoring/singlecluster-yellow-platinum--with-10-alerts', { - from: '2017-08-29 17:23:47.528', - to: '2017-08-29 17:25:50.701', + from: 'Aug 29, 2017 @ 17:23:47.528', + to: 'Aug 29, 2017 @ 17:25:50.701', }); // ensure cluster alerts are shown on overview @@ -166,8 +166,8 @@ export default function ({ getService, getPageObjects }) { before(async () => { await setup('monitoring/singlecluster-yellow-platinum', { - from: '2017-08-29 17:23:47.528', - to: '2017-08-29 17:25:50.701', + from: 'Aug 29, 2017 @ 17:23:47.528', + to: 'Aug 29, 2017 @ 17:25:50.701', }); // ensure cluster alerts are shown on overview diff --git a/x-pack/test/functional/apps/monitoring/cluster/list.js b/x-pack/test/functional/apps/monitoring/cluster/list.js index 70e89689a89db..399b392cad797 100644 --- a/x-pack/test/functional/apps/monitoring/cluster/list.js +++ b/x-pack/test/functional/apps/monitoring/cluster/list.js @@ -21,8 +21,8 @@ export default function ({ getService, getPageObjects }) { before(async () => { await setup('monitoring/multicluster', { - from: '2017-08-15 21:00:00.000', - to: '2017-08-16 00:00:00.000', + from: 'Aug 15, 2017 @ 21:00:00.000', + to: 'Aug 16, 2017 @ 00:00:00.000', }); await clusterList.assertDefaults(); @@ -76,8 +76,8 @@ export default function ({ getService, getPageObjects }) { before(async () => { await setup('monitoring/multi-basic', { - from: '2017-09-07 20:12:04.011', - to: '2017-09-07 20:18:55.733', + from: 'Sep 7, 2017 @ 20:12:04.011', + to: 'Sep 7, 2017 @ 20:18:55.733', }); await clusterList.assertDefaults(); diff --git a/x-pack/test/functional/apps/monitoring/cluster/overview.js b/x-pack/test/functional/apps/monitoring/cluster/overview.js index 8242150e404eb..3396426e95380 100644 --- a/x-pack/test/functional/apps/monitoring/cluster/overview.js +++ b/x-pack/test/functional/apps/monitoring/cluster/overview.js @@ -16,8 +16,8 @@ export default function ({ getService, getPageObjects }) { before(async () => { await setup('monitoring/singlecluster-green-gold', { - from: '2017-08-23 21:29:35.267', - to: '2017-08-23 21:47:25.556', + from: 'Aug 23, 2017 @ 21:29:35.267', + to: 'Aug 23, 2017 @ 21:47:25.556', }); }); @@ -71,8 +71,8 @@ export default function ({ getService, getPageObjects }) { before(async () => { await setup('monitoring/singlecluster-yellow-platinum', { - from: '2017-08-29 17:23:47.528', - to: '2017-08-29 17:25:50.701', + from: 'Aug 29, 2017 @ 17:23:47.528', + to: 'Aug 29, 2017 @ 17:25:50.701', }); }); @@ -121,8 +121,8 @@ export default function ({ getService, getPageObjects }) { before(async () => { await setup('monitoring/singlecluster-yellow-basic', { - from: '2017-08-29 17:55:43.879', - to: '2017-08-29 18:01:34.958', + from: 'Aug 29, 2017 @ 17:55:43.879', + to: 'Aug 29, 2017 @ 18:01:34.958', }); }); 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 c3fe5f9273a89..7109f9363e1b7 100644 --- a/x-pack/test/functional/apps/monitoring/elasticsearch/index_detail.js +++ b/x-pack/test/functional/apps/monitoring/elasticsearch/index_detail.js @@ -25,8 +25,8 @@ export default function ({ getService, getPageObjects }) { before(async () => { await setup('monitoring/singlecluster-three-nodes-shard-relocation', { - from: '2017-10-05 20:31:48.354', - to: '2017-10-05 20:35:12.176' + from: 'Oct 5, 2017 @ 20:31:48.354', + to: 'Oct 5, 2017 @ 20:35:12.176' }); // go to indices listing @@ -83,8 +83,8 @@ export default function ({ getService, getPageObjects }) { before(async () => { await setup('monitoring/singlecluster-red-platinum', { - from: '2017-10-06 19:53:06.748', - to: '2017-10-06 20:15:30.212' + from: 'Oct 6, 2017 @ 19:53:06.748', + to: 'Oct 6, 2017 @ 20:15:30.212' }); // go to indices listing diff --git a/x-pack/test/functional/apps/monitoring/elasticsearch/indices.js b/x-pack/test/functional/apps/monitoring/elasticsearch/indices.js index 1ed7c15a9ecf1..6500f373807a4 100644 --- a/x-pack/test/functional/apps/monitoring/elasticsearch/indices.js +++ b/x-pack/test/functional/apps/monitoring/elasticsearch/indices.js @@ -17,8 +17,8 @@ export default function ({ getService, getPageObjects }) { before(async () => { await setup('monitoring/singlecluster-red-platinum', { - from: '2017-10-06 19:53:06.748', - to: '2017-10-06 20:15:30.212', + from: 'Oct 6, 2017 @ 19:53:06.748', + to: 'Oct 6, 2017 @ 20:15:30.212', }); // go to indices listing 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 99dce6c1b89b6..6521753de506a 100644 --- a/x-pack/test/functional/apps/monitoring/elasticsearch/node_detail.js +++ b/x-pack/test/functional/apps/monitoring/elasticsearch/node_detail.js @@ -19,8 +19,8 @@ export default function ({ getService, getPageObjects }) { before(async () => { await setup('monitoring/singlecluster-three-nodes-shard-relocation', { - from: '2017-10-05 20:31:48.354', - to: '2017-10-05 20:35:12.176' + from: 'Oct 5, 2017 @ 20:31:48.354', + to: 'Oct 5, 2017 @ 20:35:12.176' }); // go to nodes listing @@ -74,8 +74,8 @@ export default function ({ getService, getPageObjects }) { before(async () => { await setup('monitoring/singlecluster-red-platinum', { - from: '2017-10-06 19:53:06.748', - to: '2017-10-06 20:15:30.212' + from: 'Oct 6, 2017 @ 19:53:06.748', + to: 'Oct 6, 2017 @ 20:15:30.212' }); // go to nodes listing diff --git a/x-pack/test/functional/apps/monitoring/elasticsearch/nodes.js b/x-pack/test/functional/apps/monitoring/elasticsearch/nodes.js index 7ad09e034e13b..94ad5e493d73e 100644 --- a/x-pack/test/functional/apps/monitoring/elasticsearch/nodes.js +++ b/x-pack/test/functional/apps/monitoring/elasticsearch/nodes.js @@ -21,8 +21,8 @@ export default function ({ getService, getPageObjects }) { before(async () => { await setup('monitoring/singlecluster-three-nodes-shard-relocation', { - from: '2017-10-05 20:28:28.475', - to: '2017-10-05 20:34:38.341', + from: 'Oct 5, 2017 @ 20:28:28.475', + to: 'Oct 5, 2017 @ 20:34:38.341', }); // go to nodes listing @@ -196,8 +196,8 @@ export default function ({ getService, getPageObjects }) { before(async () => { await setup('monitoring/singlecluster-three-nodes-shard-relocation', { - from: '2017-10-05 20:31:48.354', - to: '2017-10-05 20:35:12.176', + from: 'Oct 5, 2017 @ 20:31:48.354', + to: 'Oct 5, 2017 @ 20:35:12.176', }); // go to nodes listing diff --git a/x-pack/test/functional/apps/monitoring/elasticsearch/overview.js b/x-pack/test/functional/apps/monitoring/elasticsearch/overview.js index a0e91e2336e08..b5429cdc891f9 100644 --- a/x-pack/test/functional/apps/monitoring/elasticsearch/overview.js +++ b/x-pack/test/functional/apps/monitoring/elasticsearch/overview.js @@ -17,8 +17,8 @@ export default function ({ getService, getPageObjects }) { before(async () => { await setup('monitoring/singlecluster-three-nodes-shard-relocation', { - from: '2017-10-05 20:31:48.354', - to: '2017-10-05 20:35:12.176' + from: 'Oct 5, 2017 @ 20:31:48.354', + to: 'Oct 5, 2017 @ 20:35:12.176' }); // go to overview diff --git a/x-pack/test/functional/apps/monitoring/elasticsearch/shards.js b/x-pack/test/functional/apps/monitoring/elasticsearch/shards.js index ab02eead16333..4a40d686af496 100644 --- a/x-pack/test/functional/apps/monitoring/elasticsearch/shards.js +++ b/x-pack/test/functional/apps/monitoring/elasticsearch/shards.js @@ -21,8 +21,8 @@ export default function ({ getService, getPageObjects }) { before(async () => { await setup('monitoring/singlecluster-three-nodes-shard-relocation', { - from: '2017-10-05 19:34:48.000', - to: '2017-10-05 20:35:12.000', + from: 'Oct 5, 2017 @ 19:34:48.000', + to: 'Oct 5, 2017 @ 20:35:12.000', }); }); diff --git a/x-pack/test/functional/apps/monitoring/kibana/instance.js b/x-pack/test/functional/apps/monitoring/kibana/instance.js index 33448fc4b206a..0d4e06fb2b98f 100644 --- a/x-pack/test/functional/apps/monitoring/kibana/instance.js +++ b/x-pack/test/functional/apps/monitoring/kibana/instance.js @@ -17,8 +17,8 @@ export default function ({ getService, getPageObjects }) { before(async () => { await setup('monitoring/singlecluster-yellow-platinum', { - from: '2017-08-29 17:24:14.254', - to: '2017-08-29 17:25:44.142', + from: 'Aug 29, 2017 @ 17:24:14.254', + to: 'Aug 29, 2017 @ 17:25:44.142', }); // go to kibana instance diff --git a/x-pack/test/functional/apps/monitoring/kibana/instances.js b/x-pack/test/functional/apps/monitoring/kibana/instances.js index 28bf108d59f24..8f72806eee441 100644 --- a/x-pack/test/functional/apps/monitoring/kibana/instances.js +++ b/x-pack/test/functional/apps/monitoring/kibana/instances.js @@ -17,8 +17,8 @@ export default function ({ getService, getPageObjects }) { before(async () => { await setup('monitoring/singlecluster-yellow-platinum', { - from: '2017-08-29 17:24:14.254', - to: '2017-08-29 17:25:44.142', + from: 'Aug 29, 2017 @ 17:24:14.254', + to: 'Aug 29, 2017 @ 17:25:44.142', }); // go to kibana instances diff --git a/x-pack/test/functional/apps/monitoring/kibana/overview.js b/x-pack/test/functional/apps/monitoring/kibana/overview.js index 7282e48fc8a91..c5da75e37a77f 100644 --- a/x-pack/test/functional/apps/monitoring/kibana/overview.js +++ b/x-pack/test/functional/apps/monitoring/kibana/overview.js @@ -17,8 +17,8 @@ export default function ({ getService, getPageObjects }) { before(async () => { await setup('monitoring/singlecluster-yellow-platinum', { - from: '2017-08-29 17:24:14.254', - to: '2017-08-29 17:25:44.142', + from: 'Aug 29, 2017 @ 17:24:14.254', + to: 'Aug 29, 2017 @ 17:25:44.142', }); // go to kibana overview diff --git a/x-pack/test/functional/apps/monitoring/logstash/pipelines.js b/x-pack/test/functional/apps/monitoring/logstash/pipelines.js index fb9fcf8bab8bb..f4d2a5a4a20a5 100644 --- a/x-pack/test/functional/apps/monitoring/logstash/pipelines.js +++ b/x-pack/test/functional/apps/monitoring/logstash/pipelines.js @@ -19,8 +19,8 @@ export default function ({ getService, getPageObjects }) { before(async () => { await setup('monitoring/logstash-pipelines', { - from: '2018-01-22 09:10:00.000', - to: '2018-01-22 09:41:00.000', + from: 'Jan 22, 2018 @ 09:10:00.000', + to: 'Jan 22, 2018 @ 09:41:00.000', }); // go to pipelines listing diff --git a/x-pack/test/functional/apps/monitoring/time_filter.js b/x-pack/test/functional/apps/monitoring/time_filter.js index 0afcada14be5f..ae5b11e8e0b32 100644 --- a/x-pack/test/functional/apps/monitoring/time_filter.js +++ b/x-pack/test/functional/apps/monitoring/time_filter.js @@ -17,8 +17,8 @@ export default function ({ getService, getPageObjects }) { before(async () => { await setup('monitoring/multicluster', { - from: '2017-08-15 21:00:00.000', - to: '2017-08-16 00:00:00.000', + from: 'Aug 15, 2017 @ 21:00:00.000', + to: 'Aug 16, 2017 @ 00:00:00.000', }); await clusterList.assertDefaults(); }); @@ -35,7 +35,7 @@ export default function ({ getService, getPageObjects }) { }); it('should send another request when changing the time picker', async () => { - await PageObjects.timePicker.setAbsoluteRange('2016-08-15 21:00:00.000', '2016-08-16 00:00:00.000'); + await PageObjects.timePicker.setAbsoluteRange('Aug 15, 2016 @ 21:00:00.000', 'Aug 16, 2016 @ 00:00:00.000'); await clusterList.assertNoData(); }); }); diff --git a/x-pack/test/functional/apps/rollup_job/hybrid_index_pattern.js b/x-pack/test/functional/apps/rollup_job/hybrid_index_pattern.js index dca5534fb68b3..95bae4b24a535 100644 --- a/x-pack/test/functional/apps/rollup_job/hybrid_index_pattern.js +++ b/x-pack/test/functional/apps/rollup_job/hybrid_index_pattern.js @@ -11,7 +11,7 @@ import mockRolledUpData, { mockIndices } from './hybrid_index_helper'; export default function ({ getService, getPageObjects }) { - const es = getService('es'); + const es = getService('legacyEs'); const esArchiver = getService('esArchiver'); const retry = getService('retry'); const PageObjects = getPageObjects(['common', 'settings']); diff --git a/x-pack/test/functional/apps/rollup_job/rollup_jobs.js b/x-pack/test/functional/apps/rollup_job/rollup_jobs.js index eeff20105aed2..0888f0972592e 100644 --- a/x-pack/test/functional/apps/rollup_job/rollup_jobs.js +++ b/x-pack/test/functional/apps/rollup_job/rollup_jobs.js @@ -11,7 +11,7 @@ import { mockIndices } from './hybrid_index_helper'; export default function ({ getService, getPageObjects }) { - const es = getService('es'); + const es = getService('legacyEs'); const esArchiver = getService('esArchiver'); const PageObjects = getPageObjects(['rollup', 'common']); diff --git a/x-pack/test/functional/apps/security/rbac_phase1.js b/x-pack/test/functional/apps/security/rbac_phase1.js index 9b8be614c9f5b..3f9f2f6bdbe87 100644 --- a/x-pack/test/functional/apps/security/rbac_phase1.js +++ b/x-pack/test/functional/apps/security/rbac_phase1.js @@ -85,8 +85,6 @@ export default function ({ getService, getPageObjects }) { // this is to acertain that all role assigned to the user can perform actions like creating a Visualization it('rbac all role can save a visualization', async function () { - const fromTime = '2015-09-19 06:31:44.000'; - const toTime = '2015-09-23 18:31:44.000'; const vizName1 = 'Visualization VerticalBarChart'; log.debug('log in as kibanauser with rbac_all role'); @@ -96,8 +94,10 @@ export default function ({ getService, getPageObjects }) { log.debug('clickVerticalBarChart'); await PageObjects.visualize.clickVerticalBarChart(); await PageObjects.visualize.clickNewSearch(); - log.debug('Set absolute time range from \"' + fromTime + '\" to \"' + toTime + '\"'); - await PageObjects.timePicker.setAbsoluteRange(fromTime, toTime); + log.debug('Set absolute time range from \"' + + PageObjects.timePicker.defaultStartTime + '\" to \"' + + PageObjects.timePicker.defaultEndTime + '\"'); + await PageObjects.timePicker.setDefaultAbsoluteRange(); await PageObjects.visualize.waitForVisualization(); await PageObjects.visualize.saveVisualizationExpectSuccess(vizName1); await PageObjects.security.logout(); diff --git a/x-pack/test/functional/apps/uptime/monitor.ts b/x-pack/test/functional/apps/uptime/monitor.ts index ecbe893b1f2c0..034ccad4815a1 100644 --- a/x-pack/test/functional/apps/uptime/monitor.ts +++ b/x-pack/test/functional/apps/uptime/monitor.ts @@ -19,8 +19,8 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { after(async () => await esArchiver.unload(archive)); it('loads and displays uptime data based on date range', async () => { await pageObjects.uptime.loadDataAndGoToMonitorPage( - '2019-09-10 12:40:08.078', - '2019-09-11 19:40:08.078', + 'Sep 10, 2019 @ 12:40:08.078', + 'Sep 11, 2019 @ 19:40:08.078', '0000-intermittent', '0000-intermittent' ); diff --git a/x-pack/test/functional/apps/uptime/overview.ts b/x-pack/test/functional/apps/uptime/overview.ts index cdb904537a0f2..9a337c86185fe 100644 --- a/x-pack/test/functional/apps/uptime/overview.ts +++ b/x-pack/test/functional/apps/uptime/overview.ts @@ -12,8 +12,8 @@ export default ({ getPageObjects }: FtrProviderContext) => { const pageObjects = getPageObjects(['uptime']); describe('overview page', function() { - const DEFAULT_DATE_START = '2019-09-10 12:40:08.078'; - const DEFAULT_DATE_END = '2019-09-11 19:40:08.078'; + const DEFAULT_DATE_START = 'Sep 10, 2019 @ 12:40:08.078'; + const DEFAULT_DATE_END = 'Sep 11, 2019 @ 19:40:08.078'; it('loads and displays uptime data based on date range', async () => { await pageObjects.uptime.goToUptimeOverviewAndLoadData( DEFAULT_DATE_START, diff --git a/x-pack/test/functional/apps/visualize/hybrid_visualization.ts b/x-pack/test/functional/apps/visualize/hybrid_visualization.ts index dacd0b75b126c..03b6ed8e8e7c5 100644 --- a/x-pack/test/functional/apps/visualize/hybrid_visualization.ts +++ b/x-pack/test/functional/apps/visualize/hybrid_visualization.ts @@ -75,8 +75,8 @@ export default function({ getPageObjects, getService }: FtrProviderContext) { ['2019-08-22 00:00', 'php', '11'], ['2019-08-22 16:00', 'jpg', '3'], ]; - const fromTime = '2019-08-19 01:55:07.240'; - const toTime = '2019-08-22 23:09:36.205'; + const fromTime = 'Aug 19, 2019 @ 01:55:07.240'; + const toTime = 'Aug 22, 2019 @ 23:09:36.205'; await PageObjects.common.navigateToApp('visualize'); await PageObjects.visualize.clickVisualizationByName('hybrid_histogram_line_chart'); diff --git a/x-pack/test/functional/page_objects/lens_page.ts b/x-pack/test/functional/page_objects/lens_page.ts index 8153a8713ca2f..480814cb02781 100644 --- a/x-pack/test/functional/page_objects/lens_page.ts +++ b/x-pack/test/functional/page_objects/lens_page.ts @@ -46,7 +46,9 @@ export function LensPageProvider({ getService, getPageObjects }: FtrProviderCont * Move the date filter to the specified time range, defaults to * a range that has data in our dataset. */ - goToTimeRange(fromTime = '2015-09-19 06:31:44.000', toTime = '2015-09-23 18:31:44.000') { + goToTimeRange(fromTime?: string, toTime?: string) { + fromTime = fromTime || PageObjects.timePicker.defaultStartTime; + toTime = toTime || PageObjects.timePicker.defaultEndTime; return PageObjects.timePicker.setAbsoluteRange(fromTime, toTime); }, diff --git a/x-pack/test/functional/page_objects/reporting_page.js b/x-pack/test/functional/page_objects/reporting_page.js index 30de10c400c88..0ba0325ad5602 100644 --- a/x-pack/test/functional/page_objects/reporting_page.js +++ b/x-pack/test/functional/page_objects/reporting_page.js @@ -165,15 +165,13 @@ export function ReportingPageProvider({ getService, getPageObjects }) { async setTimepickerInDataRange() { log.debug('Reporting:setTimepickerInDataRange'); - const fromTime = '2015-09-19 06:31:44.000'; - const toTime = '2015-09-23 18:31:44.000'; - await PageObjects.timePicker.setAbsoluteRange(fromTime, toTime); + await PageObjects.timePicker.setDefaultAbsoluteRange(); } async setTimepickerInNoDataRange() { log.debug('Reporting:setTimepickerInNoDataRange'); - const fromTime = '1999-09-19 06:31:44.000'; - const toTime = '1999-09-23 18:31:44.000'; + const fromTime = 'Sep 19, 1999 @ 06:31:44.000'; + const toTime = 'Sep 23, 1999 @ 18:31:44.000'; await PageObjects.timePicker.setAbsoluteRange(fromTime, toTime); } } diff --git a/x-pack/test/functional/services/machine_learning/api.ts b/x-pack/test/functional/services/machine_learning/api.ts index 270722a97d6b6..2fc027a81ea8c 100644 --- a/x-pack/test/functional/services/machine_learning/api.ts +++ b/x-pack/test/functional/services/machine_learning/api.ts @@ -11,7 +11,7 @@ import { FtrProviderContext } from '../../ftr_provider_context'; import { JOB_STATE, DATAFEED_STATE } from '../../../../legacy/plugins/ml/common/constants/states'; export function MachineLearningAPIProvider({ getService }: FtrProviderContext) { - const es = getService('es'); + const es = getService('legacyEs'); const log = getService('log'); const retry = getService('retry'); const esSupertest = getService('esSupertest'); diff --git a/x-pack/test/functional/services/transform_ui/api.ts b/x-pack/test/functional/services/transform_ui/api.ts index 9050b5944dee3..a6756e5940d72 100644 --- a/x-pack/test/functional/services/transform_ui/api.ts +++ b/x-pack/test/functional/services/transform_ui/api.ts @@ -8,7 +8,7 @@ import expect from '@kbn/expect'; import { FtrProviderContext } from '../../ftr_provider_context'; export function TransformAPIProvider({ getService }: FtrProviderContext) { - const es = getService('es'); + const es = getService('legacyEs'); const log = getService('log'); const retry = getService('retry'); diff --git a/x-pack/test/kerberos_api_integration/apis/security/kerberos_login.ts b/x-pack/test/kerberos_api_integration/apis/security/kerberos_login.ts index 0a3b7f595c66d..450f7b1a427dc 100644 --- a/x-pack/test/kerberos_api_integration/apis/security/kerberos_login.ts +++ b/x-pack/test/kerberos_api_integration/apis/security/kerberos_login.ts @@ -362,7 +362,7 @@ export default function({ getService }: FtrProviderContext) { // Let's delete tokens from `.security-tokens` index directly to simulate the case when // Elasticsearch automatically removes access/refresh token document from the index after // some period of time. - const esResponse = await getService('es').deleteByQuery({ + const esResponse = await getService('legacyEs').deleteByQuery({ index: '.security-tokens', q: 'doc_type:token', refresh: true, diff --git a/x-pack/test/kerberos_api_integration/services.ts b/x-pack/test/kerberos_api_integration/services.ts index 42505994e0602..e2e7a5b8844a7 100644 --- a/x-pack/test/kerberos_api_integration/services.ts +++ b/x-pack/test/kerberos_api_integration/services.ts @@ -7,7 +7,7 @@ import { services as apiIntegrationServices } from '../api_integration/services'; export const services = { - es: apiIntegrationServices.es, + legacyEs: apiIntegrationServices.legacyEs, esSupertest: apiIntegrationServices.esSupertest, supertestWithoutAuth: apiIntegrationServices.supertestWithoutAuth, }; diff --git a/x-pack/test/oidc_api_integration/apis/authorization_code_flow/oidc_auth.js b/x-pack/test/oidc_api_integration/apis/authorization_code_flow/oidc_auth.js index 7460b1f9e238c..80ef6bd6df4ff 100644 --- a/x-pack/test/oidc_api_integration/apis/authorization_code_flow/oidc_auth.js +++ b/x-pack/test/oidc_api_integration/apis/authorization_code_flow/oidc_auth.js @@ -482,7 +482,7 @@ export default function ({ getService }) { // Let's delete tokens from `.security-tokens` index directly to simulate the case when // Elasticsearch automatically removes access/refresh token document from the index // after some period of time. - const esResponse = await getService('es').deleteByQuery({ + const esResponse = await getService('legacyEs').deleteByQuery({ index: '.security-tokens', q: 'doc_type:token', refresh: true, diff --git a/x-pack/test/oidc_api_integration/services.ts b/x-pack/test/oidc_api_integration/services.ts index e4ff6048a8cce..dda9f1d1a8886 100644 --- a/x-pack/test/oidc_api_integration/services.ts +++ b/x-pack/test/oidc_api_integration/services.ts @@ -7,6 +7,6 @@ import { services as apiIntegrationServices } from '../api_integration/services'; export const services = { - es: apiIntegrationServices.es, + legacyEs: apiIntegrationServices.legacyEs, supertestWithoutAuth: apiIntegrationServices.supertestWithoutAuth, }; diff --git a/x-pack/test/plugin_api_integration/test_suites/encrypted_saved_objects/encrypted_saved_objects_api.ts b/x-pack/test/plugin_api_integration/test_suites/encrypted_saved_objects/encrypted_saved_objects_api.ts index 98d653d71b5ec..ab9f7d2cdd339 100644 --- a/x-pack/test/plugin_api_integration/test_suites/encrypted_saved_objects/encrypted_saved_objects_api.ts +++ b/x-pack/test/plugin_api_integration/test_suites/encrypted_saved_objects/encrypted_saved_objects_api.ts @@ -9,7 +9,7 @@ import { SavedObject } from 'src/core/server'; import { FtrProviderContext } from '../../ftr_provider_context'; export default function({ getService }: FtrProviderContext) { - const es = getService('es'); + const es = getService('legacyEs'); const randomness = getService('randomness'); const supertest = getService('supertest'); diff --git a/x-pack/test/plugin_api_integration/test_suites/task_manager/task_manager_integration.js b/x-pack/test/plugin_api_integration/test_suites/task_manager/task_manager_integration.js index a8ff03dc71d24..9b4297e995cbd 100644 --- a/x-pack/test/plugin_api_integration/test_suites/task_manager/task_manager_integration.js +++ b/x-pack/test/plugin_api_integration/test_suites/task_manager/task_manager_integration.js @@ -12,7 +12,7 @@ import supertestAsPromised from 'supertest-as-promised'; const { task: { properties: taskManagerIndexMapping } } = require('../../../../legacy/plugins/task_manager/mappings.json'); export default function ({ getService }) { - const es = getService('es'); + const es = getService('legacyEs'); const log = getService('log'); const retry = getService('retry'); const config = getService('config'); diff --git a/x-pack/test/saml_api_integration/apis/security/saml_login.ts b/x-pack/test/saml_api_integration/apis/security/saml_login.ts index 276b42423860c..d512894fbb1f2 100644 --- a/x-pack/test/saml_api_integration/apis/security/saml_login.ts +++ b/x-pack/test/saml_api_integration/apis/security/saml_login.ts @@ -622,7 +622,7 @@ export default function({ getService }: FtrProviderContext) { // Let's delete tokens from `.security` index directly to simulate the case when // Elasticsearch automatically removes access/refresh token document from the index // after some period of time. - const esResponse = await getService('es').deleteByQuery({ + const esResponse = await getService('legacyEs').deleteByQuery({ index: '.security-tokens', q: 'doc_type:token', refresh: true, diff --git a/x-pack/test/saml_api_integration/config.ts b/x-pack/test/saml_api_integration/config.ts index 9d3029db013d3..6ea29b0d9e56e 100644 --- a/x-pack/test/saml_api_integration/config.ts +++ b/x-pack/test/saml_api_integration/config.ts @@ -21,7 +21,7 @@ export default async function({ readConfigFile }: FtrConfigProviderContext) { servers: xPackAPITestsConfig.get('servers'), services: { randomness: kibanaAPITestsConfig.get('services.randomness'), - es: kibanaAPITestsConfig.get('services.es'), + legacyEs: kibanaAPITestsConfig.get('services.legacyEs'), supertestWithoutAuth: xPackAPITestsConfig.get('services.supertestWithoutAuth'), }, junit: { diff --git a/x-pack/test/saml_api_integration/services.ts b/x-pack/test/saml_api_integration/services.ts index 307108fa097f4..d207112f6e81f 100644 --- a/x-pack/test/saml_api_integration/services.ts +++ b/x-pack/test/saml_api_integration/services.ts @@ -8,6 +8,6 @@ import { services as apiIntegrationServices } from '../api_integration/services' export const services = { randomness: apiIntegrationServices.randomness, - es: apiIntegrationServices.es, + legacyEs: apiIntegrationServices.legacyEs, supertestWithoutAuth: apiIntegrationServices.supertestWithoutAuth, }; diff --git a/x-pack/test/saved_object_api_integration/common/services/index.ts b/x-pack/test/saved_object_api_integration/common/services/index.ts index 1ea312714fc1e..aba605fee8947 100644 --- a/x-pack/test/saved_object_api_integration/common/services/index.ts +++ b/x-pack/test/saved_object_api_integration/common/services/index.ts @@ -12,7 +12,7 @@ import { services as kibanaApiIntegrationServices } from '../../../../../test/ap import { services as kibanaFunctionalServices } from '../../../../../test/functional/services'; export const services = { - es: LegacyEsProvider, + legacyEs: LegacyEsProvider, esSupertestWithoutAuth: apiIntegrationServices.esSupertestWithoutAuth, supertest: kibanaApiIntegrationServices.supertest, supertestWithoutAuth: apiIntegrationServices.supertestWithoutAuth, diff --git a/x-pack/test/saved_object_api_integration/security_and_spaces/apis/bulk_create.ts b/x-pack/test/saved_object_api_integration/security_and_spaces/apis/bulk_create.ts index 7e00d0a9d7f75..7768665f3b941 100644 --- a/x-pack/test/saved_object_api_integration/security_and_spaces/apis/bulk_create.ts +++ b/x-pack/test/saved_object_api_integration/security_and_spaces/apis/bulk_create.ts @@ -12,7 +12,7 @@ import { bulkCreateTestSuiteFactory } from '../../common/suites/bulk_create'; export default function({ getService }: FtrProviderContext) { const supertest = getService('supertestWithoutAuth'); const esArchiver = getService('esArchiver'); - const es = getService('es'); + const es = getService('legacyEs'); const { bulkCreateTest, diff --git a/x-pack/test/saved_object_api_integration/security_and_spaces/apis/create.ts b/x-pack/test/saved_object_api_integration/security_and_spaces/apis/create.ts index 4cc94bf21f235..e4adaa580c1db 100644 --- a/x-pack/test/saved_object_api_integration/security_and_spaces/apis/create.ts +++ b/x-pack/test/saved_object_api_integration/security_and_spaces/apis/create.ts @@ -11,7 +11,7 @@ import { createTestSuiteFactory } from '../../common/suites/create'; export default function({ getService }: FtrProviderContext) { const supertestWithoutAuth = getService('supertestWithoutAuth'); - const es = getService('es'); + const es = getService('legacyEs'); const esArchiver = getService('esArchiver'); const { diff --git a/x-pack/test/saved_object_api_integration/security_and_spaces/apis/import.ts b/x-pack/test/saved_object_api_integration/security_and_spaces/apis/import.ts index f9048d1493cc6..58859c292ce35 100644 --- a/x-pack/test/saved_object_api_integration/security_and_spaces/apis/import.ts +++ b/x-pack/test/saved_object_api_integration/security_and_spaces/apis/import.ts @@ -12,7 +12,7 @@ import { importTestSuiteFactory } from '../../common/suites/import'; export default function({ getService }: FtrProviderContext) { const supertest = getService('supertestWithoutAuth'); const esArchiver = getService('esArchiver'); - const es = getService('es'); + const es = getService('legacyEs'); const { importTest, diff --git a/x-pack/test/saved_object_api_integration/security_and_spaces/apis/index.ts b/x-pack/test/saved_object_api_integration/security_and_spaces/apis/index.ts index 1b1e9762a54e5..bb42c5422ece5 100644 --- a/x-pack/test/saved_object_api_integration/security_and_spaces/apis/index.ts +++ b/x-pack/test/saved_object_api_integration/security_and_spaces/apis/index.ts @@ -8,7 +8,7 @@ import { createUsersAndRoles } from '../../common/lib/create_users_and_roles'; import { FtrProviderContext } from '../../common/ftr_provider_context'; export default function({ getService, loadTestFile }: FtrProviderContext) { - const es = getService('es'); + const es = getService('legacyEs'); const supertest = getService('supertest'); describe('saved objects security and spaces enabled', function() { diff --git a/x-pack/test/saved_object_api_integration/security_and_spaces/apis/resolve_import_errors.ts b/x-pack/test/saved_object_api_integration/security_and_spaces/apis/resolve_import_errors.ts index fa070ac76ce57..6c91fe6310170 100644 --- a/x-pack/test/saved_object_api_integration/security_and_spaces/apis/resolve_import_errors.ts +++ b/x-pack/test/saved_object_api_integration/security_and_spaces/apis/resolve_import_errors.ts @@ -12,7 +12,7 @@ import { resolveImportErrorsTestSuiteFactory } from '../../common/suites/resolve export default function({ getService }: FtrProviderContext) { const supertest = getService('supertestWithoutAuth'); const esArchiver = getService('esArchiver'); - const es = getService('es'); + const es = getService('legacyEs'); const { resolveImportErrorsTest, diff --git a/x-pack/test/saved_object_api_integration/security_only/apis/bulk_create.ts b/x-pack/test/saved_object_api_integration/security_only/apis/bulk_create.ts index 2a5757fb0cc57..943a22c4399c7 100644 --- a/x-pack/test/saved_object_api_integration/security_only/apis/bulk_create.ts +++ b/x-pack/test/saved_object_api_integration/security_only/apis/bulk_create.ts @@ -11,7 +11,7 @@ import { bulkCreateTestSuiteFactory } from '../../common/suites/bulk_create'; export default function({ getService }: FtrProviderContext) { const supertest = getService('supertestWithoutAuth'); const esArchiver = getService('esArchiver'); - const es = getService('es'); + const es = getService('legacyEs'); const { bulkCreateTest, diff --git a/x-pack/test/saved_object_api_integration/security_only/apis/create.ts b/x-pack/test/saved_object_api_integration/security_only/apis/create.ts index bb2bf7e0e0d7a..60a9fa0a86aa6 100644 --- a/x-pack/test/saved_object_api_integration/security_only/apis/create.ts +++ b/x-pack/test/saved_object_api_integration/security_only/apis/create.ts @@ -10,7 +10,7 @@ import { createTestSuiteFactory } from '../../common/suites/create'; export default function({ getService }: FtrProviderContext) { const supertestWithoutAuth = getService('supertestWithoutAuth'); - const es = getService('es'); + const es = getService('legacyEs'); const esArchiver = getService('esArchiver'); const { diff --git a/x-pack/test/saved_object_api_integration/security_only/apis/import.ts b/x-pack/test/saved_object_api_integration/security_only/apis/import.ts index 8ad7e070edf54..770410dcfed81 100644 --- a/x-pack/test/saved_object_api_integration/security_only/apis/import.ts +++ b/x-pack/test/saved_object_api_integration/security_only/apis/import.ts @@ -11,7 +11,7 @@ import { importTestSuiteFactory } from '../../common/suites/import'; export default function({ getService }: FtrProviderContext) { const supertest = getService('supertestWithoutAuth'); const esArchiver = getService('esArchiver'); - const es = getService('es'); + const es = getService('legacyEs'); const { importTest, diff --git a/x-pack/test/saved_object_api_integration/security_only/apis/index.ts b/x-pack/test/saved_object_api_integration/security_only/apis/index.ts index 6e930338a1184..bb637a9bc4c90 100644 --- a/x-pack/test/saved_object_api_integration/security_only/apis/index.ts +++ b/x-pack/test/saved_object_api_integration/security_only/apis/index.ts @@ -8,7 +8,7 @@ import { createUsersAndRoles } from '../../common/lib/create_users_and_roles'; import { FtrProviderContext } from '../../common/ftr_provider_context'; export default function({ getService, loadTestFile }: FtrProviderContext) { - const es = getService('es'); + const es = getService('legacyEs'); const supertest = getService('supertest'); describe('saved objects security only enabled', function() { diff --git a/x-pack/test/saved_object_api_integration/security_only/apis/resolve_import_errors.ts b/x-pack/test/saved_object_api_integration/security_only/apis/resolve_import_errors.ts index e1d72f8641e93..59d50c16c259a 100644 --- a/x-pack/test/saved_object_api_integration/security_only/apis/resolve_import_errors.ts +++ b/x-pack/test/saved_object_api_integration/security_only/apis/resolve_import_errors.ts @@ -11,7 +11,7 @@ import { resolveImportErrorsTestSuiteFactory } from '../../common/suites/resolve export default function({ getService }: FtrProviderContext) { const supertest = getService('supertestWithoutAuth'); const esArchiver = getService('esArchiver'); - const es = getService('es'); + const es = getService('legacyEs'); const { resolveImportErrorsTest, diff --git a/x-pack/test/saved_object_api_integration/spaces_only/apis/bulk_create.ts b/x-pack/test/saved_object_api_integration/spaces_only/apis/bulk_create.ts index 6b67c63ed349a..d89e3b4f8605b 100644 --- a/x-pack/test/saved_object_api_integration/spaces_only/apis/bulk_create.ts +++ b/x-pack/test/saved_object_api_integration/spaces_only/apis/bulk_create.ts @@ -25,7 +25,7 @@ const expectNamespaceSpecifiedBadRequest = (resp: { [key: string]: any }) => { export default function({ getService }: FtrProviderContext) { const supertest = getService('supertest'); const esArchiver = getService('esArchiver'); - const es = getService('es'); + const es = getService('legacyEs'); const { bulkCreateTest, diff --git a/x-pack/test/saved_object_api_integration/spaces_only/apis/create.ts b/x-pack/test/saved_object_api_integration/spaces_only/apis/create.ts index d6bd0b497759f..cf34f7505cdb2 100644 --- a/x-pack/test/saved_object_api_integration/spaces_only/apis/create.ts +++ b/x-pack/test/saved_object_api_integration/spaces_only/apis/create.ts @@ -23,7 +23,7 @@ const expectNamespaceSpecifiedBadRequest = (resp: { [key: string]: any }) => { export default function({ getService }: FtrProviderContext) { const supertestWithoutAuth = getService('supertestWithoutAuth'); - const es = getService('es'); + const es = getService('legacyEs'); const esArchiver = getService('esArchiver'); const { diff --git a/x-pack/test/saved_object_api_integration/spaces_only/apis/import.ts b/x-pack/test/saved_object_api_integration/spaces_only/apis/import.ts index c8b2e68291dc3..c78a0e1cc2cce 100644 --- a/x-pack/test/saved_object_api_integration/spaces_only/apis/import.ts +++ b/x-pack/test/saved_object_api_integration/spaces_only/apis/import.ts @@ -11,7 +11,7 @@ import { importTestSuiteFactory } from '../../common/suites/import'; export default function({ getService }: FtrProviderContext) { const supertest = getService('supertest'); const esArchiver = getService('esArchiver'); - const es = getService('es'); + const es = getService('legacyEs'); const { importTest, diff --git a/x-pack/test/saved_object_api_integration/spaces_only/apis/resolve_import_errors.ts b/x-pack/test/saved_object_api_integration/spaces_only/apis/resolve_import_errors.ts index 93d60ebbf4d6d..22a7ab81e5530 100644 --- a/x-pack/test/saved_object_api_integration/spaces_only/apis/resolve_import_errors.ts +++ b/x-pack/test/saved_object_api_integration/spaces_only/apis/resolve_import_errors.ts @@ -11,7 +11,7 @@ import { resolveImportErrorsTestSuiteFactory } from '../../common/suites/resolve export default function({ getService }: FtrProviderContext) { const supertest = getService('supertest'); const esArchiver = getService('esArchiver'); - const es = getService('es'); + const es = getService('legacyEs'); const { resolveImportErrorsTest, diff --git a/x-pack/test/spaces_api_integration/common/config.ts b/x-pack/test/spaces_api_integration/common/config.ts index 23514c635d356..dffc6c524cc6e 100644 --- a/x-pack/test/spaces_api_integration/common/config.ts +++ b/x-pack/test/spaces_api_integration/common/config.ts @@ -34,7 +34,7 @@ export function createTestConfig(name: string, options: CreateTestConfigOptions) testFiles: [require.resolve(`../${name}/apis/`)], servers: config.xpack.api.get('servers'), services: { - es: LegacyEsProvider, + legacyEs: LegacyEsProvider, esSupertestWithoutAuth: config.xpack.api.get('services.esSupertestWithoutAuth'), supertest: config.kibana.api.get('services.supertest'), supertestWithoutAuth: config.xpack.api.get('services.supertestWithoutAuth'), diff --git a/x-pack/test/spaces_api_integration/security_and_spaces/apis/copy_to_space.ts b/x-pack/test/spaces_api_integration/security_and_spaces/apis/copy_to_space.ts index c6c41f7cd3a97..1c4ca2fe20662 100644 --- a/x-pack/test/spaces_api_integration/security_and_spaces/apis/copy_to_space.ts +++ b/x-pack/test/spaces_api_integration/security_and_spaces/apis/copy_to_space.ts @@ -13,7 +13,7 @@ import { copyToSpaceTestSuiteFactory } from '../../common/suites/copy_to_space'; export default function copyToSpaceSpacesAndSecuritySuite({ getService }: TestInvoker) { const supertestWithoutAuth = getService('supertestWithoutAuth'); const esArchiver = getService('esArchiver'); - const es = getService('es'); + const es = getService('legacyEs'); const { copyToSpaceTest, diff --git a/x-pack/test/spaces_api_integration/security_and_spaces/apis/delete.ts b/x-pack/test/spaces_api_integration/security_and_spaces/apis/delete.ts index 25d7317d7dd90..df4a2f51b4872 100644 --- a/x-pack/test/spaces_api_integration/security_and_spaces/apis/delete.ts +++ b/x-pack/test/spaces_api_integration/security_and_spaces/apis/delete.ts @@ -13,7 +13,7 @@ import { deleteTestSuiteFactory } from '../../common/suites/delete'; export default function deleteSpaceTestSuite({ getService }: TestInvoker) { const supertestWithoutAuth = getService('supertestWithoutAuth'); const esArchiver = getService('esArchiver'); - const es = getService('es'); + const es = getService('legacyEs'); const { deleteTest, diff --git a/x-pack/test/spaces_api_integration/security_and_spaces/apis/index.ts b/x-pack/test/spaces_api_integration/security_and_spaces/apis/index.ts index 300949f41f036..e918ab0b53841 100644 --- a/x-pack/test/spaces_api_integration/security_and_spaces/apis/index.ts +++ b/x-pack/test/spaces_api_integration/security_and_spaces/apis/index.ts @@ -9,7 +9,7 @@ import { TestInvoker } from '../../common/lib/types'; // eslint-disable-next-line import/no-default-export export default function({ loadTestFile, getService }: TestInvoker) { - const es = getService('es'); + const es = getService('legacyEs'); const supertest = getService('supertest'); describe('spaces api with security', function() { diff --git a/x-pack/test/spaces_api_integration/spaces_only/apis/copy_to_space.ts b/x-pack/test/spaces_api_integration/spaces_only/apis/copy_to_space.ts index b1427a9b77be0..4781c4bea9b30 100644 --- a/x-pack/test/spaces_api_integration/spaces_only/apis/copy_to_space.ts +++ b/x-pack/test/spaces_api_integration/spaces_only/apis/copy_to_space.ts @@ -11,7 +11,7 @@ import { copyToSpaceTestSuiteFactory } from '../../common/suites/copy_to_space'; export default function copyToSpacesOnlySuite({ getService }: FtrProviderContext) { const supertestWithoutAuth = getService('supertestWithoutAuth'); const esArchiver = getService('esArchiver'); - const es = getService('es'); + const es = getService('legacyEs'); const { copyToSpaceTest, diff --git a/x-pack/test/spaces_api_integration/spaces_only/apis/delete.ts b/x-pack/test/spaces_api_integration/spaces_only/apis/delete.ts index 350b682429778..64cbb7a02776c 100644 --- a/x-pack/test/spaces_api_integration/spaces_only/apis/delete.ts +++ b/x-pack/test/spaces_api_integration/spaces_only/apis/delete.ts @@ -12,7 +12,7 @@ import { deleteTestSuiteFactory } from '../../common/suites/delete'; export default function deleteSpaceTestSuite({ getService }: TestInvoker) { const supertestWithoutAuth = getService('supertestWithoutAuth'); const esArchiver = getService('esArchiver'); - const es = getService('es'); + const es = getService('legacyEs'); const { deleteTest, diff --git a/x-pack/test/token_api_integration/auth/header.js b/x-pack/test/token_api_integration/auth/header.js index 2317f62e63809..4b27fd5db3166 100644 --- a/x-pack/test/token_api_integration/auth/header.js +++ b/x-pack/test/token_api_integration/auth/header.js @@ -6,7 +6,7 @@ export default function ({ getService }) { const supertest = getService('supertestWithoutAuth'); - const es = getService('es'); + const es = getService('legacyEs'); async function createToken() { const { access_token: accessToken } = await es.shield.getAccessToken({ diff --git a/x-pack/test/token_api_integration/auth/session.js b/x-pack/test/token_api_integration/auth/session.js index 6045021894823..8a9f1d7a3f229 100644 --- a/x-pack/test/token_api_integration/auth/session.js +++ b/x-pack/test/token_api_integration/auth/session.js @@ -132,7 +132,7 @@ export default function ({ getService }) { // Let's delete tokens from `.security` index directly to simulate the case when // Elasticsearch automatically removes access/refresh token document from the index // after some period of time. - const esResponse = await getService('es').deleteByQuery({ + const esResponse = await getService('legacyEs').deleteByQuery({ index: '.security-tokens', q: 'doc_type:token', refresh: true, diff --git a/x-pack/test/token_api_integration/config.js b/x-pack/test/token_api_integration/config.js index 44086245a90c0..8cf9bc329a374 100644 --- a/x-pack/test/token_api_integration/config.js +++ b/x-pack/test/token_api_integration/config.js @@ -11,7 +11,7 @@ export default async function ({ readConfigFile }) { testFiles: [require.resolve('./auth')], servers: xPackAPITestsConfig.get('servers'), services: { - es: xPackAPITestsConfig.get('services.es'), + legacyEs: xPackAPITestsConfig.get('services.legacyEs'), supertestWithoutAuth: xPackAPITestsConfig.get('services.supertestWithoutAuth'), }, junit: { diff --git a/x-pack/test/upgrade_assistant_integration/config.js b/x-pack/test/upgrade_assistant_integration/config.js index 4cd4ca78d3a58..3a43d43543b61 100644 --- a/x-pack/test/upgrade_assistant_integration/config.js +++ b/x-pack/test/upgrade_assistant_integration/config.js @@ -20,9 +20,9 @@ export default async function ({ readConfigFile }) { testFiles: [require.resolve('./upgrade_assistant')], servers: xPackFunctionalTestsConfig.get('servers'), services: { + ...kibanaCommonConfig.get('services'), supertest: kibanaAPITestsConfig.get('services.supertest'), - es: LegacyEsProvider, - esArchiver: kibanaCommonConfig.get('services.esArchiver'), + legacyEs: LegacyEsProvider, }, esArchiver: xPackFunctionalTestsConfig.get('esArchiver'), junit: { diff --git a/x-pack/test/upgrade_assistant_integration/upgrade_assistant/reindexing.js b/x-pack/test/upgrade_assistant_integration/upgrade_assistant/reindexing.js index 233336c722611..137de18fc98d9 100644 --- a/x-pack/test/upgrade_assistant_integration/upgrade_assistant/reindexing.js +++ b/x-pack/test/upgrade_assistant_integration/upgrade_assistant/reindexing.js @@ -12,7 +12,7 @@ import { ReindexStatus, REINDEX_OP_TYPE } from '../../../legacy/plugins/upgrade_ export default function ({ getService }) { const supertest = getService('supertest'); const esArchiver = getService('esArchiver'); - const es = getService('es'); + const es = getService('legacyEs'); // Utility function that keeps polling API until reindex operation has completed or failed. const waitForReindexToComplete = async (indexName) => { diff --git a/x-pack/typings/jest_styled_components.d.ts b/x-pack/typings/jest_styled_components.d.ts new file mode 100644 index 0000000000000..86f82ffb013c7 --- /dev/null +++ b/x-pack/typings/jest_styled_components.d.ts @@ -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. + */ + +// https://github.com/styled-components/jest-styled-components/issues/264 + +declare namespace jest { + interface AsymmetricMatcher { + $$typeof: Symbol; //eslint-disable-line + sample?: string | RegExp | object | Array | Function; // eslint-disable-line + } + + type Value = string | number | RegExp | AsymmetricMatcher | undefined; + + interface Options { + media?: string; + modifier?: string; + supports?: string; + } + + interface Matchers { + toHaveStyleRule(property: string, value?: Value, options?: Options): R; + } +} diff --git a/yarn.lock b/yarn.lock index c9be00486696e..50a73b435e69b 100644 --- a/yarn.lock +++ b/yarn.lock @@ -87,6 +87,16 @@ lodash "^4.17.13" source-map "^0.5.0" +"@babel/generator@^7.6.3": + version "7.6.4" + resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.6.4.tgz#a4f8437287bf9671b07f483b76e3bb731bc97671" + integrity sha512-jsBuXkFoZxk0yWLyGI9llT9oiQ2FeTASmRFE32U+aaDTfoE92t78eroO7PTpU/OrYq38hlcDM6vbfLDaOLy+7w== + dependencies: + "@babel/types" "^7.6.3" + jsesc "^2.5.1" + lodash "^4.17.13" + source-map "^0.5.0" + "@babel/helper-annotate-as-pure@^7.0.0": version "7.0.0" resolved "https://registry.yarnpkg.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.0.0.tgz#323d39dd0b50e10c7c06ca7d7638e6864d8c5c32" @@ -304,6 +314,11 @@ resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.6.0.tgz#3e05d0647432a8326cb28d0de03895ae5a57f39b" integrity sha512-+o2q111WEx4srBs7L9eJmcwi655eD8sXniLqMB93TBK9GrNzGrxDWSjiqz2hLU0Ha8MTXFIP0yd9fNdP+m43ZQ== +"@babel/parser@^7.6.3": + version "7.6.4" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.6.4.tgz#cb9b36a7482110282d5cb6dd424ec9262b473d81" + integrity sha512-D8RHPW5qd0Vbyo3qb+YjO5nvUVRTXFLQ/FsDxJU2Nqz4uB5EnUN0ZQSEYpvTIbRuttig1XbHWU5oMeQwQSAA+A== + "@babel/plugin-proposal-async-generator-functions@^7.2.0": version "7.2.0" resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.2.0.tgz#b289b306669dce4ad20b0252889a15768c9d417e" @@ -990,7 +1005,7 @@ dependencies: regenerator-runtime "^0.13.2" -"@babel/runtime@^7.4.4": +"@babel/runtime@^7.4.4", "@babel/runtime@^7.6.3": version "7.7.2" resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.7.2.tgz#111a78002a5c25fc8e3361bedc9529c696b85a6a" integrity sha512-JONRbXbTXc9WQE2mAZd1p0Z3DZ/6vaQIkgYMSTP3KjRCyd7rCZCcfhCyX+YjwcKxcZ82UrxbRD358bpExNgrjw== @@ -1045,6 +1060,21 @@ globals "^11.1.0" lodash "^4.17.13" +"@babel/traverse@^7.4.5": + version "7.6.3" + resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.6.3.tgz#66d7dba146b086703c0fb10dd588b7364cec47f9" + integrity sha512-unn7P4LGsijIxaAJo/wpoU11zN+2IaClkQAxcJWBNCMS6cmVh802IyLHNkAjQ0iYnRS3nnxk5O3fuXW28IMxTw== + dependencies: + "@babel/code-frame" "^7.5.5" + "@babel/generator" "^7.6.3" + "@babel/helper-function-name" "^7.1.0" + "@babel/helper-split-export-declaration" "^7.4.4" + "@babel/parser" "^7.6.3" + "@babel/types" "^7.6.3" + debug "^4.1.0" + globals "^11.1.0" + lodash "^4.17.13" + "@babel/types@^7.0.0", "@babel/types@^7.2.0", "@babel/types@^7.3.0", "@babel/types@^7.4.0", "@babel/types@^7.4.4", "@babel/types@^7.5.5": version "7.5.5" resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.5.5.tgz#97b9f728e182785909aa4ab56264f090a028d18a" @@ -1063,6 +1093,15 @@ lodash "^4.17.13" to-fast-properties "^2.0.0" +"@babel/types@^7.6.3": + version "7.6.3" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.6.3.tgz#3f07d96f854f98e2fbd45c64b0cb942d11e8ba09" + integrity sha512-CqbcpTxMcpuQTMhjI37ZHVgjBkysg5icREQIEZ0eG1yCNwg3oy+5AaLiOKmjsCj6nqOsa6Hf0ObjRVwokb7srA== + dependencies: + esutils "^2.0.2" + lodash "^4.17.13" + to-fast-properties "^2.0.0" + "@cnakazawa/watch@^1.0.3": version "1.0.3" resolved "https://registry.yarnpkg.com/@cnakazawa/watch/-/watch-1.0.3.tgz#099139eaec7ebf07a27c1786a3ff64f39464d2ef" @@ -1126,21 +1165,6 @@ ts-debounce "^1.0.0" uuid "^3.3.2" -"@elastic/ctags-langserver@^0.1.11": - version "0.1.11" - resolved "https://registry.yarnpkg.com/@elastic/ctags-langserver/-/ctags-langserver-0.1.11.tgz#e4725a6a763a2ff61fd02bbe2b42aa70db5d0f3f" - integrity sha512-ODNcD+zFmuhMm649/4fGQXD1msafvBaHKsk9PDXTjLrUMozrCWj99tGKqR5HcwrdkoMr/3YRBre2r4cyomtoBw== - dependencies: - "@elastic/lsp-extension" "^0.1.1" - "@elastic/node-ctags" "1.0.2" - commander "^2.11.0" - find-root "^1.1.0" - line-column "^1.0.2" - minimatch "3.0.4" - mz "^2.7.0" - parse-gitignore "1.0.1" - vscode-languageserver "^5.2.1" - "@elastic/elasticsearch@^7.4.0": version "7.4.0" resolved "https://registry.yarnpkg.com/@elastic/elasticsearch/-/elasticsearch-7.4.0.tgz#57f4066acf25e9d4e9b4f6376088433aae6f25d4" @@ -1188,10 +1212,10 @@ tabbable "^1.1.0" uuid "^3.1.0" -"@elastic/eui@14.9.0": - version "14.9.0" - resolved "https://registry.yarnpkg.com/@elastic/eui/-/eui-14.9.0.tgz#934ab8d51c56671635dc17ac20ec325f43ceda75" - integrity sha512-0ZztvfRO3SNgHtS8a+4i6CSG3Yc+C0Kodzc7obY5wkOzissrnbwLZdU79hU/H6DHYCt/zYDdGcrDp6BeD67RtQ== +"@elastic/eui@16.0.0": + version "16.0.0" + resolved "https://registry.yarnpkg.com/@elastic/eui/-/eui-16.0.0.tgz#511898bfbeba5ffea6ac96c077d1184d657a451d" + integrity sha512-i9t13PzrsfBUolMZ6n2X9aAYJ/wUI2NJduCQlDU4zrXfFrM1LFJ5/KSCcpgzI8VNDakeA3PTml+oqD7J0qGA3g== dependencies: "@types/lodash" "^4.14.116" "@types/numeral" "^0.0.25" @@ -1203,12 +1227,12 @@ lodash "^4.17.11" numeral "^2.0.6" prop-types "^15.6.0" - react-ace "^5.5.0" + react-ace "^7.0.5" react-beautiful-dnd "^10.1.0" react-focus-lock "^1.17.7" - react-input-autosize "^2.2.1" + react-input-autosize "^2.2.2" react-is "~16.3.0" - react-virtualized "^9.18.5" + react-virtualized "^9.21.2" resize-observer-polyfill "^1.5.0" tabbable "^3.0.0" uuid "^3.1.0" @@ -1267,7 +1291,7 @@ vscode-languageserver-types "^3.0.3" yarn "^1.12.3" -"@elastic/lsp-extension@^0.1.1", "@elastic/lsp-extension@^0.1.2": +"@elastic/lsp-extension@^0.1.2": version "0.1.2" resolved "https://registry.yarnpkg.com/@elastic/lsp-extension/-/lsp-extension-0.1.2.tgz#7356d951d272e833d02a81e13a0ef710f9474195" integrity sha512-yDj5Ht5KCHDwBlgrlusmLtV/Yxa5z2f3vMSYbNFotoRMup8345/ZwlFp/zmyl04iFOVpT8ouB34+Ttpzbpd3vA== @@ -1304,11 +1328,6 @@ resolved "https://registry.yarnpkg.com/@elastic/node-crypto/-/node-crypto-1.0.0.tgz#4d325df333fe1319556bb4d54214098ada1171d4" integrity sha512-bbjbEyILPRTRt0xnda18OttLtlkJBPuXx3CjISUSn9jhWqHoFMzfOaZ73D5jxZE2SaFZUrJYfPpqXP6qqPufAQ== -"@elastic/node-ctags@1.0.2": - version "1.0.2" - resolved "https://registry.yarnpkg.com/@elastic/node-ctags/-/node-ctags-1.0.2.tgz#447d7694a5598f9413fe2b6f356d56f64f612dfd" - integrity sha512-EHhJ0NPlCvYy+gbzBMU4/Z/55hftfdwlAG8JwOy7g0ITmH6rFPanEnzg1WL3/L+pp8OlYHyvDLwmyg0+06y8LQ== - "@elastic/numeral@2.3.3": version "2.3.3" resolved "https://registry.yarnpkg.com/@elastic/numeral/-/numeral-2.3.3.tgz#94d38a35bd315efa7a6918b22695128fc40a885e" @@ -1407,6 +1426,13 @@ dependencies: "@emotion/memoize" "0.7.3" +"@emotion/is-prop-valid@^0.8.3": + version "0.8.4" + resolved "https://registry.yarnpkg.com/@emotion/is-prop-valid/-/is-prop-valid-0.8.4.tgz#cf1dcfc1812c226f05e1ba53592eb6b51e734990" + integrity sha512-QBW8h6wVQgeQ55F52rNaprEJxtVR+/ScOP8/V1ScSpPzKqHdFB9QVqby0Z50sqS8mcaeIl5vR1vQpKwJbIS6NQ== + dependencies: + "@emotion/memoize" "0.7.3" + "@emotion/memoize@0.7.2": version "0.7.2" resolved "https://registry.yarnpkg.com/@emotion/memoize/-/memoize-0.7.2.tgz#7f4c71b7654068dfcccad29553520f984cc66b30" @@ -1462,12 +1488,12 @@ "@emotion/styled-base" "^10.0.23" babel-plugin-emotion "^10.0.23" -"@emotion/stylis@0.8.4": +"@emotion/stylis@0.8.4", "@emotion/stylis@^0.8.4": version "0.8.4" resolved "https://registry.yarnpkg.com/@emotion/stylis/-/stylis-0.8.4.tgz#6c51afdf1dd0d73666ba09d2eb6c25c220d6fe4c" integrity sha512-TLmkCVm8f8gH0oLv+HWKiu7e8xmBIaokhxcEKPh1m8pXiV/akCiq50FvYgOwY42rjejck8nsdQxZlXZ7pmyBUQ== -"@emotion/unitless@0.7.4": +"@emotion/unitless@0.7.4", "@emotion/unitless@^0.7.4": version "0.7.4" resolved "https://registry.yarnpkg.com/@emotion/unitless/-/unitless-0.7.4.tgz#a87b4b04e5ae14a88d48ebef15015f6b7d1f5677" integrity sha512-kBa+cDHOR9jpRJ+kcGMsysrls0leukrm68DmFQoMIWQcXdr2cZvyvypWuGYT7U+9kAExUE7+T7r6G3C3A6L8MQ== @@ -3846,6 +3872,14 @@ resolved "https://registry.yarnpkg.com/@types/react-intl/-/react-intl-2.3.17.tgz#e1fc6e46e8af58bdef9531259d509380a8a99e8e" integrity sha512-FGd6J1GQ7zvl1GZ3BBev83B7nfak8dqoR2PZ+l5MoisKMpd4xOLhZJC1ugpmk3Rz5F85t6HbOg9mYqXW97BsNA== +"@types/react-native@*": + version "0.60.22" + resolved "https://registry.yarnpkg.com/@types/react-native/-/react-native-0.60.22.tgz#ba199a441cb0612514244ffb1d0fe6f04c878575" + integrity sha512-LTXMKEyGA+x4kadmjujX6yAgpcaZutJ01lC7zLJWCULaZg7Qw5/3iOQpwIJRUcOc+a8A2RR7rSxplehVf9IuhA== + dependencies: + "@types/prop-types" "*" + "@types/react" "*" + "@types/react-redux@^6.0.6": version "6.0.6" resolved "https://registry.yarnpkg.com/@types/react-redux/-/react-redux-6.0.6.tgz#87f1d0a6ea901b93fcaf95fa57641ff64079d277" @@ -4029,13 +4063,14 @@ dependencies: "@types/node" "*" -"@types/styled-components@^3.0.2": - version "3.0.2" - resolved "https://registry.yarnpkg.com/@types/styled-components/-/styled-components-3.0.2.tgz#274133bfafaca17f28707b667858bce197ae3b84" - integrity sha512-nG9swaAqmSrUDXyjpE0NxabjVYAGlmtqWXlCpRWRIZBMbTkdcyQULC+ElvTfghTc+1ANJjn6DCyUQirF5a2OOg== +"@types/styled-components@^4.4.0": + version "4.4.0" + resolved "https://registry.yarnpkg.com/@types/styled-components/-/styled-components-4.4.0.tgz#15a3d59533fd3a5bd013db4a7c4422ec542c59d2" + integrity sha512-QFl+w3hQJNHE64Or3PXMFpC3HAQDiuQLi5o9m1XPEwYWfgCZtAribO5ksjxnO8U0LG8Parh0ESCgVxo4VfxlHg== dependencies: - "@types/node" "*" "@types/react" "*" + "@types/react-native" "*" + csstype "^2.2.0" "@types/superagent@*": version "3.8.4" @@ -4738,13 +4773,13 @@ aggregate-error@^3.0.0: string.prototype.padstart "^3.0.0" symbol.prototype.description "^1.0.0" -airbnb-prop-types@^2.13.2: - version "2.13.2" - resolved "https://registry.yarnpkg.com/airbnb-prop-types/-/airbnb-prop-types-2.13.2.tgz#43147a5062dd2a4a5600e748a47b64004cc5f7fc" - integrity sha512-2FN6DlHr6JCSxPPi25EnqGaXC4OC3/B3k1lCd6MMYrZ51/Gf/1qDfaR+JElzWa+Tl7cY2aYOlsYJGFeQyVHIeQ== +airbnb-prop-types@^2.15.0: + version "2.15.0" + resolved "https://registry.yarnpkg.com/airbnb-prop-types/-/airbnb-prop-types-2.15.0.tgz#5287820043af1eb469f5b0af0d6f70da6c52aaef" + integrity sha512-jUh2/hfKsRjNFC4XONQrxo/n/3GG4Tn6Hl0WlFQN5PY9OMC9loSCoAYKnZsWaP8wEfd5xcrPloK0Zg6iS1xwVA== dependencies: - array.prototype.find "^2.0.4" - function.prototype.name "^1.1.0" + array.prototype.find "^2.1.0" + function.prototype.name "^1.1.1" has "^1.0.3" is-regex "^1.0.4" object-is "^1.0.1" @@ -4752,7 +4787,7 @@ airbnb-prop-types@^2.13.2: object.entries "^1.1.0" prop-types "^15.7.2" prop-types-exact "^1.2.0" - react-is "^16.8.6" + react-is "^16.9.0" ajv-errors@^1.0.0: version "1.0.0" @@ -4890,15 +4925,10 @@ angular-ui-ace@0.2.3: resolved "https://registry.yarnpkg.com/angular-ui-ace/-/angular-ui-ace-0.2.3.tgz#3cb903428100621a367fc7f641440e97a42a26d0" integrity sha1-PLkDQoEAYho2f8f2QUQOl6QqJtA= -angular@>=1.0.6: - version "1.6.9" - resolved "https://registry.yarnpkg.com/angular/-/angular-1.6.9.tgz#bc812932e18909038412d594a5990f4bb66c0619" - integrity sha512-6igWH2GIsxV+J38wNWCh8oyjaZsrIPIDO35twloIUyjlF2Yit6UyLAWujHP05ma/LFxTsx4NtYibRoMNBXPR1A== - -angular@^1.7.8: - version "1.7.8" - resolved "https://registry.yarnpkg.com/angular/-/angular-1.7.8.tgz#b77ede272ce1b261e3be30c1451a0b346905a3c9" - integrity sha512-wtef/y4COxM7ZVhddd7JtAAhyYObq9YXKar9tsW7558BImeVYteJiTxCKeJOL45lJ/+7B4wrAC49j8gTFYEthg== +angular@>=1.0.6, angular@^1.7.9: + version "1.7.9" + resolved "https://registry.yarnpkg.com/angular/-/angular-1.7.9.tgz#e52616e8701c17724c3c238cfe4f9446fd570bc4" + integrity sha512-5se7ZpcOtu0MBFlzGv5dsM1quQDoDeUTwZrWjGtTNA7O88cD8TEk5IEKCTDa3uECV9XnvKREVUr7du1ACiWGFQ== ansi-align@^2.0.0: version "2.0.0" @@ -5007,6 +5037,11 @@ ansi-regex@^4.1.0: resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-4.1.0.tgz#8b9f8f08cf1acb843756a839ca8c7e3168c51997" integrity sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg== +ansi-regex@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.0.tgz#388539f55179bf39339c81af30a654d69f87cb75" + integrity sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg== + ansi-styles@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-1.1.0.tgz#eaecbf66cd706882760b2f4691582b8f55d7a7de" @@ -5565,7 +5600,7 @@ array-unique@^0.3.2: resolved "https://registry.yarnpkg.com/array-unique/-/array-unique-0.3.2.tgz#a894b75d4bc4f6cd679ef3244a9fd8f46ae2d428" integrity sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg= -array.prototype.find@^2.0.4: +array.prototype.find@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/array.prototype.find/-/array.prototype.find-2.1.0.tgz#630f2eaf70a39e608ac3573e45cf8ccd0ede9ad7" integrity sha512-Wn41+K1yuO5p7wRZDl7890c3xvv5UBrfVXTVIe28rSQb6LS0fZMDrQB6PAcxQFRFy6vJTLDc3A2+3CjQdzVKRg== @@ -6168,6 +6203,16 @@ babel-plugin-react-docgen@^3.0.0: resolved "https://registry.yarnpkg.com/babel-plugin-require-context-hook-babel7/-/babel-plugin-require-context-hook-babel7-1.0.0.tgz#1273d4cee7e343d0860966653759a45d727e815d" integrity sha512-kez0BAN/cQoyO1Yu1nre1bQSYZEF93Fg7VQiBHFfMWuaZTy7vJSTT4FY68FwHTYG53Nyt0A7vpSObSVxwweQeQ== +"babel-plugin-styled-components@>= 1": + version "1.10.6" + resolved "https://registry.yarnpkg.com/babel-plugin-styled-components/-/babel-plugin-styled-components-1.10.6.tgz#f8782953751115faf09a9f92431436912c34006b" + integrity sha512-gyQj/Zf1kQti66100PhrCRjI5ldjaze9O0M3emXRPAN80Zsf8+e1thpTpaXJXVHXtaM4/+dJEgZHyS9Its+8SA== + dependencies: + "@babel/helper-annotate-as-pure" "^7.0.0" + "@babel/helper-module-imports" "^7.0.0" + babel-plugin-syntax-jsx "^6.18.0" + lodash "^4.17.11" + babel-plugin-syntax-jsx@^6.18.0: version "6.18.0" resolved "https://registry.yarnpkg.com/babel-plugin-syntax-jsx/-/babel-plugin-syntax-jsx-6.18.0.tgz#0af32a9a6e13ca7a3fd5069e62d7b0f58d0d8946" @@ -6794,7 +6839,7 @@ brace-expansion@^1.1.7: balanced-match "^1.0.0" concat-map "0.0.1" -brace@0.11.1, brace@^0.11.0: +brace@0.11.1, brace@^0.11.0, brace@^0.11.1: version "0.11.1" resolved "https://registry.yarnpkg.com/brace/-/brace-0.11.1.tgz#4896fcc9d544eef45f4bb7660db320d3b379fe58" integrity sha1-SJb8ydVE7vRfS7dmDbMg07N5/lg= @@ -7040,14 +7085,6 @@ buffer@^4.3.0: ieee754 "^1.1.4" isarray "^1.0.0" -buffer@^5.0.3: - version "5.0.8" - resolved "https://registry.yarnpkg.com/buffer/-/buffer-5.0.8.tgz#84daa52e7cf2fa8ce4195bc5cf0f7809e0930b24" - integrity sha512-xXvjQhVNz50v2nPeoOsNqWCLGfiv4ji/gXZM28jnVwdLJxH4mFyqgqCKfaK9zf1KUbG6zTkjLOy7ou+jSMarGA== - dependencies: - base64-js "^1.0.2" - ieee754 "^1.1.4" - buffer@^5.1.0, buffer@^5.2.0: version "5.2.1" resolved "https://registry.yarnpkg.com/buffer/-/buffer-5.2.1.tgz#dd57fa0f109ac59c602479044dca7b8b3d0b71d6" @@ -7355,7 +7392,7 @@ camelcase@^1.0.2: resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-1.2.1.tgz#9bb5304d2e0b56698b2c758b08a3eaa9daa58a39" integrity sha1-m7UwTS4LVmmLLHWLCKPqqdqlijk= -camelcase@^2.0.0: +camelcase@^2.0.0, camelcase@^2.0.1: version "2.1.1" resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-2.1.1.tgz#7c1d16d679a1bbe59ca02cacecfb011e201f5a1f" integrity sha1-fB0W1nmhu+WcoCys7PsBHiAfWh8= @@ -7385,6 +7422,11 @@ camelcase@^5.3.1: resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320" integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg== +camelize@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/camelize/-/camelize-1.0.0.tgz#164a5483e630fa4321e5af07020e531831b2609b" + integrity sha1-FkpUg+Yw+kMh5a8HAg5TGDGyYJs= + can-use-dom@^0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/can-use-dom/-/can-use-dom-0.1.0.tgz#22cc4a34a0abc43950f42c6411024a3f6366b45a" @@ -7980,7 +8022,7 @@ cliui@^2.1.0: right-align "^0.1.1" wordwrap "0.0.2" -cliui@^3.2.0: +cliui@^3.0.3, cliui@^3.2.0: version "3.2.0" resolved "https://registry.yarnpkg.com/cliui/-/cliui-3.2.0.tgz#120601537a916d29940f934da3b48d585a39213d" integrity sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0= @@ -8076,6 +8118,11 @@ cloneable-readable@^1.0.0: process-nextick-args "^2.0.0" readable-stream "^2.3.5" +clsx@^1.0.1: + version "1.0.4" + resolved "https://registry.yarnpkg.com/clsx/-/clsx-1.0.4.tgz#0c0171f6d5cb2fe83848463c15fcc26b4df8c2ec" + integrity sha512-1mQ557MIZTrL/140j+JVdRM6e31/OA4vTYxXgqIIZlndyfjHpyawKZia1Im05Vp9BWmImkcNrNtFYQMyFcgJDg== + cmd-shim@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/cmd-shim/-/cmd-shim-2.1.0.tgz#e59a08d4248dda3bb502044083a4db4ac890579a" @@ -9112,14 +9159,14 @@ css-select@^2.0.0: domutils "^1.7.0" nth-check "^1.0.2" -css-to-react-native@^2.0.3: - version "2.0.4" - resolved "https://registry.yarnpkg.com/css-to-react-native/-/css-to-react-native-2.0.4.tgz#cf4cc407558b3474d4ba8be1a2cd3b6ce713101b" - integrity sha1-z0zEB1WLNHTUuovhos07bOcTEBs= +css-to-react-native@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/css-to-react-native/-/css-to-react-native-3.0.0.tgz#62dbe678072a824a689bcfee011fc96e02a7d756" + integrity sha512-Ro1yETZA813eoyUp2GDBhG2j+YggidUmzO1/v9eYBKR2EHVEniE2MI/NqpTQ954BMpTPZFsGNPm46qFB9dpaPQ== dependencies: + camelize "^1.0.0" css-color-keywords "^1.0.0" - fbjs "^0.8.5" - postcss-value-parser "^3.3.0" + postcss-value-parser "^4.0.2" css-tree@1.0.0-alpha.28: version "1.0.0-alpha.28" @@ -9213,6 +9260,11 @@ csstype@^2.5.7: resolved "https://registry.yarnpkg.com/csstype/-/csstype-2.6.3.tgz#b701e5968245bf9b08d54ac83d00b624e622a9fa" integrity sha512-rINUZXOkcBmoHWEyu7JdHu5JMzkGRoMX4ov9830WNgxf5UYxcBUO0QTKAqeJ5EZfSdlrcJYkC8WwfVW7JYi4yg== +csstype@^2.6.7: + version "2.6.7" + resolved "https://registry.yarnpkg.com/csstype/-/csstype-2.6.7.tgz#20b0024c20b6718f4eda3853a1f5a1cce7f5e4a5" + integrity sha512-9Mcn9sFbGBAdmimWb2gLVDtFJzeKtDGIr76TUqmjZrw9LFXBMSU70lcs+C0/7fyCd6iBDqmksUcCOUIkisPHsQ== + cuint@^0.2.2: version "0.2.2" resolved "https://registry.yarnpkg.com/cuint/-/cuint-0.2.2.tgz#408086d409550c2631155619e9fa7bcadc3b991b" @@ -9245,7 +9297,15 @@ cyclist@~0.2.2: resolved "https://registry.yarnpkg.com/cyclist/-/cyclist-0.2.2.tgz#1b33792e11e914a2fd6d6ed6447464444e5fa640" integrity sha1-GzN5LhHpFKL9bW7WRHRkRE5fpkA= -cypress@^3.5.5: +cypress-multi-reporters@^1.2.3: + version "1.2.3" + resolved "https://registry.yarnpkg.com/cypress-multi-reporters/-/cypress-multi-reporters-1.2.3.tgz#4ba39373631c6521d21931d73f6b0bafa1ccbf83" + integrity sha512-W3ItWsbSgMfsQFTuB89OXY5gyqLuM0O2lNEn+mcQAYeMs36TxVLAg3q+Hk0Om+NcWj8OLhM06lBQpnu9+i4gug== + dependencies: + debug "^4.1.1" + lodash "^4.17.11" + +cypress@^3.6.1: version "3.6.1" resolved "https://registry.yarnpkg.com/cypress/-/cypress-3.6.1.tgz#4420957923879f60b7a5146ccbf81841a149b653" integrity sha512-6n0oqENdz/oQ7EJ6IgESNb2M7Bo/70qX9jSJsAziJTC3kICfEMmJUlrAnP9bn+ut24MlXQST5nRXhUP5nRIx6A== @@ -10174,6 +10234,11 @@ diagnostics@^1.1.1: enabled "1.0.x" kuler "1.0.x" +diff-match-patch@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/diff-match-patch/-/diff-match-patch-1.0.4.tgz#6ac4b55237463761c4daf0dc603eb869124744b1" + integrity sha512-Uv3SW8bmH9nAtHKaKSanOQmj2DnlH65fUpcrMdfdaOxUG02QQ4YGZ8AE7kKOMisF7UqvOlGKVYWRvezdncW9lg== + diff-sequences@^24.0.0: version "24.0.0" resolved "https://registry.yarnpkg.com/diff-sequences/-/diff-sequences-24.0.0.tgz#cdf8e27ed20d8b8d3caccb4e0c0d8fe31a173013" @@ -10301,6 +10366,14 @@ dom-helpers@^3.3.1: dependencies: "@babel/runtime" "^7.1.2" +dom-helpers@^5.0.0: + version "5.1.3" + resolved "https://registry.yarnpkg.com/dom-helpers/-/dom-helpers-5.1.3.tgz#7233248eb3a2d1f74aafca31e52c5299cc8ce821" + integrity sha512-nZD1OtwfWGRBWlpANxacBEZrEuLa16o1nh7YopFWeoF68Zt8GGEmzHu6Xv4F3XaFIC+YXtTLrzgqKxFgLEe4jw== + dependencies: + "@babel/runtime" "^7.6.3" + csstype "^2.6.7" + dom-serialize@^2.2.0: version "2.2.1" resolved "https://registry.yarnpkg.com/dom-serialize/-/dom-serialize-2.2.1.tgz#562ae8999f44be5ea3076f5419dcd59eb43ac95b" @@ -10813,38 +10886,47 @@ envify@^3.0.0: jstransform "^11.0.3" through "~2.3.4" -enzyme-adapter-react-16@^1.14.0: - version "1.14.0" - resolved "https://registry.yarnpkg.com/enzyme-adapter-react-16/-/enzyme-adapter-react-16-1.14.0.tgz#204722b769172bcf096cb250d33e6795c1f1858f" - integrity sha512-7PcOF7pb4hJUvjY7oAuPGpq3BmlCig3kxXGi2kFx0YzJHppqX1K8IIV9skT1IirxXlu8W7bneKi+oQ10QRnhcA== +enzyme-adapter-react-16@^1.15.1: + version "1.15.1" + resolved "https://registry.yarnpkg.com/enzyme-adapter-react-16/-/enzyme-adapter-react-16-1.15.1.tgz#8ad55332be7091dc53a25d7d38b3485fc2ba50d5" + integrity sha512-yMPxrP3vjJP+4wL/qqfkT6JAIctcwKF+zXO6utlGPgUJT2l4tzrdjMDWGd/Pp1BjHBcljhN24OzNEGRteibJhA== dependencies: - enzyme-adapter-utils "^1.12.0" + enzyme-adapter-utils "^1.12.1" + enzyme-shallow-equal "^1.0.0" has "^1.0.3" object.assign "^4.1.0" object.values "^1.1.0" prop-types "^15.7.2" - react-is "^16.8.6" + react-is "^16.10.2" react-test-renderer "^16.0.0-0" semver "^5.7.0" -enzyme-adapter-utils@^1.12.0: - version "1.12.0" - resolved "https://registry.yarnpkg.com/enzyme-adapter-utils/-/enzyme-adapter-utils-1.12.0.tgz#96e3730d76b872f593e54ce1c51fa3a451422d93" - integrity sha512-wkZvE0VxcFx/8ZsBw0iAbk3gR1d9hK447ebnSYBf95+r32ezBq+XDSAvRErkc4LZosgH8J7et7H7/7CtUuQfBA== +enzyme-adapter-utils@^1.12.1: + version "1.12.1" + resolved "https://registry.yarnpkg.com/enzyme-adapter-utils/-/enzyme-adapter-utils-1.12.1.tgz#e828e0d038e2b1efa4b9619ce896226f85c9dd88" + integrity sha512-KWiHzSjZaLEoDCOxY8Z1RAbUResbqKN5bZvenPbfKtWorJFVETUw754ebkuCQ3JKm0adx1kF8JaiR+PHPiP47g== dependencies: - airbnb-prop-types "^2.13.2" - function.prototype.name "^1.1.0" + airbnb-prop-types "^2.15.0" + function.prototype.name "^1.1.1" object.assign "^4.1.0" - object.fromentries "^2.0.0" + object.fromentries "^2.0.1" prop-types "^15.7.2" - semver "^5.6.0" + semver "^5.7.0" -enzyme-to-json@^3.3.4: - version "3.3.5" - resolved "https://registry.yarnpkg.com/enzyme-to-json/-/enzyme-to-json-3.3.5.tgz#f8eb82bd3d5941c9d8bc6fd9140030777d17d0af" - integrity sha512-DmH1wJ68HyPqKSYXdQqB33ZotwfUhwQZW3IGXaNXgR69Iodaoj8TF/D9RjLdz4pEhGq2Tx2zwNUIjBuqoZeTgA== +enzyme-shallow-equal@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/enzyme-shallow-equal/-/enzyme-shallow-equal-1.0.0.tgz#d8e4603495e6ea279038eef05a4bf4887b55dc69" + integrity sha512-VUf+q5o1EIv2ZaloNQQtWCJM9gpeux6vudGVH6vLmfPXFLRuxl5+Aq3U260wof9nn0b0i+P5OEUXm1vnxkRpXQ== dependencies: - lodash "^4.17.4" + has "^1.0.3" + object-is "^1.0.1" + +enzyme-to-json@^3.4.3: + version "3.4.3" + resolved "https://registry.yarnpkg.com/enzyme-to-json/-/enzyme-to-json-3.4.3.tgz#ed4386f48768ed29e2d1a2910893542c34e7e0af" + integrity sha512-jqNEZlHqLdz7OTpXSzzghArSS3vigj67IU/fWkPyl1c0TCj9P5s6Ze0kRkYZWNEoCqCR79xlQbigYlMx5erh8A== + dependencies: + lodash "^4.17.15" enzyme@^3.10.0: version "3.10.0" @@ -10907,41 +10989,23 @@ error@7.0.2, error@^7.0.0, error@^7.0.2: string-template "~0.2.1" xtend "~4.0.0" -es-abstract@^1.10.0, es-abstract@^1.11.0, es-abstract@^1.12.0, es-abstract@^1.13.0, es-abstract@^1.5.0: - version "1.13.0" - resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.13.0.tgz#ac86145fdd5099d8dd49558ccba2eaf9b88e24e9" - integrity sha512-vDZfg/ykNxQVwup/8E1BZhVzFfBxs9NqMzGcvIJrqg5k2/5Za2bWo40dK2J1pgLngZ7c+Shh8lwYtLGyrwPutg== +es-abstract@^1.10.0, es-abstract@^1.11.0, es-abstract@^1.12.0, es-abstract@^1.13.0, es-abstract@^1.14.2, es-abstract@^1.15.0, es-abstract@^1.4.3, es-abstract@^1.5.0, es-abstract@^1.5.1, es-abstract@^1.7.0, es-abstract@^1.9.0: + version "1.16.0" + resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.16.0.tgz#d3a26dc9c3283ac9750dca569586e976d9dcc06d" + integrity sha512-xdQnfykZ9JMEiasTAJZJdMWCQ1Vm00NBw79/AWi7ELfZuuPCSOMDZbT9mkOfSctVtfhb+sAAzrm+j//GjjLHLg== dependencies: es-to-primitive "^1.2.0" function-bind "^1.1.1" has "^1.0.3" + has-symbols "^1.0.0" is-callable "^1.1.4" is-regex "^1.0.4" - object-keys "^1.0.12" - -es-abstract@^1.4.3, es-abstract@^1.9.0: - version "1.12.0" - resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.12.0.tgz#9dbbdd27c6856f0001421ca18782d786bf8a6165" - integrity sha512-C8Fx/0jFmV5IPoMOFPA9P9G5NtqW+4cOPit3MIuvR2t7Ag2K15EJTpxnHAYTzL+aYQJIESYeXZmDBfOBE1HcpA== - dependencies: - es-to-primitive "^1.1.1" - function-bind "^1.1.1" - has "^1.0.1" - is-callable "^1.1.3" - is-regex "^1.0.4" - -es-abstract@^1.5.1, es-abstract@^1.7.0: - version "1.10.0" - resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.10.0.tgz#1ecb36c197842a00d8ee4c2dfd8646bb97d60864" - integrity sha512-/uh/DhdqIOSkAWifU+8nG78vlQxdLckUdI/sPgy0VhuXi2qJ7T8czBmqIYtLQVpCIFYafChnsRsB5pyb1JdmCQ== - dependencies: - es-to-primitive "^1.1.1" - function-bind "^1.1.1" - has "^1.0.1" - is-callable "^1.1.3" - is-regex "^1.0.4" + object-inspect "^1.6.0" + object-keys "^1.1.1" + string.prototype.trimleft "^2.1.0" + string.prototype.trimright "^2.1.0" -es-to-primitive@^1.1.1, es-to-primitive@^1.2.0: +es-to-primitive@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/es-to-primitive/-/es-to-primitive-1.2.0.tgz#edf72478033456e8dda8ef09e00ad9650707f377" integrity sha512-qZryBOJjV//LaxLTV6UC//WewneB3LcXOL9NP++ozKVXsIIIpm/2c13UDiD9Jp2eThsecw9m3jPqDwTyobcdbg== @@ -12238,7 +12302,7 @@ fbjs@^0.8.0, fbjs@^0.8.1, fbjs@^0.8.16: setimmediate "^1.0.5" ua-parser-js "^0.7.18" -fbjs@^0.8.4, fbjs@^0.8.5, fbjs@^0.8.9: +fbjs@^0.8.4, fbjs@^0.8.9: version "0.8.16" resolved "https://registry.yarnpkg.com/fbjs/-/fbjs-0.8.16.tgz#5e67432f550dc41b572bf55847b8aca64e5337db" integrity sha1-XmdDL1UNxBtXK/VYR7ispk5TN9s= @@ -13091,11 +13155,26 @@ function.prototype.name@^1.1.0: function-bind "^1.1.1" is-callable "^1.1.3" +function.prototype.name@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/function.prototype.name/-/function.prototype.name-1.1.1.tgz#6d252350803085abc2ad423d4fe3be2f9cbda392" + integrity sha512-e1NzkiJuw6xqVH7YSdiW/qDHebcmMhPNe6w+4ZYYEg0VA+LaLzx37RimbPLuonHhYGFGPx1ME2nSi74JiaCr/Q== + dependencies: + define-properties "^1.1.3" + function-bind "^1.1.1" + functions-have-names "^1.1.1" + is-callable "^1.1.4" + functional-red-black-tree@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz#1b0ab3bd553b2a0d6399d29c0e3ea0b252078327" integrity sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc= +functions-have-names@^1.1.1: + version "1.2.0" + resolved "https://registry.yarnpkg.com/functions-have-names/-/functions-have-names-1.2.0.tgz#83da7583e4ea0c9ac5ff530f73394b033e0bf77d" + integrity sha512-zKXyzksTeaCSw5wIX79iCA40YAa6CJMJgNg9wdkU/ERBrIdPSimPICYiLp65lRbSBqtiHql/HZfS2DyI/AH6tQ== + fuse.js@^3.4.4: version "3.4.5" resolved "https://registry.yarnpkg.com/fuse.js/-/fuse.js-3.4.5.tgz#8954fb43f9729bd5dbcb8c08f251db552595a7a6" @@ -14600,14 +14679,7 @@ has-values@^1.0.0: is-number "^3.0.0" kind-of "^4.0.0" -has@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/has/-/has-1.0.1.tgz#8461733f538b0837c9361e39a9ab9e9704dc2f28" - integrity sha1-hGFzP1OLCDfJNh45qauelwTcLyg= - dependencies: - function-bind "^1.0.2" - -has@^1.0.1, has@^1.0.3, has@~1.0.3: +has@^1.0.0, has@^1.0.1, has@^1.0.3, has@~1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796" integrity sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw== @@ -16948,10 +17020,10 @@ jest-specific-snapshot@^2.0.0: dependencies: jest-snapshot "^24.1.0" -jest-styled-components@^6.3.3: - version "6.3.3" - resolved "https://registry.yarnpkg.com/jest-styled-components/-/jest-styled-components-6.3.3.tgz#e15bbda13a6b6ff876d6b783751fe9840860c52a" - integrity sha512-RBMPZSJJSgPDTTJsuYzx5fsij/CULaqQNZOWkn8J/L++rX6P830o2vB9CXGzfQf/bVq9qGr1ZBNoivi+v6JPYg== +jest-styled-components@^7.0.0-beta.2: + version "7.0.0-beta.2" + resolved "https://registry.yarnpkg.com/jest-styled-components/-/jest-styled-components-7.0.0-beta.2.tgz#0442a8491a2411ea3fad0b1594214112722c173d" + integrity sha512-0t3FjoCoQPhmHxPZXm/zI9jAVnWGQERVr7hpRjN1EKyEH8R4YE8bPwA0BmA/9UTcL9iznODr1VDmz+9yXylpNw== dependencies: css "^2.2.4" @@ -17850,14 +17922,6 @@ liftoff@^3.1.0: rechoir "^0.6.2" resolve "^1.1.7" -line-column@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/line-column/-/line-column-1.0.2.tgz#d25af2936b6f4849172b312e4792d1d987bc34a2" - integrity sha1-0lryk2tvSEkXKzEuR5LR2Ye8NKI= - dependencies: - isarray "^1.0.0" - isobject "^2.0.0" - linebreak@^0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/linebreak/-/linebreak-0.3.0.tgz#0526480a62c05bd679f3e9d99830e09c6a7d0ed6" @@ -18447,7 +18511,7 @@ lodash.uniqby@^4.7.0: resolved "https://registry.yarnpkg.com/lodash.uniqby/-/lodash.uniqby-4.7.0.tgz#d99c07a669e9e6d24e1362dfe266c67616af1302" integrity sha1-2ZwHpmnp5tJOE2Lf4mbGdhavEwI= -lodash@4.17.11, lodash@4.17.15, lodash@>4.17.4, lodash@^4.0.0, lodash@^4.0.1, lodash@^4.10.0, lodash@^4.11.1, lodash@^4.13.1, lodash@^4.14.0, lodash@^4.15.0, lodash@^4.16.4, lodash@^4.17.0, lodash@^4.17.10, lodash@^4.17.11, lodash@^4.17.12, lodash@^4.17.13, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.2, 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.17.10, lodash@~4.17.15, lodash@~4.17.5: +lodash@4.17.11, lodash@4.17.15, lodash@>4.17.4, lodash@^4.0.0, lodash@^4.0.1, lodash@^4.10.0, lodash@^4.11.1, lodash@^4.13.1, lodash@^4.14.0, lodash@^4.15.0, lodash@^4.17.0, lodash@^4.17.10, lodash@^4.17.11, lodash@^4.17.12, lodash@^4.17.13, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.2, 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.17.10, lodash@~4.17.15, lodash@~4.17.5: version "4.17.15" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.15.tgz#b447f6670a0455bbfeedd11392eff330ea097548" integrity sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A== @@ -18800,6 +18864,13 @@ mapbox-gl@1.3.1: tinyqueue "^2.0.0" vt-pbf "^3.1.1" +marge@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/marge/-/marge-1.0.1.tgz#52d6026911e62e1dd1cf60a07313dde285a8370c" + integrity sha1-UtYCaRHmLh3Rz2CgcxPd4oWoNww= + dependencies: + yargs "^3.15.0" + markdown-escapes@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/markdown-escapes/-/markdown-escapes-1.0.1.tgz#1994df2d3af4811de59a6714934c2b2292734518" @@ -19460,15 +19531,7 @@ mocha-junit-reporter@^1.23.1: strip-ansi "^4.0.0" xml "^1.0.0" -mocha-multi-reporters@^1.1.7: - version "1.1.7" - resolved "https://registry.yarnpkg.com/mocha-multi-reporters/-/mocha-multi-reporters-1.1.7.tgz#cc7f3f4d32f478520941d852abb64d9988587d82" - integrity sha1-zH8/TTL0eFIJQdhSq7ZNmYhYfYI= - dependencies: - debug "^3.1.0" - lodash "^4.16.4" - -mocha@6.2.1, mocha@^6.2.0: +mocha@^6.2.0: version "6.2.1" resolved "https://registry.yarnpkg.com/mocha/-/mocha-6.2.1.tgz#da941c99437da9bac412097859ff99543969f94c" integrity sha512-VCcWkLHwk79NYQc8cxhkmI8IigTIhsCwZ6RTxQsqK6go4UvEhzJkYuHm8B2YtlSxcYq2fY+ucr4JBwoD6ci80A== @@ -19497,6 +19560,35 @@ mocha@6.2.1, mocha@^6.2.0: yargs-parser "13.1.1" yargs-unparser "1.6.0" +mocha@^6.2.2: + version "6.2.2" + resolved "https://registry.yarnpkg.com/mocha/-/mocha-6.2.2.tgz#5d8987e28940caf8957a7d7664b910dc5b2fea20" + integrity sha512-FgDS9Re79yU1xz5d+C4rv1G7QagNGHZ+iXF81hO8zY35YZZcLEsJVfFolfsqKFWunATEvNzMK0r/CwWd/szO9A== + dependencies: + ansi-colors "3.2.3" + browser-stdout "1.3.1" + debug "3.2.6" + diff "3.5.0" + escape-string-regexp "1.0.5" + find-up "3.0.0" + glob "7.1.3" + growl "1.10.5" + he "1.2.0" + js-yaml "3.13.1" + log-symbols "2.2.0" + minimatch "3.0.4" + mkdirp "0.5.1" + ms "2.1.1" + node-environment-flags "1.0.5" + object.assign "4.1.0" + strip-json-comments "2.0.1" + supports-color "6.0.0" + which "1.3.1" + wide-align "1.1.3" + yargs "13.3.0" + yargs-parser "13.1.1" + yargs-unparser "1.6.0" + mochawesome-merge@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/mochawesome-merge/-/mochawesome-merge-2.0.1.tgz#c690433acc78fd769effe4db1a107508351e2dc5" @@ -19720,7 +19812,7 @@ mute-stream@0.0.8: resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.8.tgz#1630c42b2251ff81e2a283de96a5497ea92e5e0d" integrity sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA== -mz@^2.6.0, mz@^2.7.0: +mz@^2.6.0: version "2.7.0" resolved "https://registry.yarnpkg.com/mz/-/mz-2.7.0.tgz#95008057a56cafadc2bc63dde7f9ff6955948e32" integrity sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q== @@ -20458,10 +20550,10 @@ object-hash@^1.1.8, object-hash@^1.3.1: resolved "https://registry.yarnpkg.com/object-hash/-/object-hash-1.3.1.tgz#fde452098a951cb145f039bb7d455449ddc126df" integrity sha512-OSuu/pU4ENM9kmREg0BdNrUDIl1heYa4mBZacJc+vVWz4GtAwu7jO8s4AIt2aGRUTqxykpWzI3Oqnsm13tTMDA== -object-inspect@^1.6.0, object-inspect@~1.6.0: - version "1.6.0" - resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.6.0.tgz#c70b6cbf72f274aab4c34c0c82f5167bf82cf15b" - integrity sha512-GJzfBZ6DgDAmnuaM3104jR4s1Myxr3Y3zfIyN4z3UdqN69oSRacNK8UhnobDdC+7J2AHCjGwxQubNJfE70SXXQ== +object-inspect@^1.6.0: + version "1.7.0" + resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.7.0.tgz#f4f6bd181ad77f006b5ece60bd0b6f398ff74a67" + integrity sha512-a7pEHdh1xKIAgTySUGgLMx/xwDZskN1Ud6egYYN3EdRW4ZMPNEDUTF+hwy2LUC+Bl+SyLXANnwz/jyh/qutKUw== object-inspect@~0.4.0: version "0.4.0" @@ -20473,21 +20565,21 @@ object-inspect@~1.4.0: resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.4.1.tgz#37ffb10e71adaf3748d05f713b4c9452f402cbc4" integrity sha512-wqdhLpfCUbEsoEwl3FXwGyv8ief1k/1aUdIPCqVnupM6e8l63BEJdiF/0swtn04/8p05tG/T0FrpTlfwvljOdw== +object-inspect@~1.6.0: + version "1.6.0" + resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.6.0.tgz#c70b6cbf72f274aab4c34c0c82f5167bf82cf15b" + integrity sha512-GJzfBZ6DgDAmnuaM3104jR4s1Myxr3Y3zfIyN4z3UdqN69oSRacNK8UhnobDdC+7J2AHCjGwxQubNJfE70SXXQ== + object-is@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/object-is/-/object-is-1.0.1.tgz#0aa60ec9989a0b3ed795cf4d06f62cf1ad6539b6" integrity sha1-CqYOyZiaCz7Xlc9NBvYs8a1lObY= -object-keys@^1.0.11, object-keys@^1.0.12, object-keys@^1.0.9: +object-keys@^1.0.11, object-keys@^1.0.12, object-keys@^1.0.6, object-keys@^1.0.9, object-keys@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.1.tgz#1c47f272df277f3b1daf061677d9c82e2322c60e" integrity sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA== -object-keys@^1.0.6: - version "1.0.11" - resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.0.11.tgz#c54601778ad560f1142ce0e01bcca8b56d13426d" - integrity sha1-xUYBd4rVYPEULODgG8yotW0TQm0= - object-keys@~0.4.0: version "0.4.0" resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-0.4.0.tgz#28a6aae7428dd2c3a92f3d95f21335dd204e0336" @@ -20552,15 +20644,15 @@ object.fromentries@^1.0.0: function-bind "^1.1.1" has "^1.0.1" -object.fromentries@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/object.fromentries/-/object.fromentries-2.0.0.tgz#49a543d92151f8277b3ac9600f1e930b189d30ab" - integrity sha512-9iLiI6H083uiqUuvzyY6qrlmc/Gz8hLQFOcb/Ri/0xXFkSNS3ctV+CbE6yM2+AnkYfOB3dGjdzC0wrMLIhQICA== +object.fromentries@^2.0.0, object.fromentries@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/object.fromentries/-/object.fromentries-2.0.1.tgz#050f077855c7af8ae6649f45c80b16ee2d31e704" + integrity sha512-PUQv8Hbg3j2QX0IQYv3iAGCbGcu4yY4KQ92/dhA4sFSixBmSmp13UpDLs6jGK8rBtbmhNNIK99LD2k293jpiGA== dependencies: - define-properties "^1.1.2" - es-abstract "^1.11.0" + define-properties "^1.1.3" + es-abstract "^1.15.0" function-bind "^1.1.1" - has "^1.0.1" + has "^1.0.3" object.getownpropertydescriptors@^2.0.3: version "2.0.3" @@ -20663,7 +20755,7 @@ one-time@0.0.4: onetime@^1.0.0: version "1.1.0" - resolved "http://registry.npmjs.org/onetime/-/onetime-1.1.0.tgz#a1f7838f8314c516f05ecefcbc4ccfe04b4ed789" + resolved "https://registry.npmjs.org/onetime/-/onetime-1.1.0.tgz#a1f7838f8314c516f05ecefcbc4ccfe04b4ed789" integrity sha1-ofeDj4MUxRbwXs78vEzP4EtO14k= onetime@^2.0.0: @@ -21207,11 +21299,6 @@ parse-git-config@^1.1.1: git-config-path "^1.0.1" ini "^1.3.4" -parse-gitignore@1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/parse-gitignore/-/parse-gitignore-1.0.1.tgz#8b9dc57f17b810d495c5dfa62eb07caffe7758c7" - integrity sha512-UGyowyjtx26n65kdAMWhm6/3uy5uSrpcuH7tt+QEVudiBoVS+eqHxD5kbi9oWVRwj7sCzXqwuM+rUGw7earl6A== - parse-headers@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/parse-headers/-/parse-headers-2.0.1.tgz#6ae83a7aa25a9d9b700acc28698cd1f1ed7e9536" @@ -21904,6 +21991,11 @@ postcss-value-parser@^4.0.0: resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-4.0.0.tgz#99a983d365f7b2ad8d0f9b8c3094926eab4b936d" integrity sha512-ESPktioptiSUchCKgggAkzdmkgzKfmp0EU8jXH+5kbIUB+unr0Y4CY9SRMvibuvYUBjNh1ACLbxqYNpdTQOteQ== +postcss-value-parser@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-4.0.2.tgz#482282c09a42706d1fc9a069b73f44ec08391dc9" + integrity sha512-LmeoohTpp/K4UiyQCwuGWlONxXamGzCMtFxLq4W1nZVGIQLYvMCJx3yAF9qyyuFpflABI9yVdtJAqbihOsCsJQ== + postcss-values-parser@^1.5.0: version "1.5.0" resolved "https://registry.yarnpkg.com/postcss-values-parser/-/postcss-values-parser-1.5.0.tgz#5d9fa63e2bcb0179ce48f3235303765eb89f3047" @@ -22135,7 +22227,7 @@ prop-types@15.6.1: loose-envify "^1.3.1" object-assign "^4.1.1" -prop-types@15.7.2, prop-types@15.x, prop-types@^15.5.10, prop-types@^15.5.4, prop-types@^15.5.6, prop-types@^15.5.7, prop-types@^15.5.8, prop-types@^15.6.0, prop-types@^15.6.1, prop-types@^15.6.2, prop-types@^15.7.2: +prop-types@15.7.2, prop-types@15.x, prop-types@^15.5.10, prop-types@^15.5.6, prop-types@^15.5.7, prop-types@^15.5.8, prop-types@^15.6.0, prop-types@^15.6.1, prop-types@^15.6.2, prop-types@^15.7.2: version "15.7.2" resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.7.2.tgz#52c41e75b8c87e72b9d9360e0206b99dcbffa6c5" integrity sha512-8QQikdH7//R2vurIJSutZ1smHYTcLpRWEOlHnzcWHmBYrOGUysKwSsrC89BCiFj3CbrfJ/nXFdJepOVrY1GCHQ== @@ -22700,6 +22792,17 @@ react-ace@^5.9.0: lodash.isequal "^4.1.1" prop-types "^15.5.8" +react-ace@^7.0.5: + version "7.0.5" + resolved "https://registry.yarnpkg.com/react-ace/-/react-ace-7.0.5.tgz#798299fd52ddf3a3dcc92afc5865538463544f01" + integrity sha512-3iI+Rg2bZXCn9K984ll2OF4u9SGcJH96Q1KsUgs9v4M2WePS4YeEHfW2nrxuqJrAkE5kZbxaCE79k6kqK0YBjg== + dependencies: + brace "^0.11.1" + diff-match-patch "^1.0.4" + lodash.get "^4.4.2" + lodash.isequal "^4.5.0" + prop-types "^15.7.2" + react-addons-create-fragment@^15.6.2: version "15.6.2" resolved "https://registry.yarnpkg.com/react-addons-create-fragment/-/react-addons-create-fragment-15.6.2.tgz#a394de7c2c7becd6b5475ba1b97ac472ce7c74f8" @@ -23425,6 +23528,18 @@ react-virtualized@^9.18.5: prop-types "^15.6.0" react-lifecycles-compat "^3.0.4" +react-virtualized@^9.21.2: + version "9.21.2" + resolved "https://registry.yarnpkg.com/react-virtualized/-/react-virtualized-9.21.2.tgz#02e6df65c1e020c8dbf574ec4ce971652afca84e" + integrity sha512-oX7I7KYiUM7lVXQzmhtF4Xg/4UA5duSA+/ZcAvdWlTLFCoFYq1SbauJT5gZK9cZS/wdYR6TPGpX/dqzvTqQeBA== + dependencies: + babel-runtime "^6.26.0" + clsx "^1.0.1" + dom-helpers "^5.0.0" + loose-envify "^1.3.0" + prop-types "^15.6.0" + react-lifecycles-compat "^3.0.4" + react-vis@^1.8.1: version "1.8.2" resolved "https://registry.yarnpkg.com/react-vis/-/react-vis-1.8.2.tgz#0e0aebc427e50856a01b666569ffad0411ef050f" @@ -24767,6 +24882,11 @@ safe-buffer@5.1.2, safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.1, s resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== +safe-buffer@~5.2.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.0.tgz#b74daec49b1148f88c64b68d49b1e815c1f2f519" + integrity sha512-fZEwUGbVl7kouZs1jCdMLdt95hdIv0ZeHg6L7qPeciMZhZ+/gdesW4wgTARkrFWEpspjEATAzUGPG8N2jJiwbg== + safe-json-parse@~1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/safe-json-parse/-/safe-json-parse-1.0.1.tgz#3e76723e38dfdda13c9b1d29a1e07ffee4b30b57" @@ -26166,16 +26286,7 @@ string-width@^1.0.1, string-width@^1.0.2: is-fullwidth-code-point "^2.0.0" strip-ansi "^4.0.0" -string-width@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-3.0.0.tgz#5a1690a57cc78211fffd9bf24bbe24d090604eb1" - integrity sha512-rr8CUxBbvOZDUvc5lNIJ+OC1nPVpz+Siw9VBtUjB9b6jZehZLFt0JMCZzShFHIsI8cbhm0EsNIfWJMFV3cu3Ew== - dependencies: - emoji-regex "^7.0.1" - is-fullwidth-code-point "^2.0.0" - strip-ansi "^5.0.0" - -string-width@^3.1.0: +string-width@^3.0.0, string-width@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/string-width/-/string-width-3.1.0.tgz#22767be21b62af1081574306f69ac51b62203961" integrity sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w== @@ -26185,21 +26296,21 @@ string-width@^3.1.0: strip-ansi "^5.1.0" string-width@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.1.0.tgz#ba846d1daa97c3c596155308063e075ed1c99aff" - integrity sha512-NrX+1dVVh+6Y9dnQ19pR0pP4FiEIlUvdTGn8pw6CKTNq5sgib2nIhmUNT5TAmhWmvKr3WcxBcP3E8nWezuipuQ== + version "4.2.0" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.0.tgz#952182c46cc7b2c313d1596e623992bd163b72b5" + integrity sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg== dependencies: emoji-regex "^8.0.0" is-fullwidth-code-point "^3.0.0" - strip-ansi "^5.2.0" + strip-ansi "^6.0.0" string.prototype.matchall@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/string.prototype.matchall/-/string.prototype.matchall-3.0.0.tgz#66f4d8dd5c6c6cea4dffb55ec5f3184a8dd0dd59" - integrity sha512-/g0YW/cEfXASRHAaLR7VZbTUlxgP14fmCsfSRFG2gvlG2S1q9rBpjYnEy/EIIzY+bjzs2nTfAHJYXmQ+zTnXSQ== + version "3.0.2" + resolved "https://registry.yarnpkg.com/string.prototype.matchall/-/string.prototype.matchall-3.0.2.tgz#c1fdb23f90058e929a69cfa2e8b12300daefe030" + integrity sha512-hsRe42jQ8+OJej2GVjhnSVodQ3NQgHV0FDD6dW7ZTM22J4uIbuYiAADCCc1tfyN7ocEl/KUUbudM36E2tZcF8w== dependencies: - define-properties "^1.1.2" - es-abstract "^1.12.0" + define-properties "^1.1.3" + es-abstract "^1.14.2" function-bind "^1.1.1" has-symbols "^1.0.0" regexp.prototype.flags "^1.2.0" @@ -26222,7 +26333,16 @@ string.prototype.padstart@^3.0.0: es-abstract "^1.4.3" function-bind "^1.0.2" -string.prototype.trim@^1.1.2, string.prototype.trim@~1.1.2: +string.prototype.trim@^1.1.2: + version "1.2.0" + resolved "https://registry.yarnpkg.com/string.prototype.trim/-/string.prototype.trim-1.2.0.tgz#75a729b10cfc1be439543dae442129459ce61e3d" + integrity sha512-9EIjYD/WdlvLpn987+ctkLf0FfvBefOCuiEr2henD8X+7jfwPnyvTdmW8OJhj5p+M0/96mBdynLWkxUr+rHlpg== + dependencies: + define-properties "^1.1.3" + es-abstract "^1.13.0" + function-bind "^1.1.1" + +string.prototype.trim@~1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/string.prototype.trim/-/string.prototype.trim-1.1.2.tgz#d04de2c89e137f4d7d206f086b5ed2fae6be8cea" integrity sha1-0E3iyJ4Tf019IG8Ia17S+ua+jOo= @@ -26231,24 +26351,33 @@ string.prototype.trim@^1.1.2, string.prototype.trim@~1.1.2: es-abstract "^1.5.0" function-bind "^1.0.2" +string.prototype.trimleft@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/string.prototype.trimleft/-/string.prototype.trimleft-2.1.0.tgz#6cc47f0d7eb8d62b0f3701611715a3954591d634" + integrity sha512-FJ6b7EgdKxxbDxc79cOlok6Afd++TTs5szo+zJTUyow3ycrRfJVE2pq3vcN53XexvKZu/DJMDfeI/qMiZTrjTw== + dependencies: + define-properties "^1.1.3" + function-bind "^1.1.1" + +string.prototype.trimright@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/string.prototype.trimright/-/string.prototype.trimright-2.1.0.tgz#669d164be9df9b6f7559fa8e89945b168a5a6c58" + integrity sha512-fXZTSV55dNBwv16uw+hh5jkghxSnc5oHq+5K/gXgizHwAvMetdAJlHqqoFC1FSDVPYWLkAKl2cxpUT41sV7nSg== + dependencies: + define-properties "^1.1.3" + function-bind "^1.1.1" + string_decoder@0.10, string_decoder@~0.10.x: version "0.10.31" resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-0.10.31.tgz#62e203bc41766c6c28c9fc84301dab1c5310fa94" integrity sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ= -string_decoder@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.1.0.tgz#384f322ee8a848e500effde99901bba849c5d403" - integrity sha512-8zQpRF6juocE69ae7CSPmYEGJe4VCXwP6S6dxUWI7i53Gwv54/ec41fiUA+X7BPGGv7fRSQJjBQVa0gomGaOgg== - dependencies: - safe-buffer "~5.1.0" - -string_decoder@^1.1.1: - version "1.2.0" - resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.2.0.tgz#fe86e738b19544afe70469243b2a1ee9240eae8d" - integrity sha512-6YqyX6ZWEYguAxgZzHGL7SsCeGx3V2TtOTqZz1xSTSWnqsbWwbptafNyvf/ACquZUXV3DANr5BDIwNYe1mN42w== +string_decoder@^1.0.0, string_decoder@^1.1.1: + version "1.3.0" + resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.3.0.tgz#42f114594a46cf1a8e30b0a84f56c78c3edac21e" + integrity sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA== dependencies: - safe-buffer "~5.1.0" + safe-buffer "~5.2.0" string_decoder@~1.1.1: version "1.1.1" @@ -26280,7 +26409,14 @@ stringstream@~0.0.4, stringstream@~0.0.5: resolved "https://registry.yarnpkg.com/stringstream/-/stringstream-0.0.6.tgz#7880225b0d4ad10e30927d167a1d6f2fd3b33a72" integrity sha512-87GEBAkegbBcweToUrdzf3eLhWNg06FJTebl4BVJz/JgWy8CvEr9dRtX5qWphiynMSQlxxi+QqN0z5T32SLlhA== -strip-ansi@*, strip-ansi@5.2.0, strip-ansi@^5.1.0, strip-ansi@^5.2.0: +strip-ansi@*, strip-ansi@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.0.tgz#0b1571dd7669ccd4f3e06e14ef1eed26225ae532" + integrity sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w== + dependencies: + ansi-regex "^5.0.0" + +strip-ansi@5.2.0, strip-ansi@^5.0.0, strip-ansi@^5.1.0, strip-ansi@^5.2.0: version "5.2.0" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-5.2.0.tgz#8c9a536feb6afc962bdfa5b104a5091c1ad9c0ae" integrity sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA== @@ -26308,13 +26444,6 @@ strip-ansi@^4.0.0: dependencies: ansi-regex "^3.0.0" -strip-ansi@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-5.0.0.tgz#f78f68b5d0866c20b2c9b8c61b5298508dc8756f" - integrity sha512-Uu7gQyZI7J7gn5qLn1Np3G9vcYGTVqB+lFTytnDJv83dd8T22aGH451P3jueT2/QemInJDfxHB5Tde5OzgG1Ow== - dependencies: - ansi-regex "^4.0.0" - strip-ansi@~0.1.0: version "0.1.1" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-0.1.1.tgz#39e8a98d044d150660abe4a6808acf70bb7bc991" @@ -26420,31 +26549,27 @@ style-loader@0.23.1, style-loader@^0.23.1: loader-utils "^1.1.0" schema-utils "^1.0.0" -styled-components@3.4.10: - version "3.4.10" - resolved "https://registry.yarnpkg.com/styled-components/-/styled-components-3.4.10.tgz#9a654c50ea2b516c36ade57ddcfa296bf85c96e1" - integrity sha512-TA8ip8LoILgmSAFd3r326pKtXytUUGu5YWuqZcOQVwVVwB6XqUMn4MHW2IuYJ/HAD81jLrdQed8YWfLSG1LX4Q== +styled-components@beta: + version "5.0.0-rc.2" + resolved "https://registry.yarnpkg.com/styled-components/-/styled-components-5.0.0-rc.2.tgz#6c44570ff202f47a1a688d6f1249bc079b10a958" + integrity sha512-dRMU2Ka12F2qbJK6XMDVy1H6KOXpbf7nAKReV0uIikCdW/zbO2K3C+XUCL0EqTVeevugFBJUACZUoTc7ShKsTg== dependencies: - buffer "^5.0.3" - css-to-react-native "^2.0.3" - fbjs "^0.8.16" - hoist-non-react-statics "^2.5.0" - prop-types "^15.5.4" - react-is "^16.3.1" - stylis "^3.5.0" + "@babel/helper-module-imports" "^7.0.0" + "@babel/traverse" "^7.4.5" + "@emotion/is-prop-valid" "^0.8.3" + "@emotion/stylis" "^0.8.4" + "@emotion/unitless" "^0.7.4" + babel-plugin-styled-components ">= 1" + css-to-react-native "^3.0.0" + shallowequal "^1.1.0" stylis-rule-sheet "^0.0.10" - supports-color "^3.2.3" + supports-color "^5.5.0" stylis-rule-sheet@^0.0.10: version "0.0.10" resolved "https://registry.yarnpkg.com/stylis-rule-sheet/-/stylis-rule-sheet-0.0.10.tgz#44e64a2b076643f4b52e5ff71efc04d8c3c4a430" integrity sha512-nTbZoaqoBnmK+ptANthb10ZRZOGC+EmTLLUxeYIuHNkEKcmKgXX1XWKkUBT2Ac4es3NybooPe0SmvKdhKJZAuw== -stylis@^3.5.0: - version "3.5.1" - resolved "https://registry.yarnpkg.com/stylis/-/stylis-3.5.1.tgz#fd341d59f57f9aeb412bc14c9d8a8670b438e03b" - integrity sha512-yM4PyeHuwhIOUHNJxi1/Mbq8kVLv4AkyE7IYLP/LK0lIFcr3tRa2H1iZlBYKIxOlf+/jruBTe8DdKSyQX9w4OA== - stylus-lookup@^3.0.1: version "3.0.2" resolved "https://registry.yarnpkg.com/stylus-lookup/-/stylus-lookup-3.0.2.tgz#c9eca3ff799691020f30b382260a67355fefdddd" @@ -26553,7 +26678,7 @@ supports-color@^2.0.0: resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7" integrity sha1-U10EXOa2Nj+kARcIRimZXp3zJMc= -supports-color@^3.1.0, supports-color@^3.1.2, supports-color@^3.2.3: +supports-color@^3.1.0, supports-color@^3.1.2: version "3.2.3" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-3.2.3.tgz#65ac0504b3954171d8a64946b2ae3cbb8a5f54f6" integrity sha1-ZawFBLOVQXHYpklGsq48u4pfVPY= @@ -29825,6 +29950,11 @@ window-size@0.1.0: resolved "https://registry.yarnpkg.com/window-size/-/window-size-0.1.0.tgz#5438cd2ea93b202efa3a19fe8887aee7c94f9c9d" integrity sha1-VDjNLqk7IC76Ohn+iIeu58lPnJ0= +window-size@^0.1.4: + version "0.1.4" + resolved "https://registry.yarnpkg.com/window-size/-/window-size-0.1.4.tgz#f8e1aa1ee5a53ec5bf151ffa09742a6ad7697876" + integrity sha1-+OGqHuWlPsW/FR/6CXQqatdpeHY= + window-size@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/window-size/-/window-size-0.2.0.tgz#b4315bb4214a3d7058ebeee892e13fa24d98b075" @@ -30225,7 +30355,7 @@ xxhashjs@^0.2.1: dependencies: cuint "^0.2.2" -y18n@^3.2.1: +y18n@^3.2.0, y18n@^3.2.1: version "3.2.1" resolved "https://registry.yarnpkg.com/y18n/-/y18n-3.2.1.tgz#6d15fba884c08679c0d77e88e7759e811e07fa41" integrity sha1-bRX7qITAhnnA136I53WegR4H+kE= @@ -30423,6 +30553,19 @@ yargs@^14.2.0: y18n "^4.0.0" yargs-parser "^15.0.0" +yargs@^3.15.0: + version "3.32.0" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-3.32.0.tgz#03088e9ebf9e756b69751611d2a5ef591482c995" + integrity sha1-AwiOnr+edWtpdRYR0qXvWRSCyZU= + dependencies: + camelcase "^2.0.1" + cliui "^3.0.3" + decamelize "^1.1.1" + os-locale "^1.4.0" + string-width "^1.0.1" + window-size "^0.1.4" + y18n "^3.2.0" + yargs@^7.0.0, yargs@^7.1.0: version "7.1.0" resolved "https://registry.yarnpkg.com/yargs/-/yargs-7.1.0.tgz#6ba318eb16961727f5d284f8ea003e8d6154d0c8"