Skip to content

Commit

Permalink
[7.x] Add SavedObjectsClient.bulkResolve (#112025) (#112486)
Browse files Browse the repository at this point in the history
* Add SavedObjectsClient.bulkResolve (#112025)

* Fix type error

Co-authored-by: Joe Portner <5295965+jportner@users.noreply.github.com>
  • Loading branch information
kibanamachine and jportner committed Sep 16, 2021
1 parent de32f3c commit b34f986
Show file tree
Hide file tree
Showing 78 changed files with 3,056 additions and 892 deletions.
3 changes: 3 additions & 0 deletions docs/api/saved-objects.asciidoc
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ The following saved objects APIs are available:

* <<saved-objects-api-bulk-get, Bulk get objects API>> to retrieve multiple {kib} saved objects by ID

* <<saved-objects-api-bulk-resolve, Bulk resolve objects API>> to retrieve multiple {kib} saved objects by ID, using any legacy URL aliases if they exist

* <<saved-objects-api-find, Find objects API>> to retrieve a paginated set of {kib} saved objects by various conditions

* <<saved-objects-api-create, Create saved object API>> to create {kib} saved objects
Expand Down Expand Up @@ -45,4 +47,5 @@ include::saved-objects/export.asciidoc[]
include::saved-objects/import.asciidoc[]
include::saved-objects/resolve_import_errors.asciidoc[]
include::saved-objects/resolve.asciidoc[]
include::saved-objects/bulk_resolve.asciidoc[]
include::saved-objects/rotate_encryption_key.asciidoc[]
176 changes: 176 additions & 0 deletions docs/api/saved-objects/bulk_resolve.asciidoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,176 @@
[[saved-objects-api-bulk-resolve]]
=== Bulk resolve objects API
++++
<titleabbrev>Bulk resolve objects</titleabbrev>
++++

experimental[] Retrieve multiple {kib} saved objects by ID, using any legacy URL aliases if they exist.

Under certain circumstances, when Kibana is upgraded, saved object migrations may necessitate regenerating some object IDs to enable new
features. When an object's ID is regenerated, a legacy URL alias is created for that object, preserving its old ID. In such a scenario, that
object can be retrieved via the Bulk Resolve API using either its new ID or its old ID.

[[saved-objects-api-bulk-resolve-request]]
==== Request

`POST <kibana host>:<port>/api/saved_objects/_bulk_resolve`

`POST <kibana host>:<port>/s/<space_id>/api/saved_objects/_bulk_resolve`

[[saved-objects-api-bulk-resolve-path-params]]
==== Path parameters

`space_id`::
(Optional, string) An identifier for the space. If `space_id` is not provided in the URL, the default space is used.

[[saved-objects-api-bulk-resolve-request-body]]
==== Request Body

`type`::
(Required, string) Valid options include `visualization`, `dashboard`, `search`, `index-pattern`, `config`.

`id`::
(Required, string) ID of the retrieved object. The ID includes the {kib} unique identifier or a custom identifier.

[[saved-objects-api-bulk-resolve-response-body]]
==== Response body

`resolved_objects`::
(array) Top-level property containing objects that represent the response for each of the requested objects. The order of the objects in the response is identical to the order of the objects in the request.

Saved objects that {kib} fails to find are replaced with an error object and an "exactMatch" outcome. The rationale behind the outcome is
that "exactMatch" is the default outcome, and the outcome only changes if an alias is found. This behavior is unique to `_bulk_resolve`; the
<<saved-objects-api-resolve,regular `resolve` API>> will return only an HTTP error instead.

[[saved-objects-api-bulk-resolve-body-codes]]
==== Response code

`200`::
Indicates a successful call.

[[saved-objects-api-bulk-resolve-body-example]]
==== Example

Retrieve an index pattern with the `my-pattern` ID, and a dashboard with the `my-dashboard` ID:

[source,sh]
--------------------------------------------------
$ curl -X POST api/saved_objects/_bulk_resolve
[
{
"type": "index-pattern",
"id": "my-pattern"
},
{
"type": "dashboard",
"id": "be3733a0-9efe-11e7-acb3-3dab96693fab"
}
]
--------------------------------------------------
// KIBANA

The API returns the following:

[source,sh]
--------------------------------------------------
{
"resolved_objects": [
{
"saved_object": {
"id": "my-pattern",
"type": "index-pattern",
"version": 1,
"attributes": {
"title": "my-pattern-*"
}
},
"outcome": "exactMatch"
},
{
"saved_object": {
"id": "my-dashboard",
"type": "dashboard",
"error": {
"statusCode": 404,
"message": "Not found"
}
},
"outcome": "exactMatch"
}
]
}
--------------------------------------------------

Only the index pattern exists, the dashboard was not found.

The `outcome` field may be any of the following:

* `"exactMatch"` -- One document exactly matched the given ID, *or* {kib} failed to find this object.
* `"aliasMatch"` -- One document with a legacy URL alias matched the given ID; in this case the `saved_object.id` field is different than the given ID.
* `"conflict"` -- Two documents matched the given ID, one was an exact match and another with a legacy URL alias; in this case the `saved_object` object is the exact match, and the `saved_object.id` field is the same as the given ID.

If the outcome is `"aliasMatch"` or `"conflict"`, the response will also include an `alias_target_id` field. This means that an alias was found for another object, and it describes that other object's ID.

Retrieve a dashboard object in the `testspace` by ID:

[source,sh]
--------------------------------------------------
$ curl -X GET s/testspace/api/saved_objects/resolve/dashboard/7adfa750-4c81-11e8-b3d7-01146121b73d
--------------------------------------------------
// KIBANA

The API returns the following:

[source,sh]
--------------------------------------------------
{
"resolved_objects": [
{
"saved_object": {
"id": "7adfa750-4c81-11e8-b3d7-01146121b73d",
"type": "dashboard",
"updated_at": "2019-07-23T00:11:07.059Z",
"version": "WzQ0LDFd",
"attributes": {
"title": "[Flights] Global Flight Dashboard",
"hits": 0,
"description": "Analyze mock flight data for ES-Air, Logstash Airways, Kibana Airlines and JetBeats",
"panelsJSON": "[ . . . ]",
"optionsJSON": "{\"hidePanelTitles\":false,\"useMargins\":true}",
"version": 1,
"timeRestore": true,
"timeTo": "now",
"timeFrom": "now-24h",
"refreshInterval": {
"display": "15 minutes",
"pause": false,
"section": 2,
"value": 900000
},
"kibanaSavedObjectMeta": {
"searchSourceJSON": "{\"query\":{\"language\":\"kuery\",\"query\":\"\"},\"filter\":[],\"highlightAll\":true,\"version\":true}"
}
},
"references": [
{
"name": "panel_0",
"type": "visualization",
"id": "aeb212e0-4c84-11e8-b3d7-01146121b73d"
},
. . .
{
"name": "panel_18",
"type": "visualization",
"id": "ed78a660-53a0-11e8-acbd-0be0ad9d822b"
}
],
"migrationVersion": {
"dashboard": "7.0.0"
}
},
"outcome": "conflict",
"alias_target_id": "05becb88-e214-439a-a2ac-15fc783b5d01"
}
]
}
--------------------------------------------------
2 changes: 1 addition & 1 deletion docs/developer/advanced/sharing-saved-objects.asciidoc
Original file line number Diff line number Diff line change
Expand Up @@ -412,7 +412,7 @@ deprecate and remove them.
[[sharing-saved-objects-faq-resolve-outcomes]]
==== 5. Why are there three different resolve outcomes?

The `resolve()` function first checks if an object with the given ID exists, and then it checks if an object has an alias with the given ID.
The `resolve()` function checks both if an object with the given ID exists, _and_ if an object has an alias with the given ID.

1. If only the former is true, the outcome is an `'exactMatch'` -- we found the exact object we were looking for.
2. If only the latter is true, the outcome is an `'aliasMatch'` -- we found an alias with this ID, that pointed us to an object with a
Expand Down
2 changes: 2 additions & 0 deletions docs/development/core/public/kibana-plugin-core-public.md
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,8 @@ The plugin integrates with the core system via lifecycle events: `setup`<!-- -->
| [SavedObjectsBatchResponse](./kibana-plugin-core-public.savedobjectsbatchresponse.md) | |
| [SavedObjectsBulkCreateObject](./kibana-plugin-core-public.savedobjectsbulkcreateobject.md) | |
| [SavedObjectsBulkCreateOptions](./kibana-plugin-core-public.savedobjectsbulkcreateoptions.md) | |
| [SavedObjectsBulkResolveObject](./kibana-plugin-core-public.savedobjectsbulkresolveobject.md) | |
| [SavedObjectsBulkResolveResponse](./kibana-plugin-core-public.savedobjectsbulkresolveresponse.md) | |
| [SavedObjectsBulkUpdateObject](./kibana-plugin-core-public.savedobjectsbulkupdateobject.md) | |
| [SavedObjectsBulkUpdateOptions](./kibana-plugin-core-public.savedobjectsbulkupdateoptions.md) | |
| [SavedObjectsCollectMultiNamespaceReferencesResponse](./kibana-plugin-core-public.savedobjectscollectmultinamespacereferencesresponse.md) | The response when object references are collected. |
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->

[Home](./index.md) &gt; [kibana-plugin-core-public](./kibana-plugin-core-public.md) &gt; [SavedObjectsBulkResolveObject](./kibana-plugin-core-public.savedobjectsbulkresolveobject.md) &gt; [id](./kibana-plugin-core-public.savedobjectsbulkresolveobject.id.md)

## SavedObjectsBulkResolveObject.id property

<b>Signature:</b>

```typescript
id: string;
```
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->

[Home](./index.md) &gt; [kibana-plugin-core-public](./kibana-plugin-core-public.md) &gt; [SavedObjectsBulkResolveObject](./kibana-plugin-core-public.savedobjectsbulkresolveobject.md)

## SavedObjectsBulkResolveObject interface


<b>Signature:</b>

```typescript
export interface SavedObjectsBulkResolveObject
```

## Properties

| Property | Type | Description |
| --- | --- | --- |
| [id](./kibana-plugin-core-public.savedobjectsbulkresolveobject.id.md) | <code>string</code> | |
| [type](./kibana-plugin-core-public.savedobjectsbulkresolveobject.type.md) | <code>string</code> | |

Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->

[Home](./index.md) &gt; [kibana-plugin-core-public](./kibana-plugin-core-public.md) &gt; [SavedObjectsBulkResolveObject](./kibana-plugin-core-public.savedobjectsbulkresolveobject.md) &gt; [type](./kibana-plugin-core-public.savedobjectsbulkresolveobject.type.md)

## SavedObjectsBulkResolveObject.type property

<b>Signature:</b>

```typescript
type: string;
```
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->

[Home](./index.md) &gt; [kibana-plugin-core-public](./kibana-plugin-core-public.md) &gt; [SavedObjectsBulkResolveResponse](./kibana-plugin-core-public.savedobjectsbulkresolveresponse.md)

## SavedObjectsBulkResolveResponse interface


<b>Signature:</b>

```typescript
export interface SavedObjectsBulkResolveResponse<T = unknown>
```

## Properties

| Property | Type | Description |
| --- | --- | --- |
| [resolved\_objects](./kibana-plugin-core-public.savedobjectsbulkresolveresponse.resolved_objects.md) | <code>Array&lt;SavedObjectsResolveResponse&lt;T&gt;&gt;</code> | |

Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->

[Home](./index.md) &gt; [kibana-plugin-core-public](./kibana-plugin-core-public.md) &gt; [SavedObjectsBulkResolveResponse](./kibana-plugin-core-public.savedobjectsbulkresolveresponse.md) &gt; [resolved\_objects](./kibana-plugin-core-public.savedobjectsbulkresolveresponse.resolved_objects.md)

## SavedObjectsBulkResolveResponse.resolved\_objects property

<b>Signature:</b>

```typescript
resolved_objects: Array<SavedObjectsResolveResponse<T>>;
```
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->

[Home](./index.md) &gt; [kibana-plugin-core-public](./kibana-plugin-core-public.md) &gt; [SavedObjectsClient](./kibana-plugin-core-public.savedobjectsclient.md) &gt; [bulkResolve](./kibana-plugin-core-public.savedobjectsclient.bulkresolve.md)

## SavedObjectsClient.bulkResolve property

Resolves an array of objects by id, using any legacy URL aliases if they exist

<b>Signature:</b>

```typescript
bulkResolve: <T = unknown>(objects?: Array<{
id: string;
type: string;
}>) => Promise<{
resolved_objects: ResolvedSimpleSavedObject<T>[];
}>;
```

## Example

bulkResolve(\[ { id: 'one', type: 'config' }<!-- -->, { id: 'foo', type: 'index-pattern' } \])

Saved objects that Kibana fails to find are replaced with an error object and an "exactMatch" outcome. The rationale behind the outcome is that "exactMatch" is the default outcome, and the outcome only changes if an alias is found. The `resolve` method in the public client uses `bulkResolve` under the hood, so it behaves the same way.

Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ The constructor for this class is marked as internal. Third-party code should no
| --- | --- | --- | --- |
| [bulkCreate](./kibana-plugin-core-public.savedobjectsclient.bulkcreate.md) | | <code>(objects?: SavedObjectsBulkCreateObject[], options?: SavedObjectsBulkCreateOptions) =&gt; Promise&lt;SavedObjectsBatchResponse&lt;unknown&gt;&gt;</code> | Creates multiple documents at once |
| [bulkGet](./kibana-plugin-core-public.savedobjectsclient.bulkget.md) | | <code>(objects?: Array&lt;{</code><br/><code> id: string;</code><br/><code> type: string;</code><br/><code> }&gt;) =&gt; Promise&lt;SavedObjectsBatchResponse&lt;unknown&gt;&gt;</code> | Returns an array of objects by id |
| [bulkResolve](./kibana-plugin-core-public.savedobjectsclient.bulkresolve.md) | | <code>&lt;T = unknown&gt;(objects?: Array&lt;{</code><br/><code> id: string;</code><br/><code> type: string;</code><br/><code> }&gt;) =&gt; Promise&lt;{</code><br/><code> resolved_objects: ResolvedSimpleSavedObject&lt;T&gt;[];</code><br/><code> }&gt;</code> | Resolves an array of objects by id, using any legacy URL aliases if they exist |
| [create](./kibana-plugin-core-public.savedobjectsclient.create.md) | | <code>&lt;T = unknown&gt;(type: string, attributes: T, options?: SavedObjectsCreateOptions) =&gt; Promise&lt;SimpleSavedObject&lt;T&gt;&gt;</code> | Persists an object |
| [delete](./kibana-plugin-core-public.savedobjectsclient.delete.md) | | <code>(type: string, id: string, options?: SavedObjectsDeleteOptions &#124; undefined) =&gt; ReturnType&lt;SavedObjectsApi['delete']&gt;</code> | Deletes an object |
| [find](./kibana-plugin-core-public.savedobjectsclient.find.md) | | <code>&lt;T = unknown, A = unknown&gt;(options: SavedObjectsFindOptions) =&gt; Promise&lt;SavedObjectsFindResponsePublic&lt;T, unknown&gt;&gt;</code> | Search for objects |
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ async function getDeprecations({ esClient, savedObjectsClient }: GetDeprecations
const deprecations: DeprecationsDetails[] = [];
const count = await getFooCount(savedObjectsClient);
if (count > 0) {
// Example of a manual correctiveAction
deprecations.push({
title: i18n.translate('xpack.foo.deprecations.title', {
defaultMessage: `Foo's are deprecated`
Expand Down
2 changes: 2 additions & 0 deletions docs/development/core/server/kibana-plugin-core-server.md
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,8 @@ The plugin integrates with the core system via lifecycle events: `setup`<!-- -->
| [SavedObjectsBaseOptions](./kibana-plugin-core-server.savedobjectsbaseoptions.md) | |
| [SavedObjectsBulkCreateObject](./kibana-plugin-core-server.savedobjectsbulkcreateobject.md) | |
| [SavedObjectsBulkGetObject](./kibana-plugin-core-server.savedobjectsbulkgetobject.md) | |
| [SavedObjectsBulkResolveObject](./kibana-plugin-core-server.savedobjectsbulkresolveobject.md) | |
| [SavedObjectsBulkResolveResponse](./kibana-plugin-core-server.savedobjectsbulkresolveresponse.md) | |
| [SavedObjectsBulkResponse](./kibana-plugin-core-server.savedobjectsbulkresponse.md) | |
| [SavedObjectsBulkUpdateObject](./kibana-plugin-core-server.savedobjectsbulkupdateobject.md) | |
| [SavedObjectsBulkUpdateOptions](./kibana-plugin-core-server.savedobjectsbulkupdateoptions.md) | |
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->

[Home](./index.md) &gt; [kibana-plugin-core-server](./kibana-plugin-core-server.md) &gt; [SavedObjectsBulkResolveObject](./kibana-plugin-core-server.savedobjectsbulkresolveobject.md) &gt; [id](./kibana-plugin-core-server.savedobjectsbulkresolveobject.id.md)

## SavedObjectsBulkResolveObject.id property

<b>Signature:</b>

```typescript
id: string;
```
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->

[Home](./index.md) &gt; [kibana-plugin-core-server](./kibana-plugin-core-server.md) &gt; [SavedObjectsBulkResolveObject](./kibana-plugin-core-server.savedobjectsbulkresolveobject.md)

## SavedObjectsBulkResolveObject interface


<b>Signature:</b>

```typescript
export interface SavedObjectsBulkResolveObject
```

## Properties

| Property | Type | Description |
| --- | --- | --- |
| [id](./kibana-plugin-core-server.savedobjectsbulkresolveobject.id.md) | <code>string</code> | |
| [type](./kibana-plugin-core-server.savedobjectsbulkresolveobject.type.md) | <code>string</code> | |

Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->

[Home](./index.md) &gt; [kibana-plugin-core-server](./kibana-plugin-core-server.md) &gt; [SavedObjectsBulkResolveObject](./kibana-plugin-core-server.savedobjectsbulkresolveobject.md) &gt; [type](./kibana-plugin-core-server.savedobjectsbulkresolveobject.type.md)

## SavedObjectsBulkResolveObject.type property

<b>Signature:</b>

```typescript
type: string;
```
Loading

0 comments on commit b34f986

Please sign in to comment.