Skip to content

Commit

Permalink
Merge remote-tracking branch 'upstream/master' into task/fleet-82492-…
Browse files Browse the repository at this point in the history
…integration-custom-tab
  • Loading branch information
paul-tavares committed Nov 30, 2020
2 parents 093fecb + 2e6dca6 commit 630f7c2
Show file tree
Hide file tree
Showing 232 changed files with 11,418 additions and 2,309 deletions.
76 changes: 74 additions & 2 deletions docs/developer/plugin/migrating-legacy-plugins-examples.asciidoc
Original file line number Diff line number Diff line change
Expand Up @@ -902,8 +902,9 @@ The most significant changes on the Kibana side for the consumers are the follow
===== User client accessor
Internal /current user client accessors has been renamed and are now
properties instead of functions:
** `callAsInternalUser('ping')` -> `asInternalUser.ping()`
** `callAsCurrentUser('ping')` -> `asCurrentUser.ping()`

* `callAsInternalUser('ping')` -> `asInternalUser.ping()`
* `callAsCurrentUser('ping')` -> `asCurrentUser.ping()`
* the API now reflects the `Client`’s instead of leveraging the
string-based endpoint names the `LegacyAPICaller` was using.

Expand Down Expand Up @@ -1142,6 +1143,77 @@ router.get(
);
----

==== Accessing the client from a collector's `fetch` method

At the moment, the `fetch` method's context receives preconfigured
<<scoped-services, scoped clients>> for Elasticsearch and SavedObjects.
To help in the transition, both, the legacy (`callCluster`) and new clients are provided,
but we strongly discourage using the deprecated legacy ones for any new implementation.

[source,typescript]
----
usageCollection.makeUsageCollector<MyUsage>({
type: 'my-collector',
isReady: async () => true, // Logic to confirm the `fetch` method is ready to be called
schema: {...},
async fetch(context) {
const { callCluster, esClient, soClient } = context;
// Before:
const result = callCluster('search', options)
// After:
const { body: result } = esClient.search(options);
return result;
}
});
----

Regarding the `soClient`, it is encouraged to use it instead of the plugin's owned SavedObject's repository
as we used to do in the past.

Before:

[source,typescript]
----
function getUsageCollector(
usageCollection: UsageCollectionSetup,
getSavedObjectsRepository: () => ISavedObjectsRepository | undefined
) {
usageCollection.makeUsageCollector<MyUsage>({
type: 'my-collector',
isReady: () => typeof getSavedObjectsRepository() !== 'undefined',
schema: {...},
async fetch() {
const savedObjectsRepository = getSavedObjectsRepository();
const { attributes: result } = await savedObjectsRepository.get('my-so-type', 'my-so-id');
return result;
}
});
}
----

After:

[source,typescript]
----
function getUsageCollector(usageCollection: UsageCollectionSetup) {
usageCollection.makeUsageCollector<MyUsage>({
type: 'my-collector',
isReady: () => true,
schema: {...},
async fetch({ soClient }) {
const { attributes: result } = await soClient.get('my-so-type', 'my-so-id');
return result;
}
});
}
----

==== Creating a custom client

