Skip to content

Commit

Permalink
[Console] Get ES Config from core (#75406)
Browse files Browse the repository at this point in the history
* Server side changes

- removed console_legacy plugin!
- added new es_config endpoint that returns server side es config
  at the moment this is just the first value in hosts
- Slight refactor to how routes are registered to bring them more
  in line with other ES UI plugins

* Client side update

- Updated the client to not get es host from injected metadata.
  Instead use the new endpoint created server side that returns
  this value
- Added a small README.md regarding the hooks lib and need to
  refactor use of jQuery in console
- Write code to init the es host value on the client once at start
  up in a non-blocking way. If this fails we just use the default
  value of http://localhost:9200 as this powers non-essential
  console functionality (i.e., copy as cURL).

* fix type issue and jest tests

* fix another type issue

* simplify proxy assignment in proxy handler mock

Co-authored-by: Elastic Machine <elasticmachine@users.noreply.github.com>
  • Loading branch information
jloleysens and elasticmachine authored Aug 21, 2020
1 parent 506bf6c commit 7376e4c
Show file tree
Hide file tree
Showing 25 changed files with 451 additions and 164 deletions.
49 changes: 0 additions & 49 deletions src/legacy/core_plugins/console_legacy/index.ts

This file was deleted.

4 changes: 0 additions & 4 deletions src/legacy/core_plugins/console_legacy/package.json

This file was deleted.

29 changes: 29 additions & 0 deletions src/plugins/console/common/types/api_responses.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
/*
* Licensed to Elasticsearch B.V. under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch B.V. licenses this file to you under
* the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/

export interface EsConfigApiResponse {
/**
* This is the first host in the hosts array that Kibana is configured to use
* to communicate with ES.
*
* At the moment this is used to power the copy as cURL functionality in Console
* to complete the host portion of the URL.
*/
host?: string;
}
Original file line number Diff line number Diff line change
Expand Up @@ -67,9 +67,8 @@ const inputId = 'ConAppInputTextarea';

