mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-02-17 02:51:36 -05:00
Add STS root folder override (#16927)
* Add STS root folder override * Display message to user * Show once for any service
This commit is contained in:
@@ -4,7 +4,7 @@
|
|||||||
*--------------------------------------------------------------------------------------------*/
|
*--------------------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
import { SqlOpsDataClient, ClientOptions, SqlOpsFeature } from 'dataprotocol-client';
|
import { SqlOpsDataClient, ClientOptions, SqlOpsFeature } from 'dataprotocol-client';
|
||||||
import { IConfig, ServerProvider } from '@microsoft/ads-service-downloader';
|
import { IConfig } from '@microsoft/ads-service-downloader';
|
||||||
import { ServerOptions, RPCMessageType, ClientCapabilities, ServerCapabilities, TransportKind } from 'vscode-languageclient';
|
import { ServerOptions, RPCMessageType, ClientCapabilities, ServerCapabilities, TransportKind } from 'vscode-languageclient';
|
||||||
import { Disposable } from 'vscode';
|
import { Disposable } from 'vscode';
|
||||||
import * as UUID from 'vscode-languageclient/lib/utils/uuid';
|
import * as UUID from 'vscode-languageclient/lib/utils/uuid';
|
||||||
@@ -77,17 +77,15 @@ export class CredentialStore {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public start() {
|
public async start(): Promise<void> {
|
||||||
let serverdownloader = new ServerProvider(this._config);
|
|
||||||
let clientOptions: ClientOptions = {
|
let clientOptions: ClientOptions = {
|
||||||
providerId: Constants.providerId,
|
providerId: Constants.providerId,
|
||||||
features: [CredentialsFeature]
|
features: [CredentialsFeature]
|
||||||
};
|
};
|
||||||
return serverdownloader.getOrDownloadServer().then(e => {
|
const serverPath = await Utils.getOrDownloadServer(this._config);
|
||||||
let serverOptions = this.generateServerOptions(e);
|
const serverOptions = this.generateServerOptions(serverPath);
|
||||||
this._client = new SqlOpsDataClient(Constants.serviceName, serverOptions, clientOptions);
|
this._client = new SqlOpsDataClient(Constants.serviceName, serverOptions, clientOptions);
|
||||||
this._client.start();
|
this._client.start();
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
dispose() {
|
dispose() {
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
*--------------------------------------------------------------------------------------------*/
|
*--------------------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
import * as azdata from 'azdata';
|
import * as azdata from 'azdata';
|
||||||
import { IConfig, ServerProvider } from '@microsoft/ads-service-downloader';
|
import { IConfig } from '@microsoft/ads-service-downloader';
|
||||||
import { SqlOpsDataClient, SqlOpsFeature, ClientOptions } from 'dataprotocol-client';
|
import { SqlOpsDataClient, SqlOpsFeature, ClientOptions } from 'dataprotocol-client';
|
||||||
import { ServerCapabilities, ClientCapabilities, RPCMessageType, ServerOptions, TransportKind } from 'vscode-languageclient';
|
import { ServerCapabilities, ClientCapabilities, RPCMessageType, ServerOptions, TransportKind } from 'vscode-languageclient';
|
||||||
import * as UUID from 'vscode-languageclient/lib/utils/uuid';
|
import * as UUID from 'vscode-languageclient/lib/utils/uuid';
|
||||||
@@ -81,17 +81,15 @@ export class AzureResourceProvider {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public start() {
|
public async start(): Promise<void> {
|
||||||
let serverdownloader = new ServerProvider(this._config);
|
|
||||||
let clientOptions: ClientOptions = {
|
let clientOptions: ClientOptions = {
|
||||||
providerId: Constants.providerId,
|
providerId: Constants.providerId,
|
||||||
features: [FireWallFeature]
|
features: [FireWallFeature]
|
||||||
};
|
};
|
||||||
return serverdownloader.getOrDownloadServer().then(e => {
|
const serverPath = await Utils.getOrDownloadServer(this._config);
|
||||||
let serverOptions = this.generateServerOptions(e);
|
let serverOptions = this.generateServerOptions(serverPath);
|
||||||
this._client = new SqlOpsDataClient(Constants.serviceName, serverOptions, clientOptions);
|
this._client = new SqlOpsDataClient(Constants.serviceName, serverOptions, clientOptions);
|
||||||
this._client.start();
|
this._client.start();
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public dispose() {
|
public dispose() {
|
||||||
|
|||||||
@@ -3,12 +3,12 @@
|
|||||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||||
*--------------------------------------------------------------------------------------------*/
|
*--------------------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
import { ServerProvider, IConfig, Events } from '@microsoft/ads-service-downloader';
|
import { IConfig, Events } from '@microsoft/ads-service-downloader';
|
||||||
import { ServerOptions, TransportKind } from 'vscode-languageclient';
|
import { ServerOptions, TransportKind } from 'vscode-languageclient';
|
||||||
import * as Constants from './constants';
|
import * as Constants from './constants';
|
||||||
import * as vscode from 'vscode';
|
import * as vscode from 'vscode';
|
||||||
import * as path from 'path';
|
import * as path from 'path';
|
||||||
import { getCommonLaunchArgsAndCleanupOldLogFiles } from './utils';
|
import { getCommonLaunchArgsAndCleanupOldLogFiles, getOrDownloadServer } from './utils';
|
||||||
import { Telemetry, LanguageClientErrorHandler } from './telemetry';
|
import { Telemetry, LanguageClientErrorHandler } from './telemetry';
|
||||||
import { SqlOpsDataClient, ClientOptions } from 'dataprotocol-client';
|
import { SqlOpsDataClient, ClientOptions } from 'dataprotocol-client';
|
||||||
import { TelemetryFeature, AgentServicesFeature, SerializationFeature, AccountFeature, SqlAssessmentServicesFeature, ProfilerFeature } from './features';
|
import { TelemetryFeature, AgentServicesFeature, SerializationFeature, AccountFeature, SqlAssessmentServicesFeature, ProfilerFeature } from './features';
|
||||||
@@ -82,10 +82,7 @@ export class SqlToolsServer {
|
|||||||
this.config.installDirectory = path.join(configDir, this.config.installDirectory);
|
this.config.installDirectory = path.join(configDir, this.config.installDirectory);
|
||||||
this.config.proxy = vscode.workspace.getConfiguration('http').get('proxy');
|
this.config.proxy = vscode.workspace.getConfiguration('http').get('proxy');
|
||||||
this.config.strictSSL = vscode.workspace.getConfiguration('http').get('proxyStrictSSL') || true;
|
this.config.strictSSL = vscode.workspace.getConfiguration('http').get('proxyStrictSSL') || true;
|
||||||
|
return getOrDownloadServer(this.config, handleServerProviderEvent);
|
||||||
const serverdownloader = new ServerProvider(this.config);
|
|
||||||
serverdownloader.eventEmitter.onAny(generateHandleServerProviderEvent());
|
|
||||||
return serverdownloader.getOrDownloadServer();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private activateFeatures(context: AppContext): Promise<void> {
|
private activateFeatures(context: AppContext): Promise<void> {
|
||||||
@@ -109,39 +106,37 @@ function generateServerOptions(logPath: string, executablePath: string): ServerO
|
|||||||
return { command: executablePath, args: launchArgs, transport: TransportKind.stdio };
|
return { command: executablePath, args: launchArgs, transport: TransportKind.stdio };
|
||||||
}
|
}
|
||||||
|
|
||||||
function generateHandleServerProviderEvent() {
|
function handleServerProviderEvent(e: string, ...args: any[]): void {
|
||||||
let dots = 0;
|
let dots = 0;
|
||||||
return (e: string, ...args: any[]) => {
|
switch (e) {
|
||||||
switch (e) {
|
case Events.INSTALL_START:
|
||||||
case Events.INSTALL_START:
|
outputChannel.show(true);
|
||||||
outputChannel.show(true);
|
statusView.show();
|
||||||
statusView.show();
|
outputChannel.appendLine(localize('installingServiceChannelMsg', "Installing {0} to {1}", Constants.serviceName, args[0]));
|
||||||
outputChannel.appendLine(localize('installingServiceChannelMsg', "Installing {0} to {1}", Constants.serviceName, args[0]));
|
statusView.text = localize('installingServiceStatusMsg', "Installing {0}", Constants.serviceName);
|
||||||
statusView.text = localize('installingServiceStatusMsg', "Installing {0}", Constants.serviceName);
|
break;
|
||||||
break;
|
case Events.INSTALL_END:
|
||||||
case Events.INSTALL_END:
|
outputChannel.appendLine(localize('installedServiceChannelMsg', "Installed {0}", Constants.serviceName));
|
||||||
outputChannel.appendLine(localize('installedServiceChannelMsg', "Installed {0}", Constants.serviceName));
|
break;
|
||||||
break;
|
case Events.DOWNLOAD_START:
|
||||||
case Events.DOWNLOAD_START:
|
outputChannel.appendLine(localize('downloadingServiceChannelMsg', "Downloading {0}", args[0]));
|
||||||
outputChannel.appendLine(localize('downloadingServiceChannelMsg', "Downloading {0}", args[0]));
|
outputChannel.append(localize('downloadingServiceSizeChannelMsg', "({0} KB)", Math.ceil(args[1] / 1024).toLocaleString(vscode.env.language)));
|
||||||
outputChannel.append(localize('downloadingServiceSizeChannelMsg', "({0} KB)", Math.ceil(args[1] / 1024).toLocaleString(vscode.env.language)));
|
statusView.text = localize('downloadingServiceStatusMsg', "Downloading {0}", Constants.serviceName);
|
||||||
statusView.text = localize('downloadingServiceStatusMsg', "Downloading {0}", Constants.serviceName);
|
break;
|
||||||
break;
|
case Events.DOWNLOAD_PROGRESS:
|
||||||
case Events.DOWNLOAD_PROGRESS:
|
let newDots = Math.ceil(args[0] / 5);
|
||||||
let newDots = Math.ceil(args[0] / 5);
|
if (newDots > dots) {
|
||||||
if (newDots > dots) {
|
outputChannel.append('.'.repeat(newDots - dots));
|
||||||
outputChannel.append('.'.repeat(newDots - dots));
|
dots = newDots;
|
||||||
dots = newDots;
|
}
|
||||||
}
|
break;
|
||||||
break;
|
case Events.DOWNLOAD_END:
|
||||||
case Events.DOWNLOAD_END:
|
outputChannel.appendLine(localize('downloadServiceDoneChannelMsg', "Done installing {0}", Constants.serviceName));
|
||||||
outputChannel.appendLine(localize('downloadServiceDoneChannelMsg', "Done installing {0}", Constants.serviceName));
|
break;
|
||||||
break;
|
case Events.ENTRY_EXTRACTED:
|
||||||
case Events.ENTRY_EXTRACTED:
|
outputChannel.appendLine(localize('entryExtractedChannelMsg', "Extracted {0} ({1}/{2})", args[0], args[1], args[2]));
|
||||||
outputChannel.appendLine(localize('entryExtractedChannelMsg', "Extracted {0} ({1}/{2})", args[0], args[1], args[2]));
|
break;
|
||||||
break;
|
}
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function getClientOptions(context: AppContext): ClientOptions {
|
function getClientOptions(context: AppContext): ClientOptions {
|
||||||
|
|||||||
@@ -12,6 +12,8 @@ import * as os from 'os';
|
|||||||
import * as findRemoveSync from 'find-remove';
|
import * as findRemoveSync from 'find-remove';
|
||||||
import * as constants from './constants';
|
import * as constants from './constants';
|
||||||
import { promises as fs } from 'fs';
|
import { promises as fs } from 'fs';
|
||||||
|
import { IConfig, ServerProvider } from '@microsoft/ads-service-downloader';
|
||||||
|
import { env } from 'process';
|
||||||
|
|
||||||
const configTracingLevel = 'tracingLevel';
|
const configTracingLevel = 'tracingLevel';
|
||||||
const configLogRetentionMinutes = 'logRetentionMinutes';
|
const configLogRetentionMinutes = 'logRetentionMinutes';
|
||||||
@@ -304,3 +306,45 @@ export async function exists(path: string): Promise<boolean> {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const STS_OVERRIDE_ENV_VAR = 'ADS_SQLTOOLSSERVICE';
|
||||||
|
let overrideMessageDisplayed = false;
|
||||||
|
/**
|
||||||
|
* Gets the full path to the EXE for the specified tools service, downloading it in the process if necessary. The location
|
||||||
|
* for this can be overridden with an environment variable for debugging or other purposes.
|
||||||
|
* @param config The configuration values of the server to get/download
|
||||||
|
* @param handleServerEvent A callback for handling events from the server downloader
|
||||||
|
* @returns The path to the server exe
|
||||||
|
*/
|
||||||
|
export async function getOrDownloadServer(config: IConfig, handleServerEvent?: (e: string, ...args: any[]) => void): Promise<string> {
|
||||||
|
// This env var is used to override the base install location of STS - primarily to be used for debugging scenarios.
|
||||||
|
try {
|
||||||
|
const stsRootPath = env[STS_OVERRIDE_ENV_VAR];
|
||||||
|
if (stsRootPath) {
|
||||||
|
for (const exeFile of config.executableFiles) {
|
||||||
|
const serverFullPath = path.join(stsRootPath, exeFile);
|
||||||
|
if (await exists(serverFullPath)) {
|
||||||
|
const overrideMessage = `Using ${exeFile} from ${stsRootPath}`;
|
||||||
|
// Display message to the user so they know the override is active, but only once so we don't show too many
|
||||||
|
if (!overrideMessageDisplayed) {
|
||||||
|
overrideMessageDisplayed = true;
|
||||||
|
vscode.window.showInformationMessage(overrideMessage);
|
||||||
|
}
|
||||||
|
console.log(overrideMessage);
|
||||||
|
return serverFullPath;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
console.warn(`Could not find valid SQL Tools Service EXE from ${JSON.stringify(config.executableFiles)} at ${stsRootPath}, falling back to config`);
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
console.warn('Unexpected error getting override path for SQL Tools Service client ', err);
|
||||||
|
// Fall back to config if something unexpected happens here
|
||||||
|
}
|
||||||
|
|
||||||
|
const serverdownloader = new ServerProvider(config);
|
||||||
|
if (handleServerEvent) {
|
||||||
|
serverdownloader.eventEmitter.onAny(handleServerEvent);
|
||||||
|
}
|
||||||
|
|
||||||
|
return serverdownloader.getOrDownloadServer();
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user