Note that the `plugins` option is no longer available on the new
Expand Down
13 changes: 13 additions & 0 deletions src/cli/cluster/cluster_manager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,19 @@ export class ClusterManager {
this.inReplMode = !!opts.repl;
this.basePathProxy = basePathProxy;

if (!this.basePathProxy) {
this.log.warn(
'===================================================================================================='
);
this.log.warn(
'no-base-path',
'Running Kibana in dev mode with --no-base-path disables several useful features and is not recommended'
);
this.log.warn(
'===================================================================================================='
);
}

// run @kbn/optimizer and write it's state to kbnOptimizerReady$
if (opts.disableOptimizer) {
this.kbnOptimizerReady$.next(true);
Expand Down
7 changes: 6 additions & 1 deletion src/core/server/http/base_path_proxy_server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -199,8 +199,13 @@ export class BasePathProxyServer {
const isGet = request.method === 'get';
const isBasepathLike = oldBasePath.length === 3;

const newUrl = Url.format({
pathname: `${this.httpConfig.basePath}/${kbnPath}`,
query: request.query,
});

return isGet && isBasepathLike && shouldRedirectFromOldBasePath(kbnPath)
? responseToolkit.redirect(`${this.httpConfig.basePath}/${kbnPath}`)
? responseToolkit.redirect(newUrl)
: responseToolkit.response('Not Found').code(404);
},
method: '*',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,9 @@ kibana_vars=(
xpack.code.security.gitProtocolWhitelist
xpack.encryptedSavedObjects.encryptionKey
xpack.encryptedSavedObjects.keyRotation.decryptionOnlyKeys
xpack.fleet.agents.elasticsearch.host
xpack.fleet.agents.kibana.host
xpack.fleet.agents.tlsCheckDisabled
xpack.graph.enabled
xpack.graph.canEditDrillDownUrls
xpack.graph.savePolicy
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -137,12 +137,17 @@ test('Add to library is not compatible when embeddable is not in a dashboard con
test('Add to library replaces embeddableId and retains panel count', async () => {
const dashboard = embeddable.getRoot() as IContainer;
const originalPanelCount = Object.keys(dashboard.getInput().panels).length;
const originalPanelKeySet = new Set(Object.keys(dashboard.getInput().panels));

const action = new AddToLibraryAction({ toasts: coreStart.notifications.toasts });
await action.execute({ embeddable });
expect(Object.keys(container.getInput().panels).length).toEqual(originalPanelCount);
expect(Object.keys(container.getInput().panels)).toContain(embeddable.id);
const newPanel = container.getInput().panels[embeddable.id!];

const newPanelId = Object.keys(container.getInput().panels).find(
(key) => !originalPanelKeySet.has(key)
);
expect(newPanelId).toBeDefined();
const newPanel = container.getInput().panels[newPanelId!];
expect(newPanel.type).toEqual(embeddable.type);
});

Expand All @@ -158,10 +163,15 @@ test('Add to library returns reference type input', async () => {
mockedByReferenceInput: { savedObjectId: 'testSavedObjectId', id: embeddable.id },
mockedByValueInput: { attributes: complicatedAttributes, id: embeddable.id } as EmbeddableInput,
});
const dashboard = embeddable.getRoot() as IContainer;
const originalPanelKeySet = new Set(Object.keys(dashboard.getInput().panels));
const action = new AddToLibraryAction({ toasts: coreStart.notifications.toasts });
await action.execute({ embeddable });
expect(Object.keys(container.getInput().panels)).toContain(embeddable.id);
const newPanel = container.getInput().panels[embeddable.id!];
const newPanelId = Object.keys(container.getInput().panels).find(
(key) => !originalPanelKeySet.has(key)
);
expect(newPanelId).toBeDefined();
const newPanel = container.getInput().panels[newPanelId!];
expect(newPanel.type).toEqual(embeddable.type);
expect(newPanel.explicitInput.attributes).toBeUndefined();
expect(newPanel.explicitInput.savedObjectId).toBe('testSavedObjectId');
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@

import { i18n } from '@kbn/i18n';
import _ from 'lodash';
import uuid from 'uuid';
import { ActionByType, IncompatibleActionError } from '../../ui_actions_plugin';
import { ViewMode, PanelState, IEmbeddable } from '../../embeddable_plugin';
import {
Expand Down Expand Up @@ -89,9 +88,9 @@ export class AddToLibraryAction implements ActionByType<typeof ACTION_ADD_TO_LIB

const newPanel: PanelState<EmbeddableInput> = {
type: embeddable.type,
explicitInput: { ...newInput, id: uuid.v4() },
explicitInput: { ...newInput },
};
dashboard.replacePanel(panelToReplace, newPanel);
dashboard.replacePanel(panelToReplace, newPanel, true);

const title = i18n.translate('dashboard.panel.addToLibrary.successMessage', {
defaultMessage: `Panel '{panelTitle}' was added to the visualize library`,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -135,11 +135,16 @@ test('Unlink is not compatible when embeddable is not in a dashboard container',
test('Unlink replaces embeddableId and retains panel count', async () => {
const dashboard = embeddable.getRoot() as IContainer;
const originalPanelCount = Object.keys(dashboard.getInput().panels).length;
const originalPanelKeySet = new Set(Object.keys(dashboard.getInput().panels));
const action = new UnlinkFromLibraryAction({ toasts: coreStart.notifications.toasts });
await action.execute({ embeddable });
expect(Object.keys(container.getInput().panels).length).toEqual(originalPanelCount);
expect(Object.keys(container.getInput().panels)).toContain(embeddable.id);
const newPanel = container.getInput().panels[embeddable.id!];

const newPanelId = Object.keys(container.getInput().panels).find(
(key) => !originalPanelKeySet.has(key)
);
expect(newPanelId).toBeDefined();
const newPanel = container.getInput().panels[newPanelId!];
expect(newPanel.type).toEqual(embeddable.type);
});

Expand All @@ -159,10 +164,15 @@ test('Unlink unwraps all attributes from savedObject', async () => {
mockedByReferenceInput: { savedObjectId: 'testSavedObjectId', id: embeddable.id },
mockedByValueInput: { attributes: complicatedAttributes, id: embeddable.id },
});
const dashboard = embeddable.getRoot() as IContainer;
const originalPanelKeySet = new Set(Object.keys(dashboard.getInput().panels));
const action = new UnlinkFromLibraryAction({ toasts: coreStart.notifications.toasts });
await action.execute({ embeddable });
expect(Object.keys(container.getInput().panels)).toContain(embeddable.id);
const newPanel = container.getInput().panels[embeddable.id!];
const newPanelId = Object.keys(container.getInput().panels).find(
(key) => !originalPanelKeySet.has(key)
);
expect(newPanelId).toBeDefined();
const newPanel = container.getInput().panels[newPanelId!];
expect(newPanel.type).toEqual(embeddable.type);
expect(newPanel.explicitInput.attributes).toEqual(complicatedAttributes);
});
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@

import { i18n } from '@kbn/i18n';
import _ from 'lodash';
import uuid from 'uuid';
import { ActionByType, IncompatibleActionError } from '../../ui_actions_plugin';
import { ViewMode, PanelState, IEmbeddable } from '../../embeddable_plugin';
import {
Expand Down Expand Up @@ -88,9 +87,9 @@ export class UnlinkFromLibraryAction implements ActionByType<typeof ACTION_UNLIN

const newPanel: PanelState<EmbeddableInput> = {
type: embeddable.type,
explicitInput: { ...newInput, id: uuid.v4() },
explicitInput: { ...newInput },
};
dashboard.replacePanel(panelToReplace, newPanel);
dashboard.replacePanel(panelToReplace, newPanel, true);

const title = embeddable.getTitle()
? i18n.translate('dashboard.panel.unlinkFromLibrary.successMessageWithTitle', {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -173,11 +173,30 @@ export class DashboardContainer extends Container<InheritedChildInput, Dashboard

public replacePanel(
previousPanelState: DashboardPanelState<EmbeddableInput>,
newPanelState: Partial<PanelState>
newPanelState: Partial<PanelState>,
generateNewId?: boolean
) {
// Because the embeddable type can change, we have to operate at the container level here
return this.updateInput({
panels: {
let panels;
if (generateNewId) {
// replace panel can be called with generateNewId in order to totally destroy and recreate the embeddable
panels = { ...this.input.panels };
delete panels[previousPanelState.explicitInput.id];
const newId = uuid.v4();
panels[newId] = {
...previousPanelState,
...newPanelState,
gridData: {
...previousPanelState.gridData,
i: newId,
},
explicitInput: {
...newPanelState.explicitInput,
id: newId,
},
};
} else {
// Because the embeddable type can change, we have to operate at the container level here
panels = {
...this.input.panels,
[previousPanelState.explicitInput.id]: {
...previousPanelState,
Expand All @@ -190,7 +209,11 @@ export class DashboardContainer extends Container<InheritedChildInput, Dashboard
id: previousPanelState.explicitInput.id,
},
},
},
};
}

return this.updateInput({
panels,
lastReloadRequestTime: new Date().getTime(),
});
}
Expand Down
6 changes: 3 additions & 3 deletions src/plugins/discover/public/application/angular/discover.js
Original file line number Diff line number Diff line change
Expand Up @@ -252,7 +252,8 @@ function discoverController($element, $route, $scope, $timeout, $window, Promise
if (!_.isEqual(newStatePartial, oldStatePartial)) {
$scope.$evalAsync(async () => {
if (oldStatePartial.index !== newStatePartial.index) {
//in case of index switch the route has currently to be reloaded, legacy
//in case of index pattern switch the route has currently to be reloaded, legacy
$route.reload();
return;
}

Expand Down Expand Up @@ -289,8 +290,7 @@ function discoverController($element, $route, $scope, $timeout, $window, Promise
$scope.state.sort,
config.get(MODIFY_COLUMNS_ON_SWITCH)
);
await replaceUrlAppState(nextAppState);
$route.reload();
await setAppState(nextAppState);
}
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ export const applicationUsageSchema = {
logs: commonSchema,
metrics: commonSchema,
infra: commonSchema, // It's a forward app so we'll likely never report it
ingestManager: commonSchema,
fleet: commonSchema,
lens: commonSchema,
maps: commonSchema,
ml: commonSchema,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ describe('telemetry_application_usage', () => {

const logger = loggingSystemMock.createLogger();

let collector: Collector<unknown, unknown>;
let collector: Collector<unknown>;

const usageCollectionMock = createUsageCollectionSetupMock();
usageCollectionMock.makeUsageCollector.mockImplementation((config) => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ export function getCoreUsageCollector(
usageCollection: UsageCollectionSetup,
getCoreUsageDataService: () => CoreUsageDataStart
) {
return usageCollection.makeUsageCollector<CoreUsageData, { core: CoreUsageData }>({
return usageCollection.makeUsageCollector<CoreUsageData>({
type: 'core',
isReady: () => typeof getCoreUsageDataService() !== 'undefined',
schema: {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ import { CoreUsageData } from 'src/core/server/';
const logger = loggingSystemMock.createLogger();

describe('telemetry_core', () => {
let collector: Collector<unknown, unknown>;
let collector: Collector<unknown>;

const usageCollectionMock = createUsageCollectionSetupMock();
usageCollectionMock.makeUsageCollector.mockImplementation((config) => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ import { registerKibanaUsageCollector } from './';
const logger = loggingSystemMock.createLogger();

describe('telemetry_kibana', () => {
let collector: Collector<unknown, unknown>;
let collector: Collector<unknown>;

const usageCollectionMock = createUsageCollectionSetupMock();
usageCollectionMock.makeUsageCollector.mockImplementation((config) => {
Expand Down Expand Up @@ -66,23 +66,4 @@ describe('telemetry_kibana', () => {
timelion_sheet: { total: 0 },
});
});

test('formatForBulkUpload', async () => {
const resultFromFetch = {
index: '.kibana-tests',
dashboard: { total: 0 },
visualization: { total: 0 },
search: { total: 0 },
index_pattern: { total: 0 },
graph_workspace: { total: 0 },
timelion_sheet: { total: 0 },
};

expect(collector.formatForBulkUpload!(resultFromFetch)).toStrictEqual({
type: 'kibana_stats',
payload: {
usage: resultFromFetch,
},
});
});
});
Loading

0 comments on commit 630f7c2

Please sign in to comment.