-
Notifications
You must be signed in to change notification settings - Fork 8.3k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[Streams] Dashboard linking (#204309)
Links dashboard to Streams. Changes: - Introduces `IndexStorageAdapter` to manage ES indices - see https://github.com/dgieselaar/kibana/blob/streams-app-asset-linking/x-pack/solutions/observability/packages/utils_server/es/storage/README.md for motivation - Introduces `AssetClient` and `AssetService` to manage asset links with `IndexStorageAdapter` - `RepositorySupertestClient` to make it easier to use `@kbn/server-route-repository` with FTR tests - refactors related to above changes --------- Co-authored-by: Chris Cowan <[email protected]> Co-authored-by: Joe Reuter <[email protected]> Co-authored-by: kibanamachine <[email protected]> Co-authored-by: Elastic Machine <[email protected]>
- Loading branch information
1 parent
8a9202e
commit 28414ce
Showing
64 changed files
with
3,834 additions
and
262 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
76 changes: 76 additions & 0 deletions
76
x-pack/solutions/observability/packages/utils_server/es/storage/README.md
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,76 @@ | ||
# Storage adapter | ||
|
||
Storage adapters are an abstraction for managing & writing data into Elasticsearch, from Kibana plugins. | ||
|
||
There are several ways one can use Elasticsearch in Kibana, for instance: | ||
|
||
- a simple id-based CRUD table | ||
- timeseries data with regular indices | ||
- timeseries data with data streams | ||
|
||
But then there are many choices to be made that make this a very complex problem: | ||
|
||
- Elasticsearch asset managmeent | ||
- Authentication | ||
- Schema changes | ||
- Kibana's distributed nature | ||
- Stateful versus serverless | ||
|
||
The intent of storage adapters is to come up with an abstraction that allows Kibana developers to have a common interface for writing to and reading data from Elasticsearch. For instance, for setting up your data store, it should not matter how you authenticate (internal user? current user? API keys?). | ||
|
||
## Saved objects | ||
|
||
Some of these problems are solved by Saved Objects. But Saved Objects come with a lot of baggage - Kibana RBAC, relationships, spaces, all of which might not be | ||
needed for your use case but are still restrictive. One could consider Saved Objects to be the target of an adapter, but Storage Adapters aim to address a wider set of use-cases. | ||
|
||
## Philosophy | ||
|
||
Storage adapters should largely adhere to the following principles: | ||
|
||
- Interfaces are as close to Elasticsearch as possible. Meaning, the `search` method is practically a pass-through for `_search`. | ||
- Strongly-typed. TypeScript types are inferred from the schema. This makes it easy to create fully-typed clients for any storage. | ||
- Lazy writes. No Elasticsearch assets (templates, indices, aliases) get installed unless necessary. Anything that gets persisted to Elasticsearch raises questions (in SDHs, UIs, APIs) and should be avoided when possible. This also helps avoidable upgrade issues (e.g. conflicting mappings for something that never got used). | ||
- Recoverable. If somehow Elasticsearch assets get borked, the adapters should make a best-effort attempt to recover, or log warnings with clear remediation steps. | ||
|
||
## Future goals | ||
|
||
Currently, we only have the StorageIndexAdapter which writes to plain indices. In the future, we'll want more: | ||
|
||
- A StorageDataStreamAdapter or StorageSavedObjectAdapter | ||
- Federated search | ||
- Data/Index Lifecycle Management | ||
- Migration scripts | ||
- Runtime mappings for older versions | ||
|
||
## Usage | ||
|
||
### Storage index adapter | ||
|
||
To use the storage index adapter, instantiate it with an authenticated Elasticsearch client: | ||
|
||
```ts | ||
const storageSettings = { | ||
name: '.kibana_streams_assets', | ||
schema: { | ||
properties: { | ||
[ASSET_ASSET_ID]: types.keyword({ required: true }), | ||
[ASSET_TYPE]: types.enum(Object.values(ASSET_TYPES), { required: true }), | ||
}, | ||
}, | ||
} satisfies IndexStorageSettings; | ||
|
||
// create and configure the adapter | ||
const adapter = new StorageIndexAdapter( | ||
esClient: coreStart.elasticsearch.client.asInternalUser, | ||
this.logger.get('assets'), | ||
storageSettings | ||
); | ||
|
||
// get the client (its interface is shared across all adapters) | ||
const client = adapter.getClient(); | ||
|
||
const response = await client.search('operation_name', { | ||
track_total_hits: true | ||
}); | ||
|
||
``` |
15 changes: 15 additions & 0 deletions
15
x-pack/solutions/observability/packages/utils_server/es/storage/get_schema_version.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
/* | ||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one | ||
* or more contributor license agreements. Licensed under the Elastic License | ||
* 2.0; you may not use this file except in compliance with the Elastic License | ||
* 2.0. | ||
*/ | ||
|
||
import stringify from 'json-stable-stringify'; | ||
import objectHash from 'object-hash'; | ||
import { IndexStorageSettings } from '.'; | ||
|
||
export function getSchemaVersion(storage: IndexStorageSettings): string { | ||
const version = objectHash(stringify(storage.schema.properties)); | ||
return version; | ||
} |
91 changes: 91 additions & 0 deletions
91
x-pack/solutions/observability/packages/utils_server/es/storage/index.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 | ||
* 2.0; you may not use this file except in compliance with the Elastic License | ||
* 2.0. | ||
*/ | ||
import type { | ||
BulkOperationContainer, | ||
BulkRequest, | ||
BulkResponse, | ||
DeleteRequest, | ||
DeleteResponse, | ||
IndexRequest, | ||
IndexResponse, | ||
SearchRequest, | ||
} from '@elastic/elasticsearch/lib/api/types'; | ||
import { InferSearchResponseOf } from '@kbn/es-types'; | ||
import { StorageFieldTypeOf, StorageMappingProperty } from './types'; | ||
|
||
interface StorageSchemaProperties { | ||
[x: string]: StorageMappingProperty; | ||
} | ||
|
||
export interface StorageSchema { | ||
properties: StorageSchemaProperties; | ||
} | ||
|
||
interface StorageSettingsBase { | ||
schema: StorageSchema; | ||
} | ||
|
||
export interface IndexStorageSettings extends StorageSettingsBase { | ||
name: string; | ||
} | ||
|
||
export type StorageSettings = IndexStorageSettings; | ||
|
||
export type StorageAdapterSearchRequest = Omit<SearchRequest, 'index'>; | ||
export type StorageAdapterSearchResponse< | ||
TDocument, | ||
TSearchRequest extends Omit<SearchRequest, 'index'> | ||
> = InferSearchResponseOf<TDocument, TSearchRequest>; | ||
|
||
export type StorageAdapterBulkOperation = Pick<BulkOperationContainer, 'delete' | 'index'>; | ||
|
||
export type StorageAdapterBulkRequest<TDocument extends Record<string, any>> = Omit< | ||
BulkRequest, | ||
'operations' | 'index' | ||
> & { | ||
operations: Array<StorageAdapterBulkOperation | TDocument>; | ||
}; | ||
export type StorageAdapterBulkResponse = BulkResponse; | ||
|
||
export type StorageAdapterDeleteRequest = DeleteRequest; | ||
export type StorageAdapterDeleteResponse = DeleteResponse; | ||
|
||
export type StorageAdapterIndexRequest<TDocument = unknown> = Omit< | ||
IndexRequest<TDocument>, | ||
'index' | ||
>; | ||
export type StorageAdapterIndexResponse = IndexResponse; | ||
|
||
export interface IStorageAdapter<TStorageSettings extends StorageSettings = never> { | ||
bulk<TDocument extends Record<string, any>>( | ||
request: StorageAdapterBulkRequest<TDocument> | ||
): Promise<StorageAdapterBulkResponse>; | ||
search<TDocument, TSearchRequest extends Omit<SearchRequest, 'index'>>( | ||
request: StorageAdapterSearchRequest | ||
): Promise<StorageAdapterSearchResponse<TDocument, TSearchRequest>>; | ||
index<TDocument>( | ||
request: StorageAdapterIndexRequest<TDocument> | ||
): Promise<StorageAdapterIndexResponse>; | ||
delete(request: StorageAdapterDeleteRequest): Promise<StorageAdapterDeleteResponse>; | ||
} | ||
|
||
export type StorageSettingsOf<TStorageAdapter extends IStorageAdapter<StorageSettings>> = | ||
TStorageAdapter extends IStorageAdapter<infer TStorageSettings> | ||
? TStorageSettings extends StorageSettings | ||
? TStorageSettings | ||
: never | ||
: never; | ||
|
||
export type StorageDocumentOf<TStorageSettings extends StorageSettings> = { | ||
[TKey in keyof TStorageSettings['schema']['properties']]: StorageFieldTypeOf< | ||
TStorageSettings['schema']['properties'][TKey] | ||
>; | ||
} & { _id: string }; | ||
|
||
export { StorageIndexAdapter } from './index_adapter'; | ||
export { StorageClient } from './storage_client'; | ||
export { types } from './types'; |
Oops, something went wrong.