Skip to content

Commit 080063a

Browse files
Merge branch 'master' into alerts/index-threshold-non-array-index-param
2 parents 9f95ce7 + 4bc5f01 commit 080063a

File tree

1,488 files changed

+51591
-14776
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

1,488 files changed

+51591
-14776
lines changed

.ci/teamcity/default/build_plugins.sh

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ node scripts/build_kibana_platform_plugins \
1414
--scan-dir "$XPACK_DIR/test/plugin_api_integration/plugins" \
1515
--scan-dir "$XPACK_DIR/test/plugin_api_perf/plugins" \
1616
--scan-dir "$XPACK_DIR/test/licensing_plugin/plugins" \
17+
--scan-dir "$XPACK_DIR/test/usage_collection/plugins" \
1718
--verbose
1819
tc_end_block "Build Platform Plugins"
1920

.ci/teamcity/setup_env.sh

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ else
4848
fi
4949

5050
tc_set_env FLEET_PACKAGE_REGISTRY_PORT 6104 # Any unused port is fine, used by ingest manager tests
51+
tc_set_env TEST_CORS_SERVER_PORT 6105 # Any unused port is fine, used by ingest manager tests
5152

5253
if [[ "$(which google-chrome-stable)" || "$(which google-chrome)" ]]; then
5354
echo "Chrome detected, setting DETECT_CHROMEDRIVER_VERSION=true"