function EditorUI({ initialTextValue }: EditorProps) {
const {
services: { history, notifications, settings: settingsService },
services: { history, notifications, settings: settingsService, esHostService },
docLinkVersion,
elasticsearchUrl,
} = useServicesContext();

const { settings } = useEditorReadContext();
Expand Down Expand Up @@ -232,7 +231,7 @@ function EditorUI({ initialTextValue }: EditorProps) {
<EuiFlexItem>
<ConsoleMenu
getCurl={() => {
return editorInstanceRef.current!.getRequestsAsCURL(elasticsearchUrl);
return editorInstanceRef.current!.getRequestsAsCURL(esHostService.getHost());
}}
getDocumentation={() => {
return getDocumentation(editorInstanceRef.current!, docLinkVersion);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,21 +17,27 @@
* under the License.
*/
import { notificationServiceMock } from '../../../../../core/public/mocks';
import { httpServiceMock } from '../../../../../core/public/mocks';

import { HistoryMock } from '../../services/history.mock';
import { SettingsMock } from '../../services/settings.mock';
import { StorageMock } from '../../services/storage.mock';
import { createApi, createEsHostService } from '../lib';

import { ContextValue } from './services_context';

export const serviceContextMock = {
create: (): ContextValue => {
const storage = new StorageMock({} as any, 'test');
const http = httpServiceMock.createSetupContract();
const api = createApi({ http });
const esHostService = createEsHostService({ api });
(storage.keys as jest.Mock).mockImplementation(() => []);
return {
elasticsearchUrl: 'test',
services: {
trackUiMetric: { count: () => {}, load: () => {} },
storage,
esHostService,
settings: new SettingsMock(storage),
history: new HistoryMock(storage),
notifications: notificationServiceMock.createSetupContract(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,22 +17,25 @@
* under the License.
*/

import React, { createContext, useContext } from 'react';
import React, { createContext, useContext, useEffect } from 'react';
import { NotificationsSetup } from 'kibana/public';
import { History, Storage, Settings } from '../../services';
import { History, Settings, Storage } from '../../services';
import { ObjectStorageClient } from '../../../common/types';
import { MetricsTracker } from '../../types';
import { EsHostService } from '../lib';

interface ContextServices {
history: History;
storage: Storage;
settings: Settings;
notifications: NotificationsSetup;
objectStorageClient: ObjectStorageClient;
trackUiMetric: MetricsTracker;
esHostService: EsHostService;
}

export interface ContextValue {
services: {
history: History;
storage: Storage;
settings: Settings;
notifications: NotificationsSetup;
objectStorageClient: ObjectStorageClient;
trackUiMetric: MetricsTracker;
};
elasticsearchUrl: string;
services: ContextServices;
docLinkVersion: string;
}

Expand All @@ -44,6 +47,11 @@ interface ContextProps {
const ServicesContext = createContext<ContextValue>(null as any);

export function ServicesContextProvider({ children, value }: ContextProps) {
useEffect(() => {
// Fire and forget, we attempt to init the host service once.
value.services.esHostService.init();
}, [value.services.esHostService]);

return <ServicesContext.Provider value={value}>{children}</ServicesContext.Provider>;
}

Expand Down
5 changes: 5 additions & 0 deletions src/plugins/console/public/application/hooks/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
## Notes

* Do not add any code directly to this directory. This code should be moved to the neighbouring `lib` directory to be in line with future ES UI plugin patterns.

* The `es.send` method uses $.ajax under the hood and needs to be refactored to use the new platform-provided http client.
11 changes: 7 additions & 4 deletions src/plugins/console/public/application/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,19 +19,20 @@

import React from 'react';
import { render, unmountComponentAtNode } from 'react-dom';
import { NotificationsSetup } from 'src/core/public';
import { HttpSetup, NotificationsSetup } from 'src/core/public';
import { ServicesContextProvider, EditorContextProvider, RequestContextProvider } from './contexts';
import { Main } from './containers';
import { createStorage, createHistory, createSettings } from '../services';
import * as localStorageObjectClient from '../lib/local_storage_object_client';
import { createUsageTracker } from '../services/tracker';
import { UsageCollectionSetup } from '../../../usage_collection/public';
import { createApi, createEsHostService } from './lib';

export interface BootDependencies {
http: HttpSetup;
docLinkVersion: string;
I18nContext: any;
notifications: NotificationsSetup;
elasticsearchUrl: string;
usageCollection?: UsageCollectionSetup;
element: HTMLElement;
}
Expand All @@ -40,9 +41,9 @@ export function renderApp({
I18nContext,
notifications,
docLinkVersion,
elasticsearchUrl,
usageCollection,
element,
http,
}: BootDependencies) {
const trackUiMetric = createUsageTracker(usageCollection);
trackUiMetric.load('opened_app');
Expand All @@ -54,14 +55,16 @@ export function renderApp({
const history = createHistory({ storage });
const settings = createSettings({ storage });
const objectStorageClient = localStorageObjectClient.create(storage);
const api = createApi({ http });
const esHostService = createEsHostService({ api });

render(
<I18nContext>
<ServicesContextProvider
value={{
elasticsearchUrl,
docLinkVersion,
services: {
esHostService,
storage,
history,
settings,
Expand Down
39 changes: 39 additions & 0 deletions src/plugins/console/public/application/lib/api.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
/*
* Licensed to Elasticsearch B.V. under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch B.V. licenses this file to you under
* the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/

import { HttpSetup } from 'kibana/public';
import { EsConfigApiResponse } from '../../../common/types/api_responses';
import { sendRequest } from '../../shared_imports';

interface Dependencies {
http: HttpSetup;
}

export type Api = ReturnType<typeof createApi>;

export const createApi = ({ http }: Dependencies) => {
return {
getEsConfig: () => {
return sendRequest<EsConfigApiResponse>(http, {
path: '/api/console/es_config',
method: 'get',
});
},
};
};
54 changes: 54 additions & 0 deletions src/plugins/console/public/application/lib/es_host_service.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
/*
* Licensed to Elasticsearch B.V. under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch B.V. licenses this file to you under
* the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/

import { Api } from './api';

/**
* Very simple state for holding the current ES host.
*
* This is used to power the copy as cURL functionality.
*/
export class EsHostService {
private host = 'http://localhost:9200';

constructor(private readonly api: Api) {}

private setHost(host: string): void {
this.host = host;
}

/**
* Initialize the host value based on the value set on the server.
*
* This call is necessary because this value can only be retrieved at
* runtime.
*/
public async init() {
const { data } = await this.api.getEsConfig();
if (data && data.host) {
this.setHost(data.host);
}
}

public getHost(): string {
return this.host;
}
}

export const createEsHostService = ({ api }: { api: Api }) => new EsHostService(api);
21 changes: 21 additions & 0 deletions src/plugins/console/public/application/lib/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
/*
* Licensed to Elasticsearch B.V. under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch B.V. licenses this file to you under
* the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/

export { createApi, Api } from './api';
export { createEsHostService, EsHostService } from './es_host_service';
10 changes: 2 additions & 8 deletions src/plugins/console/public/plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ import { AppSetupUIPluginDependencies } from './types';

export class ConsoleUIPlugin implements Plugin<void, void, AppSetupUIPluginDependencies> {
public setup(
{ notifications, getStartServices }: CoreSetup,
{ notifications, getStartServices, http }: CoreSetup,
{ devTools, home, usageCollection }: AppSetupUIPluginDependencies
) {
home.featureCatalogue.register({
Expand Down Expand Up @@ -53,23 +53,17 @@ export class ConsoleUIPlugin implements Plugin<void, void, AppSetupUIPluginDepen
const [core] = await getStartServices();

const {
injectedMetadata,
i18n: { Context: I18nContext },
docLinks: { DOC_LINK_VERSION },
} = core;

const { renderApp } = await import('./application');

const elasticsearchUrl = injectedMetadata.getInjectedVar(
'elasticsearchUrl',
'http://localhost:9200'
) as string;

return renderApp({
http,
docLinkVersion: DOC_LINK_VERSION,
I18nContext,
notifications,
elasticsearchUrl,
usageCollection,
element,
});
Expand Down
Loading

0 comments on commit 7376e4c

Please sign in to comment.