Skip to content

Commit

Permalink
Merge branch 'master' into ml-base-privilege
Browse files Browse the repository at this point in the history
  • Loading branch information
kibanamachine committed Oct 26, 2021
2 parents f1b8294 + eb74b86 commit 485a632
Show file tree
Hide file tree
Showing 112 changed files with 1,084 additions and 2,836 deletions.
12 changes: 6 additions & 6 deletions .bazelrc
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,12 @@
import %workspace%/.bazelrc.common

# Remote cache settings for local env
build --remote_cache=grpcs://cloud.buildbuddy.io
build --incompatible_remote_results_ignore_disk=true
build --noremote_upload_local_results
build --remote_timeout=30
build --remote_header=x-buildbuddy-api-key=3EYk49W2NefOx2n3yMze
build --remote_accept_cached=true
# build --remote_cache=grpcs://cloud.buildbuddy.io
# build --incompatible_remote_results_ignore_disk=true
# build --noremote_upload_local_results
# build --remote_timeout=30
# build --remote_header=x-buildbuddy-api-key=3EYk49W2NefOx2n3yMze
# build --remote_accept_cached=true

# Enable this in case you want to share your build info
# build --build_metadata=VISIBILITY=PUBLIC
Expand Down
10 changes: 5 additions & 5 deletions dev_docs/tutorials/data/search.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ tags: ['kibana', 'onboarding', 'dev', 'tutorials', 'search', 'sessions', 'search

Searching data stored in Elasticsearch can be done in various ways, for example using the Elasticsearch REST API or using an `Elasticsearch Client` for low level access.

However, the recommended and easist way to search Elasticsearch is by using the low level search service. The service is exposed from the `data` plugin, and by using it, you not only gain access to the data you stored, but also to capabilities, such as Custom Search Strategies, Asynchronous Search, Partial Results, Search Sessions, and more.
However, the recommended and easiest way to search Elasticsearch is by using the low level search service. The service is exposed from the `data` plugin, and by using it, you not only gain access to the data you stored, but also to capabilities, such as Custom Search Strategies, Asynchronous Search, Partial Results, Search Sessions, and more.

Here is a basic example for using the `data.search` service from a custom plugin:

Expand Down Expand Up @@ -418,11 +418,11 @@ export class MyPlugin implements Plugin {
// return the name you want to give the saved Search Session
return `MyApp_${Math.random()}`;
},
getUrlGeneratorData: async () => {
getLocatorData: async () => {
return {
urlGeneratorId: MY_URL_GENERATOR,
initialState: getUrlGeneratorState({ ...deps, shouldRestoreSearchSession: false }),
restoreState: getUrlGeneratorState({ ...deps, shouldRestoreSearchSession: true }),
id: MY_LOCATOR,
initialState: getLocatorParams({ ...deps, shouldRestoreSearchSession: false }),
restoreState: getLocatorParams({ ...deps, shouldRestoreSearchSession: true }),
};
},
});
Expand Down
20 changes: 8 additions & 12 deletions examples/search_examples/public/plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,18 +8,18 @@

import {
AppMountParameters,
AppNavLinkStatus,
CoreSetup,
CoreStart,
Plugin,
AppNavLinkStatus,
} from '../../../src/core/public';
import {
SearchExamplesPluginSetup,
SearchExamplesPluginStart,
AppPluginSetupDependencies,
AppPluginStartDependencies,
SearchExamplesPluginSetup,
SearchExamplesPluginStart,
} from './types';
import { createSearchSessionsExampleUrlGenerator } from './search_sessions/url_generator';
import { SearchSessionsExamplesAppLocatorDefinition } from './search_sessions/app_locator';
import { PLUGIN_NAME } from '../common';
import img from './search_examples.png';

Expand Down Expand Up @@ -67,14 +67,10 @@ export class SearchExamplesPlugin
],
});

// we need an URL generator for search session examples for restoring a search session
share.urlGenerators.registerUrlGenerator(
createSearchSessionsExampleUrlGenerator(() => {
return core
.getStartServices()
.then(([coreStart]) => ({ appBasePath: coreStart.http.basePath.get() }));
})
);
// we need an locator for search session examples for restoring a search session
const getAppBasePath = () =>
core.getStartServices().then(([coreStart]) => coreStart.http.basePath.get());
share.url.locators.create(new SearchSessionsExamplesAppLocatorDefinition(getAppBasePath));

