Skip to content

Commit 405f556

Browse files
authored
Merge pull request #430 from Couchbase-Ecosystem/DA-597-add-sdk-doctor-to-vs-code-extension
DA-597 add sdk doctor to vs code extension
2 parents 48e6768 + 01d5cee commit 405f556

9 files changed

Lines changed: 571 additions & 231 deletions

File tree

package-lock.json

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
"name": "vscode-couchbase",
33
"displayName": "Couchbase",
44
"description": "",
5-
"version": "2.1.6",
5+
"version": "2.1.7",
66
"engines": {
77
"vscode": "^1.63.1"
88
},
@@ -1323,5 +1323,4 @@
13231323
}
13241324
]
13251325
}
1326-
}
1327-
1326+
}

src/handlers/dependenciesUtil.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,9 @@ class DependenciesUtil {
1818
public static readonly CBIMPORT_EXPORT_VERSION =
1919
config.CBIMPORT_EXPORT_VERSION;
2020

21+
public static readonly SDK_DOCTOR_VERSION = config.SDK_DOCTOR_VERSION;
22+
public static readonly SDK_DOCTOR_KEY = config.SDK_DOCTOR_KEY;
23+
2124
public static createVersioningFile(directoryPath: string): void {
2225
const filePath = path.join(
2326
directoryPath,

src/handlers/handleCLIDownloader.ts

Lines changed: 76 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ class DependenciesDownloader {
2121
private readonly TOOL_IMPORT_EXPORT = "import_export";
2222
private readonly ALL_TOOLS = "all_tools";
2323
private readonly TOOL_MDB_MIGRATE = "cb_migrate";
24+
private readonly SDK_DOCTOR = "sdk-doctor";
2425

2526
private getToolInstallPath(toolKey: string): string {
2627
if (toolKey === this.TOOL_SHELL) {
@@ -31,14 +32,18 @@ class DependenciesDownloader {
3132
return "cbmigrate";
3233
} else if (toolKey === this.ALL_TOOLS) {
3334
return "cbtools";
34-
} else {
35+
} else if(toolKey === this.SDK_DOCTOR) {
36+
return "sdk-doctor";
37+
}
38+
else {
3539
throw new Error("Not Implemented yet");
3640
}
3741
}
3842

3943
private getToolsMap(toolKey: string, os: string): Map<CBToolsType, string> {
4044
const suffix = os.includes("mac") || os.includes("linux") ? "" : ".exe";
4145
const pathPrefix = "bin" + path.sep;
46+
console.log(toolKey);
4247

4348
const map = new Map<CBToolsType, string>();
4449

@@ -64,6 +69,8 @@ class DependenciesDownloader {
6469
CBToolsType.MCTIMINGS,
6570
path.join(pathPrefix, "mctimings" + suffix)
6671
);
72+
} else if (toolKey === this.SDK_DOCTOR) {
73+
map.set(CBToolsType.SDK_DOCTOR, 'sdk-doctor'+ suffix);
6774
} else {
6875
throw new Error("Not implemented yet");
6976
}
@@ -80,6 +87,38 @@ class DependenciesDownloader {
8087
}
8188
public getDownloadList(os: string): Map<string, ToolSpec> {
8289
const map = new Map<string, ToolSpec>();
90+
// SDK Doctor Download configuration
91+
if (os === OSUtil.MACOS_64 || os === OSUtil.MACOS_ARM) {
92+
map.set(
93+
this.SDK_DOCTOR,
94+
this.getToolSpec(
95+
"https://intellij-plugin-dependencies.s3.us-east-2.amazonaws.com/sdkdoctor/1.0.8-sdk-doctor-macos.zip",
96+
this.SDK_DOCTOR,
97+
os
98+
)
99+
);
100+
} else if (os === OSUtil.WINDOWS_64 || os === OSUtil.WINDOWS_ARM) {
101+
map.set(
102+
this.SDK_DOCTOR,
103+
this.getToolSpec(
104+
"https://intellij-plugin-dependencies.s3.us-east-2.amazonaws.com/sdkdoctor/1.0.8-sdk-doctor-windows.zip",
105+
this.SDK_DOCTOR,
106+
os
107+
)
108+
);
109+
} else if (os === OSUtil.LINUX_64 || os === OSUtil.LINUX_ARM) {
110+
map.set(
111+
this.SDK_DOCTOR,
112+
this.getToolSpec(
113+
"https://intellij-plugin-dependencies.s3.us-east-2.amazonaws.com/sdkdoctor/1.0.8-sdk-doctor-linux.zip",
114+
this.SDK_DOCTOR,
115+
os
116+
)
117+
);
118+
} else {
119+
throw new Error("OS not supported.");
120+
}
121+
// CB Tools Download configuration
83122
if (os === OSUtil.MACOS_64) {
84123
map.set(
85124
this.TOOL_SHELL,
@@ -283,7 +322,7 @@ class DependenciesDownloader {
283322
) {
284323
logger.info("Cleaning up older tools versions if update required");
285324
const shell: ToolSpec | undefined = downloads.get(this.TOOL_SHELL);
286-
if (shell == undefined) {
325+
if (shell === undefined) {
287326
return;
288327
}
289328
// Checks if CB shell is installed and requires update by comparing current version of tool with version config value
@@ -307,7 +346,7 @@ class DependenciesDownloader {
307346

308347
}
309348
const cbimport_export: ToolSpec | undefined = downloads.get(this.TOOL_IMPORT_EXPORT);
310-
if (cbimport_export == undefined) {
349+
if (cbimport_export === undefined) {
311350
return;
312351
}
313352
// Checks if CB Import/Export is installed and requires update by comparing current version of tool with version config value
@@ -347,6 +386,7 @@ class DependenciesDownloader {
347386
this.manageShellInstallation(downloads, toolsPath, extensionPath);
348387
this.manageCbMigrateInstallation(downloads, toolsPath, extensionPath);
349388
this.manageDataImportExportInstallation(downloads, toolsPath, extensionPath);
389+
this.manageSdkDoctorInstallation(downloads, toolsPath, extensionPath);
350390
};
351391

352392
private setToolActive(
@@ -524,6 +564,39 @@ class DependenciesDownloader {
524564
}
525565
}
526566

567+
public manageSdkDoctorInstallation(
568+
downloads: Map<string, ToolSpec>,
569+
toolsPath: string,
570+
extensionPath: string
571+
): void {
572+
const sdkDoctor = downloads.get(this.SDK_DOCTOR);
573+
if (sdkDoctor === undefined) {
574+
return;
575+
}
576+
const sdkDoctorPath = path.join(toolsPath, sdkDoctor.getInstallationPath());
577+
const sdkDoctorTool = CBTools.getTool(CBToolsType.SDK_DOCTOR);
578+
const sdkDoctorStatus = sdkDoctorTool.status;
579+
const sdkDoctorDownloadsMap = downloads.get(this.SDK_DOCTOR);
580+
if (sdkDoctorDownloadsMap === undefined) {
581+
return;
582+
}
583+
if (
584+
sdkDoctorStatus === ToolStatus.NOT_AVAILABLE &&
585+
!this.isInstalled(
586+
toolsPath,
587+
sdkDoctorDownloadsMap,
588+
CBToolsType.SDK_DOCTOR
589+
)
590+
) {
591+
logger.info("Downloading SDK Doctor.");
592+
sdkDoctorTool.status = ToolStatus.DOWNLOADING;
593+
this.downloadAndUnzip(sdkDoctorPath, sdkDoctor, extensionPath, DependenciesUtil.SDK_DOCTOR_KEY, DependenciesUtil.SDK_DOCTOR_VERSION);
594+
} else {
595+
logger.debug("SDK Doctor is already installed");
596+
this.setToolActive(ToolStatus.AVAILABLE, sdkDoctorPath, sdkDoctor);
597+
}
598+
}
599+
527600
// This is a test function, keeping this here to check for any specific downloaded CLI tool
528601
/* public runFile(targetDir:string) {
529602
const scriptPath = path.join(targetDir, 'cbsh');

src/handlers/versionConfig.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,4 +8,6 @@ export const config = {
88
CBMIGRATE_VERSION: "2",
99
SHELL_VERSION: "1.0.0",
1010
CBIMPORT_EXPORT_VERSION: "7.6",
11+
SDK_DOCTOR_VERSION: "1.0.8",
12+
SDK_DOCTOR_KEY: "sdk-doctor",
1113
};

src/tools/SDKDocterRunner.ts

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
import * as childProcess from 'child_process';
2+
import { CBTools, ToolStatus, Type } from '../util/DependencyDownloaderUtils/CBTool';
3+
4+
export class SdkDoctorRunner {
5+
static async run(
6+
host: string,
7+
ssl: boolean,
8+
bucket: string,
9+
username: string,
10+
password: string,
11+
outputCallback: (line: string) => void
12+
): Promise<void> {
13+
try {
14+
const sdkDoctorTool = CBTools.getTool(Type.SDK_DOCTOR);
15+
if (sdkDoctorTool.status !== ToolStatus.AVAILABLE) {
16+
throw new Error('SDK Doctor is not available. Please ensure it is installed.');
17+
}
18+
19+
const sdkDoctorExecutable = sdkDoctorTool.path;
20+
const clusterUrl = SdkDoctorRunner.adjustClusterProtocol(host, ssl);
21+
const args = [
22+
'diagnose',
23+
`${clusterUrl}/${bucket}`,
24+
'-u', username,
25+
'-p', password
26+
];
27+
28+
const process = childProcess.spawn(sdkDoctorExecutable, args);
29+
30+
process.stdout.on('data', (data) => {
31+
const lines = data.toString().split('\n');
32+
lines.forEach((line: string) => {
33+
if (line.trim()) {
34+
outputCallback(line.trim());
35+
}
36+
});
37+
});
38+
39+
process.stderr.on('data', (data) => {
40+
console.error(`SDK Doctor error: ${data}`);
41+
});
42+
43+
await new Promise<void>((resolve, reject) => {
44+
process.on('close', (code) => {
45+
if (code !== 0) {
46+
console.warn(`SDK Doctor exited with code ${code}`);
47+
}
48+
resolve();
49+
});
50+
51+
process.on('error', (err) => {
52+
reject(err);
53+
});
54+
});
55+
56+
} catch (error) {
57+
console.error('Error while running the SDK Doctor', error);
58+
}
59+
}
60+
61+
private static adjustClusterProtocol(host: string, ssl: boolean): string {
62+
const protocol = ssl ? 'couchbases://' : 'couchbase://';
63+
return host.startsWith('couchbase://') || host.startsWith('couchbases://')
64+
? host
65+
: `${protocol}${host}`;
66+
}
67+
}

src/util/DependencyDownloaderUtils/CBTool.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,8 @@ export enum Type {
2020
CB_EXPORT = "CB_EXPORT",
2121
CBC_PILLOW_FIGHT = "CBC_PILLOW_FIGHT",
2222
MCTIMINGS = "MCTIMINGS",
23-
CB_MIGRATE = "CB_MIGRATE"
23+
CB_MIGRATE = "CB_MIGRATE",
24+
SDK_DOCTOR = "SDK_DOCTOR"
2425
}
2526

2627

src/util/connections.ts

Lines changed: 41 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ import { CouchbaseRestAPI } from "./apis/CouchbaseRestAPI";
2727
import { hasQueryService, hasSearchService } from "./common";
2828
import { SecretService } from "./secretService";
2929
import ConnectionEvents from "./events/connectionEvents";
30+
import { SdkDoctorRunner } from "../tools/SDKDocterRunner";
3031

3132
export function getConnectionId(connection: IConnection) {
3233
const { url, username } = connection;
@@ -151,6 +152,43 @@ export async function addConnection(clusterConnectionTreeProvider: ClusterConnec
151152
currentPanel.dispose();
152153
break;
153154

155+
case 'testConnection':
156+
const { connectionUrl, username, password, bucketName, isSecure } = message;
157+
if(bucketName === "") {
158+
try {
159+
await connect(connectionUrl, { username: username, password: password, configProfile: 'wanDevelopment' });
160+
currentPanel.webview.postMessage({
161+
command: 'testConnectionResult',
162+
result: 'Connection was successfull!'
163+
});
164+
}
165+
catch (err) {
166+
currentPanel.webview.postMessage({
167+
command: 'testConnectionResult',
168+
result: '[ERRO]: Connection Failed ' + err
169+
});
170+
}
171+
return;
172+
}
173+
const results: string[] = [];
174+
175+
await SdkDoctorRunner.run(
176+
connectionUrl,
177+
isSecure,
178+
bucketName,
179+
username,
180+
password,
181+
(line) => {
182+
results.push(line);
183+
}
184+
);
185+
186+
currentPanel.webview.postMessage({
187+
command: 'testConnectionResult',
188+
result: results.join('\n')
189+
});
190+
break;
191+
154192
default:
155193
console.error('Unrecognized command');
156194
}
@@ -163,10 +201,11 @@ async function handleConnectionError(err: any) {
163201
if (err instanceof AuthenticationFailureError) {
164202
answer = await vscode.window.showErrorMessage(`
165203
Authentication Failed: Please check your credentials and try again \n
166-
If you're still having difficulty, please check out this helpful troubleshooting link`, { modal: true }, "Troubleshoot Link");
204+
or inform a Bucket on Troubleshooting to inspect your connection \n
205+
or check out this helpful troubleshooting link`, { modal: true }, "Troubleshoot Link");
167206
}
168207
else {
169-
answer = await vscode.window.showErrorMessage(`Could not establish a connection \n ${err} \n If you're having difficulty, please check out this helpful troubleshooting link`, { modal: true }, "Troubleshoot Link");
208+
answer = await vscode.window.showErrorMessage(`Could not establish a connection \n ${err} \n Inform a Bucket on Troubleshooting to inspect your connection \n or check out this helpful troubleshooting link`, { modal: true }, "Troubleshoot Link");
170209
}
171210

172211
if (answer === "Troubleshoot Link") {

0 commit comments

Comments
 (0)