.github/PULL_REQUEST_TEMPLATE.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ Delete any items that are not applicable to this PR.
1111
- [ ] [Unit or functional tests](https://www.elastic.co/guide/en/kibana/master/development-tests.html) were updated or added to match the most common scenarios
1212
- [ ] Any UI touched in this PR is usable by keyboard only (learn more about [keyboard accessibility](https://webaim.org/techniques/keyboard/))
1313
- [ ] Any UI touched in this PR does not create any new axe failures (run axe in browser: [FF](https://addons.mozilla.org/en-US/firefox/addon/axe-devtools/), [Chrome](https://chrome.google.com/webstore/detail/axe-web-accessibility-tes/lhdoppojpmngadmnindnejefpokejbdd?hl=en-US))
14-
- [ ] If a plugin configuration key changed, check if it needs to be whitelisted in the [cloud](https://github.com/elastic/cloud) and added to the [docker list](https://github.com/elastic/kibana/blob/c29adfef29e921cc447d2a5ed06ac2047ceab552/src/dev/build/tasks/os_packages/docker_generator/resources/bin/kibana-docker)
14+
- [ ] If a plugin configuration key changed, check if it needs to be allowlisted in the [cloud](https://github.com/elastic/cloud) and added to the [docker list](https://github.com/elastic/kibana/blob/c29adfef29e921cc447d2a5ed06ac2047ceab552/src/dev/build/tasks/os_packages/docker_generator/resources/bin/kibana-docker)
1515
- [ ] This renders correctly on smaller devices using a responsive layout. (You can test this [in your browser](https://www.browserstack.com/guide/responsive-testing-on-local-server))
1616
- [ ] This was checked for [cross-browser compatibility](https://www.elastic.co/support/matrix#matrix_browsers)
1717

.teamcity/src/Common.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import jetbrains.buildServer.configs.kotlin.v2019_2.DslContext
44
const val ENABLE_REPORTING = false
55

66
// If set to false, jobs with triggers (scheduled, on commit, etc) will be paused
7-
const val ENABLE_TRIGGERS = false
7+
const val ENABLE_TRIGGERS = true
88

99
fun getProjectBranch(): String {
1010
return DslContext.projectName

.teamcity/src/builds/PullRequestCi.kt

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -63,13 +63,15 @@ object PullRequestCi : BuildType({
6363
}
6464

6565
features {
66-
commitStatusPublisher {
67-
enabled = isReportingEnabled()
68-
vcsRootExtId = "${Kibana.id}"
69-
publisher = github {
70-
githubUrl = "https://api.github.com"
71-
authType = personalToken {
72-
token = "credentialsJSON:07d22002-12de-4627-91c3-672bdb23b55b"
66+
if(isReportingEnabled()) {
67+
commitStatusPublisher {
68+
enabled = true
69+
vcsRootExtId = "${Kibana.id}"
70+
publisher = github {
71+
githubUrl = "https://api.github.com"
72+
authType = personalToken {
73+
token = "credentialsJSON:07d22002-12de-4627-91c3-672bdb23b55b"
74+
}
7375
}
7476
}
7577
}

.teamcity/src/builds/default/DefaultCiGroups.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ package builds.default
33
import dependsOn
44
import jetbrains.buildServer.configs.kotlin.v2019_2.BuildType
55

6-
const val DEFAULT_CI_GROUP_COUNT = 11
6+
const val DEFAULT_CI_GROUP_COUNT = 13
77
val defaultCiGroups = (1..DEFAULT_CI_GROUP_COUNT).map { DefaultCiGroup(it) }
88

99
object DefaultCiGroups : BuildType({
347 KB
Loading
198 KB
Loading
Lines changed: 305 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,305 @@
1+
---
2+
id: kibPlatformIntro
3+
slug: /kibana-dev-docs/platform-intro
4+
title: Plugins and the Kibana platform
5+
summary: An introduction to the Kibana platform and how to use it to build a plugin.
6+
date: 2021-01-06
7+
tags: ['kibana','onboarding', 'dev', 'architecture']
8+
---
9+
10+
From an end user perspective, Kibana is a tool for interacting with Elasticsearch, providing an easy way
11+
to visualize and analyze data.
12+
13+
From a developer perspective, Kibana is a platform that provides a set of tools to build not only the UI you see in Kibana today, but
14+
a wide variety of applications that can be used to explore, visualize, and act upon data in Elasticsearch. The platform provides developers the ability to build applications, or inject extra functionality into
15+
already existing applications. Did you know that almost everything you see in the
16+
Kibana UI is built inside a plugin? If you removed all plugins from Kibana, you'd be left with an empty navigation menu, and a set of
17+
developer tools. The Kibana platform is a blank canvas, just waiting for a developer to come along and create something!
18+
19+
![Kibana personas](assets/kibana_platform_plugin_end_user.png)
20+
21+
## Plugins vs The Platform
22+
23+
The core platform provides the most basic and fundamental tools neccessary for building a plugin, like creating saved objects,
24+
routing, application registration, and notifications. The Core platform is not a plugin itself, although
25+
there are some plugins that provide platform functionality. For example, the
26+
<DocLink id="kibDataPlugin" text="data plugin"/> provides basic utilities to search, query, and filter data in Elasticsearch.
27+
This code is not part of Core, but is still fundamental for building a plugin,
28+
and we strongly encourage using this service over querying Elasticsearch directly.
29+
30+
<DocCallOut title="Three kinds of public services">
31+
We currently have three kinds of public services:
32+
33+
- platform services provided by `core`
34+
- platform services provided by plugins, that can, and should, be used by every plugin (e.g. <DocLink id="kibDataPlugin" text="data"/>) .
35+
- shared services provided by plugins, that are only relevant for only a few, specific plugins (e.g. "presentation utils").
36+
37+
Two common questions we encounter are:
38+
39+
1. Which services are platform services?
40+
2. What is the difference between platform code supplied by core, and platform code supplied by plugins?
41+
42+
We don't have great answers to those questions today. Currently, the best answers we have are:
43+
44+
1. Platform plugins are _usually_ plugins that are managed by the Platform Group, but we are starting to see some exceptions.
45+
2. `core` code contains the most fundamental and stable services needed for plugin development. Everything else goes in a plugin.
46+
47+
We will continue to focus on adding clarity around these types of services and what developers can expect from each.
48+
49+
</DocCallOut>
50+
51+
<DocAccordion buttonContent="A bit of history">
52+
<DocCallOut title="A bit of history">
53+
When the Kibana platform and plugin infrastructure was built, we thought of two types of code: core services, and other plugin services. We planned to keep the most stable and fundamental
54+
code needed to build plugins inside core.
55+
56+
In reality, we ended up with many platform-like services living outside of core, with no (short term) intention of moving them. We highly encourage plugin developers to use
57+
them, so we consider them part of platform services.
58+
59+
When we built our platform system, we also thought we'd end up with only a handful of large plugins outside core. Users could turn certain plugins off, to minimize the code
60+
footprint and speed up Kibana.
61+
62+
In reality, our plugin model ended up being used like micro-services. Plugins are the only form of encapsulation we provide developers, and they liked it! However, we ended
63+
up with a ton of small plugins, that developers never intended to be uninstallable, nor tested in this manner. We are considering ways to provide developers the ability to build services
64+
with the encapsulation
65+
they desire, without the need to build a plugin.
66+
67+
Another side effect of having many small plugins is that common code often ends up extracted into another plugin. Use case specific utilities are exported,
68+
that are not meant to be used in a general manner. This makes our definition of "platform code" a bit trickier to define. We'd like to say "The platform is made up of
69+
every publically exposed service", but in today's world, that wouldn't be a very accurate picture.
70+
71+
We recognize the need to better clarify the relationship between core functionality, platform-like plugin functionality, and functionality exposed by other plugins.
72+
It's something we will be working on!
73+
</DocCallOut>
74+
</DocAccordion>
75+
76+
The main difference between core functionality and functionality supplied by plugins, is in how it is accessed. Core is
77+
passed to plugins as the first parameter to their `start` and `setup` lifecycle functions, while plugin supplied functionality is passed as the
78+
second parameter. Plugin dependencies must be declared explicitly inside the `kibana.json` file. Core functionality is always provided. Read the
79+
section on [how plugins interact with eachother and core](#how-plugins-interact-with-each-other-and-core) for more information.
80+
81+
## The anatomy of a plugin
82+
83+
Plugins are defined as classes and present themselves to Kibana through a simple wrapper function. A plugin can have browser-side code, server-side code,
84+
or both. There is no architectural difference between a plugin in the browser and a plugin on the server. In both places, you describe your plugin similarly,
85+
and you interact with Core and other plugins in the same way.
86+
87+
The basic file structure of a Kibana plugin named demo that has both client-side and server-side code would be:
88+
89+
```
90+
plugins/
91+
demo
92+
kibana.json [1]
93+
public
94+
index.ts [2]
95+
plugin.ts [3]
96+
server
97+
index.ts [4]
98+
plugin.ts [5]
99+
```
100+
101+
### [1] kibana.json
102+
103+
`kibana.json` is a static manifest file that is used to identify the plugin and to specify if this plugin has server-side code, browser-side code, or both:
104+
105+
```
106+
{
107+
"id": "demo",
108+
"version": "kibana",
109+
"server": true,
110+
"ui": true
111+
}
112+
```
113+
114+
### [2] public/index.ts
115+
116+
`public/index.ts` is the entry point into the client-side code of this plugin. It must export a function named plugin, which will receive a standard set of
117+
core capabilities as an argument. It should return an instance of its plugin class for Kibana to load.
118+
119+
```
120+
import type { PluginInitializerContext } from 'kibana/server';
121+
import { DemoPlugin } from './plugin';
122+
123+
export function plugin(initializerContext: PluginInitializerContext) {
124+
return new DemoPlugin(initializerContext);
125+
}
126+
```
127+
128+
### [3] public/plugin.ts
129+
130+
`public/plugin.ts` is the client-side plugin definition itself. Technically speaking, it does not need to be a class or even a separate file from the entry
131+
point, but all plugins at Elastic should be consistent in this way.
132+
133+
134+
```ts
135+
import type { Plugin, PluginInitializerContext, CoreSetup, CoreStart } from 'kibana/server';
136+
137+
export class DemoPlugin implements Plugin {
138+
constructor(initializerContext: PluginInitializerContext) {}
139+
140+
public setup(core: CoreSetup) {
141+
// called when plugin is setting up during Kibana's startup sequence
142+
}
143+
144+
public start(core: CoreStart) {
145+
// called after all plugins are set up
146+
}
147+
148+
public stop() {
149+
// called when plugin is torn down during Kibana's shutdown sequence
150+
}
151+
}
152+
```
153+
154+
155+
### [4] server/index.ts
156+
157+
`server/index.ts` is the entry-point into the server-side code of this plugin. It is identical in almost every way to the client-side entry-point:
158+
159+
### [5] server/plugin.ts
160+
161+
`server/plugin.ts` is the server-side plugin definition. The shape of this plugin is the same as it’s client-side counter-part:
162+
163+
```ts
164+
import type { Plugin, PluginInitializerContext, CoreSetup, CoreStart } from 'kibana/server';
165+
166+
export class DemoPlugin implements Plugin {
167+
constructor(initializerContext: PluginInitializerContext) {}
168+
169+
public setup(core: CoreSetup) {
170+
// called when plugin is setting up during Kibana's startup sequence
171+
}
172+
173+
public start(core: CoreStart) {
174+
// called after all plugins are set up
175+
}
176+
177+
public stop() {
178+
// called when plugin is torn down during Kibana's shutdown sequence
179+
}
180+
}
181+
```
182+
183+
Kibana does not impose any technical restrictions on how the the internals of a plugin are architected, though there are certain
184+
considerations related to how plugins integrate with core APIs and APIs exposed by other plugins that may greatly impact how they are built.
185+
186+
## Plugin lifecycles & Core services
187+
188+
The various independent domains that make up core are represented by a series of services. Those services expose public interfaces that are provided to all plugins.
189+
Services expose different features at different parts of their lifecycle. We describe the lifecycle of core services and plugins with specifically-named functions on the service definition.
190+
191+
Kibana has three lifecycles: setup, start, and stop. Each plugin’s setup function is called sequentially while Kibana is setting up on the server or when it is being loaded in the browser. The start functions are called sequentially after setup has been completed for all plugins. The stop functions are called sequentially while Kibana is gracefully shutting down the server or when the browser tab or window is being closed.
192+
193+
The table below explains how each lifecycle relates to the state of Kibana.
194+
195+
| lifecycle | purpose | server | browser |
196+
| ---------- | ------ | ------- | ----- |
197+
| setup | perform "registration" work to setup environment for runtime |configure REST API endpoint, register saved object types, etc. | configure application routes in SPA, register custom UI elements in extension points, etc. |
198+
| start | bootstrap runtime logic | respond to an incoming request, request Elasticsearch server, etc. | start polling Kibana server, update DOM tree in response to user interactions, etc.|
199+
| stop | cleanup runtime | dispose of active handles before the server shutdown. | store session data in the LocalStorage when the user navigates away from Kibana, etc. |
200+
201+
Different service interfaces can and will be passed to setup, start, and stop because certain functionality makes sense in the context of a running plugin while other types
202+
of functionality may have restrictions or may only make sense in the context of a plugin that is stopping.
203+
204+
## How plugin's interact with each other, and Core
205+
206+
The lifecycle-specific contracts exposed by core services are always passed as the first argument to the equivalent lifecycle function in a plugin.
207+
For example, the core http service exposes a function createRouter to all plugin setup functions. To use this function to register an HTTP route handler,
208+
a plugin just accesses it off of the first argument:
209+
210+
```ts
211+
import type { CoreSetup } from 'kibana/server';
212+
213+
export class DemoPlugin {
214+
public setup(core: CoreSetup) {
215+
const router = core.http.createRouter();
216+
// handler is called when '/path' resource is requested with `GET` method
217+
router.get({ path: '/path', validate: false }, (context, req, res) => res.ok({ content: 'ok' }));
218+
}
219+
}
220+
```
221+
222+
Unlike core, capabilities exposed by plugins are not automatically injected into all plugins.
223+
Instead, if a plugin wishes to use the public interface provided by another plugin, it must first declare that plugin as a
224+
dependency in it’s kibana.json manifest file.
225+
226+
** foobar plugin.ts: **
227+
228+
```
229+
import type { Plugin } from 'kibana/server';
230+
export interface FoobarPluginSetup { [1]
231+
getFoo(): string;
232+
}
233+
234+
export interface FoobarPluginStart { [1]
235+
getBar(): string;
236+
}
237+
238+
export class MyPlugin implements Plugin<FoobarPluginSetup, FoobarPluginStart> {
239+
public setup(): FoobarPluginSetup {
240+
return {
241+
getFoo() {
242+
return 'foo';
243+
},
244+
};
245+
}
246+
247+
public start(): FoobarPluginStart {
248+
return {
249+
getBar() {
250+
return 'bar';
251+
},
252+
};
253+
}
254+
}
255+
```
256+
[1] We highly encourage plugin authors to explicitly declare public interfaces for their plugins.
257+
258+
259+
** demo kibana.json**
260+
261+
```
262+
{
263+
"id": "demo",
264+
"requiredPlugins": ["foobar"],
265+
"server": true,
266+
"ui": true
267+
}
268+
```
269+
270+
With that specified in the plugin manifest, the appropriate interfaces are then available via the second argument of setup and/or start:
271+
272+
```ts
273+
import type { CoreSetup, CoreStart } from 'kibana/server';
274+
import type { FoobarPluginSetup, FoobarPluginStart } from '../../foobar/server';
275+
276+
interface DemoSetupPlugins { [1]
277+
foobar: FoobarPluginSetup;
278+
}
279+
280+
interface DemoStartPlugins {
281+
foobar: FoobarPluginStart;
282+
}
283+
284+
export class DemoPlugin {
285+
public setup(core: CoreSetup, plugins: DemoSetupPlugins) { [2]
286+
const { foobar } = plugins;
287+
foobar.getFoo(); // 'foo'
288+
foobar.getBar(); // throws because getBar does not exist
289+
}
290+
291+
public start(core: CoreStart, plugins: DemoStartPlugins) { [3]
292+
const { foobar } = plugins;
293+
foobar.getFoo(); // throws because getFoo does not exist
294+
foobar.getBar(); // 'bar'
295+
}
296+
297+
public stop() {}
298+
}
299+
```
300+
301+
[1] The interface for plugin’s dependencies must be manually composed. You can do this by importing the appropriate type from the plugin and constructing an interface where the property name is the plugin’s ID.
302+
303+
[2] These manually constructed types should then be used to specify the type of the second argument to the plugin.
304+
305+
[3] Notice that the type for the setup and start lifecycles are different. Plugin lifecycle functions can only access the APIs that are exposed during that lifecycle.

docs/api/saved-objects.asciidoc

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ The following saved objects APIs are available:
1010

1111
* <<saved-objects-api-get, Get object API>> to retrieve a single {kib} saved object by ID
1212

13+
* <<saved-objects-api-resolve, Resolve object API>> to retrieve a single {kib} saved object by ID, using any legacy URL alias if it exists
14+
1315
* <<saved-objects-api-bulk-get, Bulk get objects API>> to retrieve multiple {kib} saved objects by ID
1416

1517
* <<saved-objects-api-find, Find objects API>> to retrieve a paginated set of {kib} saved objects by various conditions
@@ -40,4 +42,5 @@ include::saved-objects/delete.asciidoc[]
4042
include::saved-objects/export.asciidoc[]
4143
include::saved-objects/import.asciidoc[]
4244
include::saved-objects/resolve_import_errors.asciidoc[]
45+
include::saved-objects/resolve.asciidoc[]
4346
include::saved-objects/rotate_encryption_key.asciidoc[]

0 commit comments

Comments
 (0)