Skip to content

Commit 77b0105

Browse files
spacedragonzfy0701
authored andcommitted
[Code] compute url for language server plugin (#32644)
1 parent 71f14ec commit 77b0105

File tree

6 files changed

+105
-66
lines changed

6 files changed

+105
-66
lines changed

x-pack/plugins/code/common/language_server.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,4 +20,6 @@ export interface LanguageServer {
2020
version?: string;
2121
build?: string;
2222
status?: LanguageServerStatus;
23+
downloadUrl?: any;
24+
pluginName?: string;
2325
}

x-pack/plugins/code/public/components/admin_page/language_server_tab.tsx

Lines changed: 56 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,9 @@
66

77
import {
88
EuiButton,
9+
EuiCodeBlock,
910
EuiFlexGroup,
1011
EuiFlexItem,
11-
EuiLink,
12-
EuiLoadingSpinner,
1312
EuiModal,
1413
EuiModalBody,
1514
EuiModalFooter,
@@ -18,18 +17,18 @@ import {
1817
EuiOverlayMask,
1918
EuiPanel,
2019
EuiSpacer,
20+
EuiTabbedContent,
2121
EuiText,
2222
EuiTextColor,
2323
} from '@elastic/eui';
2424
import React from 'react';
2525
import { connect } from 'react-redux';
2626
import styled from 'styled-components';
27+
import { InstallationType } from '../../../common/installation';
2728
import { LanguageServer, LanguageServerStatus } from '../../../common/language_server';
2829
import { requestInstallLanguageServer } from '../../actions/language_server';
2930
import { RootState } from '../../reducers';
3031
import { JavaIcon, TypeScriptIcon } from '../shared/icons';
31-
const JAVA_URL =
32-
'https://download.elasticsearch.org/code/java-langserver/snapshot/java_languageserver-1.0.0-SNAPSHOT-darwin.zip';
3332

3433
const LanguageServerState = styled(EuiTextColor)`
3534
color: ${props => props.color};
@@ -55,25 +54,17 @@ const LanguageServerLi = (props: {
5554
let state = null;
5655
if (status === LanguageServerStatus.RUNNING) {
5756
state = <LanguageServerState>Running ...</LanguageServerState>;
58-
button = (
59-
<EuiButton size="s" color="secondary" onClick={onInstallClick}>
60-
Re-install
61-
</EuiButton>
62-
);
6357
} else if (status === LanguageServerStatus.NOT_INSTALLED) {
6458
state = <LanguageServerState color={'subdued'}>Not Installed</LanguageServerState>;
65-
button = props.loading ? (
66-
<EuiButton size="s" color="secondary">
67-
<EuiLoadingSpinner size="s" />
68-
Installing
69-
</EuiButton>
70-
) : (
59+
} else if (status === LanguageServerStatus.READY) {
60+
state = <LanguageServerState color={'subdued'}>Installed</LanguageServerState>;
61+
}
62+
if (props.languageServer.installationType === InstallationType.Plugin) {
63+
button = (
7164
<EuiButton size="s" color="secondary" onClick={onInstallClick}>
72-
Install
65+
Setup
7366
</EuiButton>
7467
);
75-
} else if (status === LanguageServerStatus.READY) {
76-
state = <LanguageServerState color={'subdued'}>Installed</LanguageServerState>;
7768
}
7869
return (
7970
<EuiFlexItem>
@@ -108,6 +99,7 @@ interface State {
10899
showingInstruction: boolean;
109100
name?: string;
110101
url?: string;
102+
pluginName?: string;
111103
}
112104

113105
class AdminLanguageSever extends React.PureComponent<Props, State> {
@@ -116,22 +108,22 @@ class AdminLanguageSever extends React.PureComponent<Props, State> {
116108
this.state = { showingInstruction: false };
117109
}
118110

119-
public toggleInstruction = (showingInstruction: boolean, name?: string, url?: string) => {
120-
this.setState({ showingInstruction, name, url });
111+
public toggleInstruction = (
112+
showingInstruction: boolean,
113+
name?: string,
114+
url?: string,
115+
pluginName?: string
116+
) => {
117+
this.setState({ showingInstruction, name, url, pluginName });
121118
};
122119

123120
public render() {
124121
const languageServers = this.props.languageServers.map(ls => (
125122
<LanguageServerLi
126123
languageServer={ls}
127124
key={ls.name}
128-
requestInstallLanguageServer={
129-
() =>
130-
this.toggleInstruction(
131-
true,
132-
ls.name,
133-
JAVA_URL
134-
) /*this.props.requestInstallLanguageServer*/
125+
requestInstallLanguageServer={() =>
126+
this.toggleInstruction(true, ls.name, ls.downloadUrl, ls.pluginName)
135127
}
136128
loading={this.props.installLoading[ls.name]}
137129
/>
@@ -156,6 +148,7 @@ class AdminLanguageSever extends React.PureComponent<Props, State> {
156148
<LanguageServerInstruction
157149
show={this.state.showingInstruction}
158150
name={this.state.name!}
151+
pluginName={this.state.pluginName!}
159152
url={this.state.url!}
160153
close={() => this.toggleInstruction(false)}
161154
/>
@@ -164,36 +157,57 @@ class AdminLanguageSever extends React.PureComponent<Props, State> {
164157
}
165158
}
166159

160+
const SupportedOS = [
161+
{ id: 'win', name: 'Windows' },
162+
{ id: 'linux', name: 'Linux' },
163+
{ id: 'darwin', name: 'macOS' },
164+
];
165+
167166
const LanguageServerInstruction = (props: {
168167
name: string;
168+
pluginName: string;
169169
url: string;
170170
show: boolean;
171171
close: () => void;
172172
}) => {
173+
const tabs = SupportedOS.map(({ id, name }) => {
174+
const url = props.url ? props.url.replace('$OS', id) : '';
175+
const installCode = `bin/kibana-plugin install ${url}`;
176+
return {
177+
id,
178+
name,
179+
content: (
180+
<EuiText grow={false}>
181+
<h3>Install</h3>
182+
<p>
183+
Stop your kibana Code node, then use the following command to install ${props.name}{' '}
184+
Language Server plugin:
185+
<EuiCodeBlock language="shell">{installCode}</EuiCodeBlock>
186+
</p>
187+
<h3>Uninstall</h3>
188+
<p>
189+
Stop your kibana Code node, then use the following command to remove ${props.name}{' '}
190+
Language Server plugin:
191+
<pre>
192+
<code>bin/kibana-plugin remove {props.pluginName}</code>
193+
</pre>
194+
</p>
195+
</EuiText>
196+
),
197+
};
198+
});
199+
173200
return (
174201
<React.Fragment>
175202
{' '}
176203
{props.show && (
177204
<EuiOverlayMask>
178-
<EuiModal onClose={props.close}>
205+
<EuiModal onClose={props.close} maxWidth={false}>
179206
<EuiModalHeader>
180207
<EuiModalHeaderTitle>Install Instruction</EuiModalHeaderTitle>
181208
</EuiModalHeader>
182209
<EuiModalBody>
183-
<EuiText grow={false}>
184-
<h3>Download</h3>
185-
<p>
186-
Download {props.name} language server plugin from
187-
<EuiLink href={props.url}> here.</EuiLink>
188-
</p>
189-
<h3>Install</h3>
190-
<p>
191-
Stop your kibana code node. Install it using kibana-plugin command.
192-
<pre>
193-
<code>bin/kibana-plugin install {JAVA_URL}</code>
194-
</pre>
195-
</p>
196-
</EuiText>
210+
<EuiTabbedContent tabs={tabs} initialSelectedTab={tabs[1]} size={'m'} />
197211
</EuiModalBody>
198212
<EuiModalFooter>
199213
<EuiButton onClick={props.close} fill>

x-pack/plugins/code/server/lsp/install_manager.test.ts

Lines changed: 24 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -13,13 +13,13 @@ import path from 'path';
1313
import tar from 'tar-fs';
1414
import URL from 'url';
1515
import zlib from 'zlib';
16-
import {LanguageServers} from './language_servers';
17-
import {InstallManager} from "./install_manager";
18-
import {ServerOptions} from "../server_options";
16+
import { LanguageServers } from './language_servers';
17+
import { InstallManager } from "./install_manager";
18+
import { ServerOptions } from "../server_options";
1919
import rimraf from 'rimraf';
20-
import {LanguageServerStatus} from '../../common/language_server';
21-
import {Server} from 'hapi';
22-
import {InstallationType} from "../../common/installation";
20+
import { LanguageServerStatus } from '../../common/language_server';
21+
import { Server } from 'hapi';
22+
import { InstallationType } from "../../common/installation";
2323

2424
const LANG_SERVER_NAME = 'Java';
2525
const langSrvDef = LanguageServers.find(l => l.name === LANG_SERVER_NAME)!;
@@ -34,6 +34,18 @@ const options: ServerOptions = {
3434
} as ServerOptions;
3535

3636
const server = new Server();
37+
server.config = () => {
38+
return {
39+
get(key: string): any {
40+
if (key === 'pkg.version') {
41+
return '8.0.0';
42+
}
43+
},
44+
has(key: string): boolean {
45+
return key === 'pkg.version';
46+
}
47+
}
48+
}
3749

3850
const manager = new InstallManager(server, options);
3951

@@ -53,7 +65,7 @@ beforeAll(async () => {
5365

5466
});
5567
beforeEach(() => {
56-
const downloadUrl = URL.parse(langSrvDef.downloadUrl!(langSrvDef));
68+
const downloadUrl = URL.parse(langSrvDef.downloadUrl!(langSrvDef, server.config().get('pkg.version')));
5769
nock.cleanAll();
5870
// mimic github's behavior, redirect to a s3 address
5971
nock(`${downloadUrl.protocol}//${downloadUrl.host!}`)
@@ -77,9 +89,9 @@ afterAll(() => {
7789
nock.cleanAll();
7890
rimraf.sync(fakeTestDir);
7991
});
80-
8192

82-
test('it can download a package', async() => {
93+
94+
test('it can download a package', async () => {
8395
const manager = new InstallManager(server, options);
8496
langSrvDef.installationType = InstallationType.Download
8597
const p = await manager.downloadFile(langSrvDef);
@@ -88,10 +100,10 @@ test('it can download a package', async() => {
88100
expect(fs.statSync(p).size).toBe(fs.statSync(fakePackageFile).size)
89101
});
90102

91-
test('it can install language server', async() => {
103+
test('it can install language server', async () => {
92104
expect(manager.status(langSrvDef)).toBe(LanguageServerStatus.NOT_INSTALLED);
93105
langSrvDef.installationType = InstallationType.Download
94-
const installPromise = manager.install(langSrvDef);
106+
const installPromise = manager.install(langSrvDef);
95107
expect(manager.status(langSrvDef)).toBe(LanguageServerStatus.INSTALLING);
96108
await installPromise;
97109
expect(manager.status(langSrvDef)).toBe(LanguageServerStatus.READY);
@@ -102,7 +114,7 @@ test('it can install language server', async() => {
102114
});
103115

104116

105-
test('install language server by plugin', async() => {
117+
test('install language server by plugin', async () => {
106118
langSrvDef.installationType = InstallationType.Plugin
107119
expect(manager.status(langSrvDef)).toBe(LanguageServerStatus.NOT_INSTALLED);
108120
const testDir = path.join(fakeTestDir, 'test_plugin');

x-pack/plugins/code/server/lsp/install_manager.ts

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,10 @@ export class InstallManager {
8686
}
8787

8888
public async downloadFile(def: LanguageServerDefinition): Promise<string> {
89-
const url = typeof def.downloadUrl === 'function' ? def.downloadUrl(def) : def.downloadUrl;
89+
const url =
90+
typeof def.downloadUrl === 'function'
91+
? def.downloadUrl(def, this.getKibanaVersion())
92+
: def.downloadUrl;
9093

9194
const res = await fetch(url!);
9295
if (!res.ok) {
@@ -150,14 +153,22 @@ export class InstallManager {
150153
}
151154
return undefined;
152155
} else {
153-
let version = def.version!;
154-
if (def.build) {
155-
version += '-' + def.build;
156+
let version = def.version;
157+
if (version) {
158+
if (def.build) {
159+
version += '-' + def.build;
160+
}
161+
} else {
162+
version = this.getKibanaVersion();
156163
}
157164
return path.join(this.basePath, def.installationFolderName || def.name, version);
158165
}
159166
}
160167

168+
private getKibanaVersion(): string {
169+
return this.server.config().get('pkg.version');
170+
}
171+
161172
private async unPack(packageFile: string, def: LanguageServerDefinition) {
162173
const dest = this.installationPath(def)!;
163174
this.sendEvent({

x-pack/plugins/code/server/lsp/language_servers.ts

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ export interface LanguageServerDefinition extends LanguageServer {
1616
builtinWorkspaceFolders: boolean;
1717
launcher: LauncherConstructor;
1818
installationFolderName?: string;
19-
downloadUrl?: (lang: LanguageServerDefinition) => string | string;
19+
downloadUrl?: (lang: LanguageServerDefinition, version: string) => string | string;
2020
embedPath?: string;
2121
installationPluginName?: string;
2222
}
@@ -38,14 +38,10 @@ export const JAVA: LanguageServerDefinition = {
3838
languages: ['java'],
3939
launcher: JavaLauncher,
4040
installationType: InstallationType.Plugin,
41-
installationPluginName: 'javaLanguageServer',
41+
installationPluginName: 'java-langserver',
4242
installationFolderName: 'jdt',
43-
version: '1.0.0-SNAPSHOT',
44-
build: '201812040656',
45-
downloadUrl: (lang: LanguageServerDefinition) =>
46-
`https://github.com/Poytr1/eclipse.jdt.ls/releases/download/v${
47-
lang.version
48-
}/jdt-language-server-${lang.version}-${lang.build}.tar.gz`,
43+
downloadUrl: (lang: LanguageServerDefinition, version: string) =>
44+
`https://download.elasticsearch.org/code/java-langserver/release/java-langserver-${version}-$OS.zip`,
4945
};
5046
export const GO: LanguageServerDefinition = {
5147
name: 'Go',

x-pack/plugins/code/server/routes/install.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,13 +16,17 @@ export function installRoute(
1616
lspService: LspService,
1717
installManager: InstallManager
1818
) {
19+
const kibanaVersion = server.config().get('pkg.version') as string;
1920
const status = (def: LanguageServerDefinition) => ({
2021
name: def.name,
2122
status: lspService.languageServerStatus(def.name),
2223
version: def.version,
2324
build: def.build,
2425
languages: def.languages,
2526
installationType: def.installationType,
27+
downloadUrl:
28+
typeof def.downloadUrl === 'function' ? def.downloadUrl(def, kibanaVersion) : def.downloadUrl,
29+
pluginName: def.pluginName,
2630
});
2731

2832
server.route({

0 commit comments

Comments
 (0)