return {};
}
Expand Down
14 changes: 5 additions & 9 deletions examples/search_examples/public/search_sessions/app.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -55,11 +55,7 @@ import {
createStateContainer,
useContainerState,
} from '../../../../src/plugins/kibana_utils/public';
import {
getInitialStateFromUrl,
SEARCH_SESSIONS_EXAMPLES_APP_URL_GENERATOR,
SearchSessionExamplesUrlGeneratorState,
} from './url_generator';
import { getInitialStateFromUrl, SEARCH_SESSIONS_EXAMPLES_APP_LOCATOR } from './app_locator';

interface SearchSessionsExampleAppDeps {
notifications: CoreStart['notifications'];
Expand Down Expand Up @@ -140,23 +136,23 @@ export const SearchSessionsExampleApp = ({
const enableSessionStorage = useCallback(() => {
data.search.session.enableStorage({
getName: async () => 'Search sessions example',
getUrlGeneratorData: async () => ({
getLocatorData: async () => ({
initialState: {
time: data.query.timefilter.timefilter.getTime(),
filters: data.query.filterManager.getFilters(),
query: data.query.queryString.getQuery(),
indexPatternId: indexPattern?.id,
numericFieldName,
} as SearchSessionExamplesUrlGeneratorState,
},
restoreState: {
time: data.query.timefilter.timefilter.getAbsoluteTime(),
filters: data.query.filterManager.getFilters(),
query: data.query.queryString.getQuery(),
indexPatternId: indexPattern?.id,
numericFieldName,
searchSessionId: data.search.session.getSessionId(),
} as SearchSessionExamplesUrlGeneratorState,
urlGeneratorId: SEARCH_SESSIONS_EXAMPLES_APP_URL_GENERATOR,
},
id: SEARCH_SESSIONS_EXAMPLES_APP_LOCATOR,
}),
});
}, [
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,50 +6,50 @@
* Side Public License, v 1.
*/

import { TimeRange, Filter, Query, esFilters } from '../../../../src/plugins/data/public';
import { SerializableRecord } from '@kbn/utility-types';
import { esFilters, Filter, Query, TimeRange } from '../../../../src/plugins/data/public';
import { getStatesFromKbnUrl, setStateToKbnUrl } from '../../../../src/plugins/kibana_utils/public';
import { UrlGeneratorsDefinition } from '../../../../src/plugins/share/public';
import { LocatorDefinition } from '../../../../src/plugins/share/common';

export const STATE_STORAGE_KEY = '_a';
export const GLOBAL_STATE_STORAGE_KEY = '_g';

export const SEARCH_SESSIONS_EXAMPLES_APP_URL_GENERATOR =
'SEARCH_SESSIONS_EXAMPLES_APP_URL_GENERATOR';
export const SEARCH_SESSIONS_EXAMPLES_APP_LOCATOR = 'SEARCH_SESSIONS_EXAMPLES_APP_LOCATOR';

export interface AppUrlState {
export interface AppUrlState extends SerializableRecord {
filters?: Filter[];
query?: Query;
indexPatternId?: string;
numericFieldName?: string;
searchSessionId?: string;
}

export interface GlobalUrlState {
export interface GlobalUrlState extends SerializableRecord {
filters?: Filter[];
time?: TimeRange;
}

export type SearchSessionExamplesUrlGeneratorState = AppUrlState & GlobalUrlState;
export type SearchSessionsExamplesAppLocatorParams = AppUrlState & GlobalUrlState;

export const createSearchSessionsExampleUrlGenerator = (
getStartServices: () => Promise<{
appBasePath: string;
}>
): UrlGeneratorsDefinition<typeof SEARCH_SESSIONS_EXAMPLES_APP_URL_GENERATOR> => ({
id: SEARCH_SESSIONS_EXAMPLES_APP_URL_GENERATOR,
createUrl: async (state: SearchSessionExamplesUrlGeneratorState) => {
const startServices = await getStartServices();
const appBasePath = startServices.appBasePath;
const path = `${appBasePath}/app/searchExamples/search-sessions`;
export class SearchSessionsExamplesAppLocatorDefinition
implements LocatorDefinition<SearchSessionsExamplesAppLocatorParams>
{
public readonly id = SEARCH_SESSIONS_EXAMPLES_APP_LOCATOR;

constructor(protected readonly getAppBasePath: () => Promise<string>) {}

public readonly getLocation = async (params: SearchSessionsExamplesAppLocatorParams) => {
const appBasePath = await this.getAppBasePath();
const path = `${appBasePath}/search-sessions`;

let url = setStateToKbnUrl<AppUrlState>(
STATE_STORAGE_KEY,
{
query: state.query,
filters: state.filters?.filter((f) => !esFilters.isFilterPinned(f)),
indexPatternId: state.indexPatternId,
numericFieldName: state.numericFieldName,
searchSessionId: state.searchSessionId,
query: params.query,
filters: params.filters?.filter((f) => !esFilters.isFilterPinned(f)),
indexPatternId: params.indexPatternId,
numericFieldName: params.numericFieldName,
searchSessionId: params.searchSessionId,
} as AppUrlState,
{ useHash: false, storeInHashQuery: false },
path
Expand All @@ -58,18 +58,22 @@ export const createSearchSessionsExampleUrlGenerator = (
url = setStateToKbnUrl<GlobalUrlState>(
GLOBAL_STATE_STORAGE_KEY,
{
time: state.time,
filters: state.filters?.filter((f) => esFilters.isFilterPinned(f)),
time: params.time,
filters: params.filters?.filter((f) => esFilters.isFilterPinned(f)),
} as GlobalUrlState,
{ useHash: false, storeInHashQuery: false },
url
);

return url;
},
});
return {
app: 'searchExamples',
path: url,
state: {},
};
};
}

export function getInitialStateFromUrl(): SearchSessionExamplesUrlGeneratorState {
export function getInitialStateFromUrl(): SearchSessionsExamplesAppLocatorParams {
const {
_a: { numericFieldName, indexPatternId, searchSessionId, filters: aFilters, query } = {},
_g: { filters: gFilters, time } = {},
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -330,7 +330,7 @@
"react-moment-proptypes": "^1.7.0",
"react-monaco-editor": "^0.41.2",
"react-popper-tooltip": "^2.10.1",
"react-query": "^3.27.0",
"react-query": "^3.28.0",
"react-redux": "^7.2.0",
"react-resizable": "^1.7.5",
"react-resize-detector": "^4.2.0",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,18 +7,19 @@
*/

import { History } from 'history';
import { DashboardConstants } from '../..';
import { DashboardAppLocatorParams, DashboardConstants } from '../..';
import { DashboardState } from '../../types';
import { getDashboardTitle } from '../../dashboard_strings';
import { DashboardSavedObject } from '../../saved_dashboards';
import { getQueryParams } from '../../services/kibana_utils';
import { createQueryParamObservable } from '../../../../kibana_utils/public';
import { DASHBOARD_APP_URL_GENERATOR, DashboardUrlGeneratorState } from '../../url_generator';
import {
DataPublicPluginStart,
noSearchSessionStorageCapabilityMessage,
SearchSessionInfoProvider,
} from '../../services/data';
import { stateToRawDashboardState } from './convert_dashboard_state';
import { DASHBOARD_APP_LOCATOR } from '../../locator';

export const getSearchSessionIdFromURL = (history: History): string | undefined =>
getQueryParams(history.location)[DashboardConstants.SEARCH_SESSION_ID] as string | undefined;
Expand All @@ -32,16 +33,14 @@ export function createSessionRestorationDataProvider(deps: {
getAppState: () => DashboardState;
getDashboardTitle: () => string;
getDashboardId: () => string;
}) {
}): SearchSessionInfoProvider<DashboardAppLocatorParams> {
return {
getName: async () => deps.getDashboardTitle(),
getUrlGeneratorData: async () => {
return {
urlGeneratorId: DASHBOARD_APP_URL_GENERATOR,
initialState: getUrlGeneratorState({ ...deps, shouldRestoreSearchSession: false }),
restoreState: getUrlGeneratorState({ ...deps, shouldRestoreSearchSession: true }),
};
},
getLocatorData: async () => ({
id: DASHBOARD_APP_LOCATOR,
initialState: getLocatorParams({ ...deps, shouldRestoreSearchSession: false }),
restoreState: getLocatorParams({ ...deps, shouldRestoreSearchSession: true }),
}),
};
}

Expand Down Expand Up @@ -93,7 +92,7 @@ export function enableDashboardSearchSessions({
* Fetches the state to store when a session is saved so that this dashboard can be recreated exactly
* as it was.
*/
function getUrlGeneratorState({
function getLocatorParams({
data,
getAppState,
kibanaVersion,
Expand All @@ -105,7 +104,7 @@ function getUrlGeneratorState({
getAppState: () => DashboardState;
getDashboardId: () => string;
shouldRestoreSearchSession: boolean;
}): DashboardUrlGeneratorState {
}): DashboardAppLocatorParams {
const appState = stateToRawDashboardState({ state: getAppState(), version: kibanaVersion });
const { filterManager, queryString } = data.query;
const { timefilter } = data.query.timefilter;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ describe('createSessionRestorationDataProvider', () => {
(mockDataPlugin.search.session.getSessionId as jest.Mock).mockImplementation(
() => searchSessionId
);
const { initialState, restoreState } = await searchSessionInfoProvider.getUrlGeneratorData();
const { initialState, restoreState } = await searchSessionInfoProvider.getLocatorData();
expect(initialState.searchSessionId).toBeUndefined();
expect(restoreState.searchSessionId).toBe(searchSessionId);
});
Expand All @@ -48,13 +48,13 @@ describe('createSessionRestorationDataProvider', () => {
(mockDataPlugin.query.timefilter.timefilter.getAbsoluteTime as jest.Mock).mockImplementation(
() => absoluteTime
);
const { initialState, restoreState } = await searchSessionInfoProvider.getUrlGeneratorData();
const { initialState, restoreState } = await searchSessionInfoProvider.getLocatorData();
expect(initialState.timeRange).toBe(relativeTime);
expect(restoreState.timeRange).toBe(absoluteTime);
});

test('restoreState has refreshInterval paused', async () => {
const { initialState, restoreState } = await searchSessionInfoProvider.getUrlGeneratorData();
const { initialState, restoreState } = await searchSessionInfoProvider.getLocatorData();
expect(initialState.refreshInterval).toBeUndefined();
expect(restoreState.refreshInterval?.pause).toBe(true);
});
Expand Down
9 changes: 5 additions & 4 deletions src/plugins/data/common/search/session/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
* Side Public License, v 1.
*/

import { SerializableRecord } from '@kbn/utility-types';
import { SearchSessionStatus } from './status';

export const SEARCH_SESSION_TYPE = 'search-session';
Expand Down Expand Up @@ -43,19 +44,19 @@ export interface SearchSessionSavedObjectAttributes {
*/
status: SearchSessionStatus;
/**
* urlGeneratorId
* locatorId (see share.url.locators service)
*/
urlGeneratorId?: string;
locatorId?: string;
/**
* The application state that was used to create the session.
* Should be used, for example, to re-load an expired search session.
*/
initialState?: Record<string, unknown>;
initialState?: SerializableRecord;
/**
* Application state that should be used to restore the session.
* For example, relative dates are conveted to absolute ones.
*/
restoreState?: Record<string, unknown>;
restoreState?: SerializableRecord;
/**
* Mapping of search request hashes to their corresponsing info (async search id, etc.)
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ const mockSavedObject: SearchSessionSavedObject = {
attributes: {
name: 'my_name',
appId: 'my_app_id',
urlGeneratorId: 'my_url_generator_id',
locatorId: 'my_url_generator_id',
idMapping: {},
sessionId: 'session_id',
touched: new Date().toISOString(),
Expand Down
Loading

0 comments on commit 485a632

Please sign in to comment.