Remove kibana.defaultAppId setting (#109798)

* Remove kibana.defaultAppId setting

* Fix typings

* Remove plugin dependency

* Use proper navigation method to get to home

* Default route for home

* Address discover new routing code

* Make non existing /kibana URLs working

* Fix space awareness

* Remove documentation

* Remove the setting from docker file

* Make defaultRoute forward work properly

* Add forward_url tests

Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com>
This commit is contained in:
Tim Roes 2021-09-03 17:59:59 +02:00 committed by GitHub
parent 634ce7f83b
commit b6ab15e9f4
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
18 changed files with 70 additions and 210 deletions

View file

@ -295,12 +295,6 @@ is an alternative to `elasticsearch.username` and `elasticsearch.password`.
| `interpreter.enableInVisualize`
| Enables use of interpreter in Visualize. *Default: `true`*
| `kibana.defaultAppId:`
| deprecated:[7.9.0,This setting will be removed in Kibana 8.0.]
Instead, use the <<defaultroute,`defaultRoute` advanced setting>>.
+
The default application to load. *Default: `"home"`*
|[[kibana-index]] `kibana.index:`
| deprecated:[7.11.0,This setting will be removed in 8.0.] Multitenancy by
changing `kibana.index` will not be supported starting in 8.0. See

View file

@ -76,7 +76,6 @@ kibana_vars=(
interpreter.enableInVisualize
kibana.autocompleteTerminateAfter
kibana.autocompleteTimeout
kibana.defaultAppId
kibana.index
logging.appenders
logging.appenders.console

View file

@ -28,10 +28,7 @@ export function NotFoundRoute(props: NotFoundRouteProps) {
useEffect(() => {
const path = window.location.hash.substr(1);
getUrlTracker().restorePreviousUrl();
const { navigated } = urlForwarding.navigateToLegacyKibanaUrl(path);
if (!navigated) {
urlForwarding.navigateToDefaultApp();
}
urlForwarding.navigateToLegacyKibanaUrl(path);
const bannerMessage = i18n.translate('discover.noMatchRoute.bannerTitleText', {
defaultMessage: 'Page not found',

View file

@ -12,19 +12,10 @@ import PropTypes from 'prop-types';
import { Home } from './home';
import { TutorialDirectory } from './tutorial_directory';
import { Tutorial } from './tutorial/tutorial';
import { HashRouter as Router, Switch, Route } from 'react-router-dom';
import { HashRouter as Router, Switch, Route, Redirect } from 'react-router-dom';
import { getTutorial } from '../load_tutorials';
import { replaceTemplateStrings } from './tutorial/replace_template_strings';
import { getServices } from '../kibana_services';
import useMount from 'react-use/lib/useMount';
const RedirectToDefaultApp = () => {
useMount(() => {
const { urlForwarding } = getServices();
urlForwarding.navigateToDefaultApp();
});
return null;
};
export function HomeApp({ directories, solutions }) {
const {
@ -78,7 +69,7 @@ export function HomeApp({ directories, solutions }) {
hasUserIndexPattern={() => indexPatternService.hasUserIndexPattern()}
/>
</Route>
<Route path="*" exact={true} component={RedirectToDefaultApp} />
<Redirect to="/" />
</Switch>
</Router>
</I18nProvider>

View file

@ -14,7 +14,6 @@ import {
PluginInitializerContext,
} from 'kibana/public';
import { i18n } from '@kbn/i18n';
import { first } from 'rxjs/operators';
import {
EnvironmentService,
@ -137,27 +136,9 @@ export class HomePublicPlugin
};
}
public start(
{ application: { capabilities, currentAppId$ }, http }: CoreStart,
{ urlForwarding }: HomePluginStartDependencies
) {
public start({ application: { capabilities } }: CoreStart) {
this.featuresCatalogueRegistry.start({ capabilities });
// If the home app is the initial location when loading Kibana...
if (
window.location.pathname === http.basePath.prepend(HOME_APP_BASE_PATH) &&
window.location.hash === ''
) {
// ...wait for the app to mount initially and then...
currentAppId$.pipe(first()).subscribe((appId) => {
if (appId === 'home') {
// ...navigate to default app set by `kibana.defaultAppId`.
// This doesn't do anything as along as the default settings are kept.
urlForwarding.navigateToDefaultApp({ overwriteHash: false });
}
});
}
return { featureCatalogue: this.featuresCatalogueRegistry };
}
}

View file

@ -1,15 +0,0 @@
/*
* 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 and the Server Side Public License, v 1; you may not use this file except
* in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1.
*/
import { schema, TypeOf } from '@kbn/config-schema';
export const configSchema = schema.object({
defaultAppId: schema.string({ defaultValue: 'home' }),
});
export type ConfigSchema = TypeOf<typeof configSchema>;

View file

@ -1,7 +1,7 @@
{
"id": "kibanaLegacy",
"version": "kibana",
"server": true,
"server": false,
"ui": true,
"owner": {
"name": "Vis Editors",

View file

@ -9,11 +9,9 @@
// TODO: https://github.com/elastic/kibana/issues/110891
/* eslint-disable @kbn/eslint/no_export_all */
import { PluginInitializerContext } from 'kibana/public';
import { KibanaLegacyPlugin } from './plugin';
export const plugin = (initializerContext: PluginInitializerContext) =>
new KibanaLegacyPlugin(initializerContext);
export const plugin = () => new KibanaLegacyPlugin();
export * from './plugin';

View file

@ -14,9 +14,6 @@ export type Start = jest.Mocked<ReturnType<KibanaLegacyPlugin['start']>>;
const createSetupContract = (): Setup => ({});
const createStartContract = (): Start => ({
config: {
defaultAppId: 'home',
},
loadFontAwesome: jest.fn(),
loadAngularBootstrap: jest.fn(),
});

View file

@ -6,18 +6,15 @@
* Side Public License, v 1.
*/
import { PluginInitializerContext, CoreStart, CoreSetup } from 'kibana/public';
import { ConfigSchema } from '../config';
import { CoreStart, CoreSetup } from 'kibana/public';
import { injectHeaderStyle } from './utils/inject_header_style';
export class KibanaLegacyPlugin {
constructor(private readonly initializerContext: PluginInitializerContext<ConfigSchema>) {}
public setup(core: CoreSetup<{}, KibanaLegacyStart>) {
return {};
}
public start({ application, http: { basePath }, uiSettings }: CoreStart) {
public start({ uiSettings }: CoreStart) {
injectHeaderStyle(uiSettings);
return {
/**
@ -35,11 +32,6 @@ export class KibanaLegacyPlugin {
const { initAngularBootstrap } = await import('./angular_bootstrap');
initAngularBootstrap();
},
/**
* @deprecated
* Just exported for wiring up with dashboard mode, should not be used.
*/
config: this.initializerContext.config.get(),
};
}
}

View file

@ -1,49 +0,0 @@
/*
* 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 and the Server Side Public License, v 1; you may not use this file except
* in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1.
*/
import type { CoreSetup, CoreStart, PluginConfigDescriptor } from 'kibana/server';
import { get } from 'lodash';
import { configSchema, ConfigSchema } from '../config';
export const config: PluginConfigDescriptor<ConfigSchema> = {
exposeToBrowser: {
defaultAppId: true,
},
schema: configSchema,
deprecations: ({ renameFromRoot }) => [
// TODO: Remove deprecation once defaultAppId is deleted
renameFromRoot('kibana.defaultAppId', 'kibana_legacy.defaultAppId', { silent: true }),
(completeConfig, rootPath, addDeprecation) => {
if (
get(completeConfig, 'kibana.defaultAppId') === undefined &&
get(completeConfig, 'kibana_legacy.defaultAppId') === undefined
) {
return;
}
addDeprecation({
message: `kibana.defaultAppId is deprecated and will be removed in 8.0. Please use the \`defaultRoute\` advanced setting instead`,
correctiveActions: {
manualSteps: [
'Go to Stack Management > Advanced Settings',
'Update the "defaultRoute" setting under the General section',
'Remove "kibana.defaultAppId" from the kibana.yml config file',
],
},
});
},
],
};
class Plugin {
public setup(core: CoreSetup) {}
public start(core: CoreStart) {}
}
export const plugin = () => new Plugin();

View file

@ -6,6 +6,5 @@
"owner": {
"name": "Vis Editors",
"githubTeam": "kibana-vis-editors"
},
"requiredPlugins": ["kibanaLegacy"]
}
}

View file

@ -0,0 +1,54 @@
/*
* 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 and the Server Side Public License, v 1; you may not use this file except
* in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1.
*/
import type { Location } from 'history';
import type { AppMountParameters, CoreSetup, ScopedHistory } from 'kibana/public';
import { coreMock } from '../../../../core/public/mocks';
import type { UrlForwardingStart } from '../plugin';
import { createLegacyUrlForwardApp } from './forward_app';
function createAppMountParams(hash: string): AppMountParameters {
return {
history: {
location: {
hash,
} as Location<unknown>,
} as ScopedHistory,
} as AppMountParameters;
}
describe('forward_app', () => {
let coreSetup: CoreSetup<{}, UrlForwardingStart>;
let coreStart: ReturnType<typeof coreMock['createStart']>;
beforeEach(() => {
coreSetup = coreMock.createSetup({ basePath: '/base/path' });
coreStart = coreMock.createStart({ basePath: '/base/path' });
coreSetup.getStartServices = () => Promise.resolve([coreStart, {}, {} as any]);
});
it('should forward to defaultRoute if hash is not a known redirect', async () => {
coreStart.uiSettings.get.mockImplementation((key) => {
if (key === 'defaultRoute') return '/app/defaultApp';
throw new Error('Mock implementation missing');
});
const app = createLegacyUrlForwardApp(coreSetup, [
{ legacyAppId: 'discover', newAppId: 'discover', rewritePath: (p) => p },
]);
await app.mount(createAppMountParams('#/foobar'));
expect(coreStart.application.navigateToUrl).toHaveBeenCalledWith('/base/path/app/defaultApp');
});
it('should not forward to defaultRoute if hash path is a known redirect', async () => {
const app = createLegacyUrlForwardApp(coreSetup, [
{ legacyAppId: 'discover', newAppId: 'discover', rewritePath: (p) => p },
]);
await app.mount(createAppMountParams('#/discover'));
expect(coreStart.application.navigateToUrl).not.toHaveBeenCalled();
});
});

View file

@ -23,23 +23,18 @@ export const createLegacyUrlForwardApp = (
async mount(params: AppMountParameters) {
const hash = params.history.location.hash.substr(1);
if (!hash) {
const [, , kibanaLegacyStart] = await core.getStartServices();
kibanaLegacyStart.navigateToDefaultApp();
}
const [
{
application,
uiSettings,
http: { basePath },
},
] = await core.getStartServices();
const result = await navigateToLegacyKibanaUrl(hash, forwards, basePath, application);
if (!result.navigated) {
const [, , kibanaLegacyStart] = await core.getStartServices();
kibanaLegacyStart.navigateToDefaultApp();
const { navigated } = navigateToLegacyKibanaUrl(hash, forwards, basePath, application);
if (!navigated) {
const defaultRoute = uiSettings.get<string>('defaultRoute');
application.navigateToUrl(basePath.prepend(defaultRoute));
}
return () => {};

View file

@ -17,7 +17,6 @@ const createSetupContract = (): Setup => ({
const createStartContract = (): Start => ({
getForwards: jest.fn(),
navigateToDefaultApp: jest.fn(),
navigateToLegacyKibanaUrl: jest.fn(),
});

View file

@ -1,39 +0,0 @@
/*
* 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 and the Server Side Public License, v 1; you may not use this file except
* in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1.
*/
import { ApplicationStart, IBasePath } from 'kibana/public';
import { ForwardDefinition } from './plugin';
export function navigateToDefaultApp(
defaultAppId: string,
forwards: ForwardDefinition[],
application: ApplicationStart,
basePath: IBasePath,
currentAppId: string | undefined,
overwriteHash: boolean
) {
// navigate to the respective path in the legacy kibana plugin by default (for unmigrated plugins)
let targetAppId = 'kibana';
let targetAppPath = `#/${defaultAppId}`;
// try to find an existing redirect for the target path if possible
// this avoids having to load the legacy app just to get redirected to a core application again afterwards
const relevantForward = forwards.find((forward) => defaultAppId.startsWith(forward.legacyAppId));
if (relevantForward) {
targetAppPath = relevantForward.rewritePath(`/${defaultAppId}`);
targetAppId = relevantForward.newAppId;
}
// when the correct app is already loaded, just set the hash to the right value
// otherwise use navigateToApp (or setting href in case of kibana app)
if (currentAppId !== targetAppId) {
application.navigateToApp(targetAppId, { path: targetAppPath, replace: true });
} else if (overwriteHash) {
window.location.hash = targetAppPath;
}
}

View file

@ -7,9 +7,6 @@
*/
import { CoreStart, CoreSetup } from 'kibana/public';
import { KibanaLegacyStart } from 'src/plugins/kibana_legacy/public';
import { Subscription } from 'rxjs';
import { navigateToDefaultApp } from './navigate_to_default_app';
import { createLegacyUrlForwardApp } from './forward_app';
import { navigateToLegacyKibanaUrl } from './forward_app/navigate_to_legacy_kibana_url';
@ -21,8 +18,6 @@ export interface ForwardDefinition {
export class UrlForwardingPlugin {
private forwardDefinitions: ForwardDefinition[] = [];
private currentAppId: string | undefined;
private currentAppIdSubscription: Subscription | undefined;
public setup(core: CoreSetup<{}, UrlForwardingStart>) {
core.application.register(createLegacyUrlForwardApp(core, this.forwardDefinitions));
@ -71,30 +66,8 @@ export class UrlForwardingPlugin {
};
}
public start(
{ application, http: { basePath }, uiSettings }: CoreStart,
{ kibanaLegacy }: { kibanaLegacy: KibanaLegacyStart }
) {
this.currentAppIdSubscription = application.currentAppId$.subscribe((currentAppId) => {
this.currentAppId = currentAppId;
});
public start({ application, http: { basePath } }: CoreStart) {
return {
/**
* Navigates to the app defined as kibana.defaultAppId.
* This takes redirects into account and uses the right mechanism to navigate.
*/
navigateToDefaultApp: (
{ overwriteHash }: { overwriteHash: boolean } = { overwriteHash: true }
) => {
navigateToDefaultApp(
kibanaLegacy.config.defaultAppId,
this.forwardDefinitions,
application,
basePath,
this.currentAppId,
overwriteHash
);
},
/**
* Resolves the provided hash using the registered forwards and navigates to the target app.
* If a navigation happened, `{ navigated: true }` will be returned.
@ -111,12 +84,6 @@ export class UrlForwardingPlugin {
getForwards: () => this.forwardDefinitions,
};
}
public stop() {
if (this.currentAppIdSubscription) {
this.currentAppIdSubscription.unsubscribe();
}
}
}
export type UrlForwardingSetup = ReturnType<UrlForwardingPlugin['setup']>;

View file

@ -26,7 +26,7 @@ export default function ({ getService, getPageObjects }) {
});
it('clicking on console on homepage should take you to console app', async () => {
await PageObjects.common.navigateToUrl('home');
await PageObjects.common.navigateToApp('home');
await testSubjects.click('homeDevTools');
const url = await browser.getCurrentUrl();
expect(url.includes('/app/dev_tools#/console')).to.be(true);