mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-01-14 01:25:37 -05:00
Modifying the migration extension to use its own service. (#21781)
* Adding migration service to sql migrations * enabling auto flush log * Adding support for env variable * Adding TDE Migration service * code cleanup * updating service downloader * Removing custom output channel * remove unnecessary await * Updated service version to get latest code * Consolidate TDE into migration service * Sync to latest main * Update sql-migration package version * Fix merge conflict error * Fixing all merge conflicts * Fixing stuff * removing extra whitespace * Cleaning up --------- Co-authored-by: Akshay Mata <akma@microsoft.com>
This commit is contained in:
3
extensions/sql-migration/.gitignore
vendored
3
extensions/sql-migration/.gitignore
vendored
@@ -1 +1,2 @@
|
||||
*.vsix
|
||||
*.vsix
|
||||
migrationService/
|
||||
|
||||
41
extensions/sql-migration/DEVELOPER_GUIDE.md
Normal file
41
extensions/sql-migration/DEVELOPER_GUIDE.md
Normal file
@@ -0,0 +1,41 @@
|
||||
# SQL Migration Extension Developer Guide
|
||||
|
||||
SQL migration utilizes a backend service to execute assessments and provide SKU recommendations. The source code for the backend service can be found at [Microsoft.SqlTools.Migration](https://github.com/microsoft/sqltoolsservice/tree/main/src/Microsoft.SqlTools.Migration).
|
||||
|
||||
During regular usage of the extension, the backend service is downloaded from a URL specified in the config.json file.
|
||||
|
||||
When developing the extension, it is possible to run the backend service locally and debug the extension against the local backend service. This guide will walk you through the necessary steps to do so.
|
||||
|
||||
## Using ADS_MIGRATIONSERVICE environment variable
|
||||
|
||||
1. Clone the sqltoolsservice repository by running `git clone git@github.com:microsoft/sqltoolsservice.git`
|
||||
1. Navigate to the migration folder by running `cd src/Microsoft.SqlTools.Migration`
|
||||
1. Publish the project by running `dotnet publish -r <platform>` (e.g. `dotnet publish -r win-x64`). This will publish the project to a folder similar to `bin/Debug/net7.0/<platform>/publish/`
|
||||
1. In a terminal window, set the `ADS_MIGRATIONSERVICE` environment variable to the full path of the publish folder from the previous step.
|
||||
For example:
|
||||
```
|
||||
$ENV:ADS_MIGRATIONSERVICE=/Users/username/sqltoolsservice/src/Microsoft.SqlTools.Migration/bin/Debug/net7.0/win-x64/publish
|
||||
```
|
||||
1. Launch Azure Data Studio from the same terminal where you set the environment variable. When the migration service is activated, it will use the backend service from the environment variable path.
|
||||
1. You should see a pop-up notification indicating that the migration service is running from the environment variable path. If this notification does not appear, check that the environment variable is spelled correctly and that it points to the correct directory.
|
||||
1. After making changes to the service, you can republish the project and launch Azure Data Studio again from the same terminal where you set the environment variable.
|
||||
|
||||
## Replacing the Binaries Manually
|
||||
|
||||
1. Close any running instances of Azure Data Studio.
|
||||
1. Copy the publish folder from `src/Migration.SqlTools.Migration/bin/Debug/net7.0/<platform>/publish/` to `src/extensions/sql-migration/`. For example:
|
||||
```
|
||||
cp -r <src>/sqltoolsservice/src/Microsoft.SqlTools.Migration/bin/Debug/net7.0/win-x64/publish <src>/azuredatastudio/extensions/sql-migration/migrationService/<platform>/<version>/
|
||||
```
|
||||
1. Launch Azure Data Studio from `<src>/azuredatastudio`
|
||||
|
||||
|
||||
## Debugging the extension service:
|
||||
|
||||
### The logs for the extension and service during runtime can be accessed by:
|
||||
|
||||
1. Opening the command palette (Ctrl+P) and searching for "Developer: Open Extensions Logs Folder"
|
||||
2. Opening the Microsoft.sql-migration folder to access the log files. You will see three different log files:
|
||||
* `MicrosoftSqlToolsMigration`: logs for the migration service
|
||||
* `SqlAssessmentReport-<TIMESTAMP>`: report generated everytime user runs the assessment
|
||||
* `SqlAssessmentsLogs`: folder that contains runtime logs for the assessments
|
||||
20
extensions/sql-migration/config.json
Normal file
20
extensions/sql-migration/config.json
Normal file
@@ -0,0 +1,20 @@
|
||||
{
|
||||
"downloadUrl": "https://github.com/Microsoft/sqltoolsservice/releases/download/{#version#}/microsoft.sqltools.migration-{#fileName#}",
|
||||
"useDefaultLinuxRuntime": true,
|
||||
"version": "4.5.0.12",
|
||||
"downloadFileNames": {
|
||||
"Windows_86": "win-x86-net6.0.zip",
|
||||
"Windows_64": "win-x64-net6.0.zip",
|
||||
"OSX": "osx-x64-net6.0.tar.gz",
|
||||
"Linux": "rhel-x64-net6.0.tar.gz"
|
||||
},
|
||||
"installDirectory": "./migrationService/{#platform#}/{#version#}",
|
||||
"executableFiles": ["MicrosoftSqlToolsMigration", "MicrosoftSqlToolsMigration.exe"],
|
||||
"retry": {
|
||||
"retries": 3,
|
||||
"factor": 2,
|
||||
"minTimeout": 1000,
|
||||
"maxTimeout": 300000,
|
||||
"randomize": false
|
||||
}
|
||||
}
|
||||
@@ -2,7 +2,7 @@
|
||||
"name": "sql-migration",
|
||||
"displayName": "%displayName%",
|
||||
"description": "%description%",
|
||||
"version": "1.3.1",
|
||||
"version": "1.4.0",
|
||||
"publisher": "Microsoft",
|
||||
"preview": false,
|
||||
"license": "https://raw.githubusercontent.com/Microsoft/azuredatastudio/main/LICENSE.txt",
|
||||
@@ -153,6 +153,8 @@
|
||||
]
|
||||
},
|
||||
"dependencies": {
|
||||
"dataprotocol-client": "github:Microsoft/sqlops-dataprotocolclient#1.3.1",
|
||||
"@microsoft/ads-service-downloader": "^1.1.0",
|
||||
"@microsoft/ads-extension-telemetry": "^1.3.4",
|
||||
"uuid": "^8.3.2",
|
||||
"vscode-nls": "^4.1.2"
|
||||
|
||||
@@ -11,6 +11,20 @@ import { formatNumber, ParallelCopyTypeCodes, PipelineStatusCodes } from './help
|
||||
import { ValidationError } from '../api/azure';
|
||||
const localize = nls.loadMessageBundle();
|
||||
|
||||
export const serviceName = 'Sql Migration Service';
|
||||
export const providerId = 'SqlMigration';
|
||||
export const extensionConfigSectionName = 'sqlMigration';
|
||||
export const sqlConfigSectionName = 'sql';
|
||||
export const configLogDebugInfo = 'logDebugInfo';
|
||||
export function serviceCrashMessage(error: string): string {
|
||||
return localize('serviceCrashMessage', "Migration service component could not start. {0}", error);
|
||||
}
|
||||
export const serviceCrashed = localize('serviceCrashed', "Service component crashed.");
|
||||
export function waitingForService(serviceName: string): string {
|
||||
return localize('waitingForService', "Waiting for {0} component to start.", serviceName);
|
||||
}
|
||||
export const serviceProviderInitializationError = localize('serviceProviderIntializationError', "Service provider could not be initialized.");
|
||||
|
||||
// mirrors MigrationState as defined in RP
|
||||
export enum MigrationState {
|
||||
Canceled = 'Canceled',
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
|
||||
import * as azdata from 'azdata';
|
||||
import * as vscode from 'vscode';
|
||||
import * as mssql from 'mssql';
|
||||
import { promises as fs } from 'fs';
|
||||
import { DatabaseMigration, getMigrationDetails } from '../api/azure';
|
||||
import { MenuCommands, SqlMigrationExtensionId } from '../api/utils';
|
||||
@@ -26,6 +25,8 @@ import { DashboardStatusBar, ErrorEvent } from './DashboardStatusBar';
|
||||
import { DashboardTab } from './dashboardTab';
|
||||
import { MigrationsTab, MigrationsTabId } from './migrationsTab';
|
||||
import { AdsMigrationStatus, MigrationDetailsEvent, ServiceContextChangeEvent } from './tabBase';
|
||||
import { migrationServiceProvider } from '../service/provider';
|
||||
import { ApiType, SqlMigrationService } from '../service/features';
|
||||
import { getSourceConnectionId, getSourceConnectionProfile } from '../api/sqlUtils';
|
||||
|
||||
export interface MenuCommandArgs {
|
||||
@@ -438,9 +439,10 @@ export class DashboardWidget {
|
||||
serverName = activeConnection.serverName;
|
||||
}
|
||||
if (serverName) {
|
||||
const api = (await vscode.extensions.getExtension(mssql.extension.name)?.activate()) as mssql.IExtension;
|
||||
if (api) {
|
||||
this.stateModel = new MigrationStateModel(this._context, api.sqlMigration, api.tdeMigration);
|
||||
const migrationService = <SqlMigrationService>await migrationServiceProvider.getService(ApiType.SqlMigrationProvider);
|
||||
|
||||
if (migrationService) {
|
||||
this.stateModel = new MigrationStateModel(this._context, migrationService);
|
||||
this._context.subscriptions.push(this.stateModel);
|
||||
const savedInfo = this.checkSavedInfo(serverName);
|
||||
if (savedInfo) {
|
||||
@@ -474,9 +476,9 @@ export class DashboardWidget {
|
||||
serverName = activeConnection.serverName;
|
||||
}
|
||||
if (serverName) {
|
||||
const api = (await vscode.extensions.getExtension(mssql.extension.name)?.activate()) as mssql.IExtension;
|
||||
if (api) {
|
||||
this.stateModel = new MigrationStateModel(this._context, api.sqlMigration, api.tdeMigration);
|
||||
const migrationService = <SqlMigrationService>await migrationServiceProvider.getService(ApiType.SqlMigrationProvider);
|
||||
if (migrationService) {
|
||||
this.stateModel = new MigrationStateModel(this._context, migrationService);
|
||||
this._context.subscriptions.push(this.stateModel);
|
||||
const wizardController = new WizardController(
|
||||
this._context,
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
|
||||
import * as azdata from 'azdata';
|
||||
import * as vscode from 'vscode';
|
||||
import * as mssql from 'mssql';
|
||||
import * as features from '../../service/features';
|
||||
import { azureResource } from 'azurecore';
|
||||
import { getLocations, getResourceGroupFromId, getBlobContainerId, getFullResourceGroupFromId, getResourceName, DatabaseMigration, getMigrationTargetInstance } from '../../api/azure';
|
||||
import { MigrationMode, MigrationStateModel, NetworkContainerType, SavedInfo } from '../../models/stateMachine';
|
||||
@@ -14,6 +14,7 @@ import { WizardController } from '../../wizard/wizardController';
|
||||
import { getMigrationModeEnum, getMigrationTargetTypeEnum } from '../../constants/helper';
|
||||
import * as constants from '../../constants/strings';
|
||||
import { ServiceContextChangeEvent } from '../../dashboard/tabBase';
|
||||
import { migrationServiceProvider } from '../../service/provider';
|
||||
import { getSourceConnectionProfile } from '../../api/sqlUtils';
|
||||
|
||||
export class RetryMigrationDialog {
|
||||
@@ -29,10 +30,10 @@ export class RetryMigrationDialog {
|
||||
serviceContext: MigrationServiceContext,
|
||||
migration: DatabaseMigration,
|
||||
serverName: string,
|
||||
api: mssql.IExtension,
|
||||
migrationService: features.SqlMigrationService,
|
||||
location: azureResource.AzureLocation): Promise<MigrationStateModel> {
|
||||
|
||||
const stateModel = new MigrationStateModel(this._context, api.sqlMigration, api.tdeMigration);
|
||||
const stateModel = new MigrationStateModel(this._context, migrationService);
|
||||
const sourceDatabaseName = migration.properties.sourceDatabaseName;
|
||||
const savedInfo: SavedInfo = {
|
||||
closedPage: 0,
|
||||
@@ -160,8 +161,8 @@ export class RetryMigrationDialog {
|
||||
serverName = activeConnection.serverName;
|
||||
}
|
||||
|
||||
const api = (await vscode.extensions.getExtension(mssql.extension.name)?.activate()) as mssql.IExtension;
|
||||
const stateModel = await this.createMigrationStateModel(this._serviceContext, this._migration, serverName, api, location!);
|
||||
const migrationService = <features.SqlMigrationService>await migrationServiceProvider.getService(features.ApiType.SqlMigrationProvider)!;
|
||||
const stateModel = await this.createMigrationStateModel(this._serviceContext, this._migration, serverName, migrationService, location!);
|
||||
|
||||
if (await stateModel.loadSavedInfo()) {
|
||||
const wizardController = new WizardController(
|
||||
|
||||
@@ -7,8 +7,8 @@ import * as azdata from 'azdata';
|
||||
import * as vscode from 'vscode';
|
||||
import { MigrationStateModel, MigrationTargetType } from '../../models/stateMachine';
|
||||
import * as constants from '../../constants/strings';
|
||||
import * as contracts from '../../service/contracts';
|
||||
import * as styles from '../../constants/styles';
|
||||
import * as mssql from 'mssql';
|
||||
import * as utils from '../../api/utils';
|
||||
import * as fs from 'fs';
|
||||
import path = require('path');
|
||||
@@ -29,8 +29,8 @@ export class SkuRecommendationResultsDialog {
|
||||
public targetName?: string;
|
||||
private _saveButton!: azdata.window.Button;
|
||||
|
||||
public targetRecommendations?: mssql.SkuRecommendationResultItem[];
|
||||
public instanceRequirements?: mssql.SqlInstanceRequirements;
|
||||
public targetRecommendations?: contracts.SkuRecommendationResultItem[];
|
||||
public instanceRequirements?: contracts.SqlInstanceRequirements;
|
||||
|
||||
constructor(public model: MigrationStateModel, public _targetType: MigrationTargetType) {
|
||||
switch (this._targetType) {
|
||||
@@ -90,9 +90,9 @@ export class SkuRecommendationResultsDialog {
|
||||
return container;
|
||||
}
|
||||
|
||||
private createRecommendation(_view: azdata.ModelView, recommendationItem: mssql.SkuRecommendationResultItem): azdata.FlexContainer {
|
||||
private createRecommendation(_view: azdata.ModelView, recommendationItem: contracts.SkuRecommendationResultItem): azdata.FlexContainer {
|
||||
|
||||
let recommendation: mssql.IaaSSkuRecommendationResultItem | mssql.PaaSSkuRecommendationResultItem;
|
||||
let recommendation: contracts.IaaSSkuRecommendationResultItem | contracts.PaaSSkuRecommendationResultItem;
|
||||
|
||||
let configuration = constants.NA;
|
||||
let storageSection = _view.modelBuilder.flexContainer().withLayout({
|
||||
@@ -100,7 +100,7 @@ export class SkuRecommendationResultsDialog {
|
||||
}).component();
|
||||
switch (this._targetType) {
|
||||
case MigrationTargetType.SQLVM:
|
||||
recommendation = <mssql.IaaSSkuRecommendationResultItem>recommendationItem;
|
||||
recommendation = <contracts.IaaSSkuRecommendationResultItem>recommendationItem;
|
||||
|
||||
if (recommendation.targetSku) {
|
||||
configuration = constants.VM_CONFIGURATION(
|
||||
@@ -113,18 +113,18 @@ export class SkuRecommendationResultsDialog {
|
||||
|
||||
case MigrationTargetType.SQLMI:
|
||||
case MigrationTargetType.SQLDB:
|
||||
recommendation = <mssql.PaaSSkuRecommendationResultItem>recommendationItem;
|
||||
recommendation = <contracts.PaaSSkuRecommendationResultItem>recommendationItem;
|
||||
|
||||
if (recommendation.targetSku) {
|
||||
const serviceTier = recommendation.targetSku.category?.sqlServiceTier === mssql.AzureSqlPaaSServiceTier.GeneralPurpose
|
||||
const serviceTier = recommendation.targetSku.category?.sqlServiceTier === contracts.AzureSqlPaaSServiceTier.GeneralPurpose
|
||||
? constants.GENERAL_PURPOSE
|
||||
: recommendation.targetSku.category?.sqlServiceTier === mssql.AzureSqlPaaSServiceTier.HyperScale
|
||||
: recommendation.targetSku.category?.sqlServiceTier === contracts.AzureSqlPaaSServiceTier.HyperScale
|
||||
? constants.HYPERSCALE
|
||||
: constants.BUSINESS_CRITICAL;
|
||||
|
||||
const hardwareType = recommendation.targetSku.category?.hardwareType === mssql.AzureSqlPaaSHardwareType.Gen5
|
||||
const hardwareType = recommendation.targetSku.category?.hardwareType === contracts.AzureSqlPaaSHardwareType.Gen5
|
||||
? constants.GEN5
|
||||
: recommendation.targetSku.category?.hardwareType === mssql.AzureSqlPaaSHardwareType.PremiumSeries
|
||||
: recommendation.targetSku.category?.hardwareType === contracts.AzureSqlPaaSHardwareType.PremiumSeries
|
||||
? constants.PREMIUM_SERIES
|
||||
: constants.PREMIUM_SERIES_MEMORY_OPTIMIZED;
|
||||
|
||||
@@ -240,7 +240,7 @@ export class SkuRecommendationResultsDialog {
|
||||
return recommendationContainer;
|
||||
}
|
||||
|
||||
private createSqlVmTargetStorageSection(_view: azdata.ModelView, recommendation: mssql.IaaSSkuRecommendationResultItem): azdata.FlexContainer {
|
||||
private createSqlVmTargetStorageSection(_view: azdata.ModelView, recommendation: contracts.IaaSSkuRecommendationResultItem): azdata.FlexContainer {
|
||||
const recommendedTargetStorageSection = _view.modelBuilder.text()
|
||||
.withProps({
|
||||
value: constants.RECOMMENDED_TARGET_STORAGE_CONFIGURATION,
|
||||
@@ -348,18 +348,18 @@ export class SkuRecommendationResultsDialog {
|
||||
return container;
|
||||
}
|
||||
|
||||
private getCachingText(caching: mssql.AzureManagedDiskCaching): string {
|
||||
private getCachingText(caching: contracts.AzureManagedDiskCaching): string {
|
||||
switch (caching) {
|
||||
case mssql.AzureManagedDiskCaching.NotApplicable:
|
||||
case contracts.AzureManagedDiskCaching.NotApplicable:
|
||||
return constants.CACHING_NA;
|
||||
|
||||
case mssql.AzureManagedDiskCaching.None:
|
||||
case contracts.AzureManagedDiskCaching.None:
|
||||
return constants.CACHING_NONE;
|
||||
|
||||
case mssql.AzureManagedDiskCaching.ReadOnly:
|
||||
case contracts.AzureManagedDiskCaching.ReadOnly:
|
||||
return constants.CACHING_READ_ONLY;
|
||||
|
||||
case mssql.AzureManagedDiskCaching.ReadWrite:
|
||||
case contracts.AzureManagedDiskCaching.ReadWrite:
|
||||
return constants.CACHING_READ_WRITE;
|
||||
}
|
||||
}
|
||||
@@ -460,7 +460,7 @@ export class SkuRecommendationResultsDialog {
|
||||
return container;
|
||||
}
|
||||
|
||||
public async openDialog(dialogName?: string, recommendations?: mssql.SkuRecommendationResult) {
|
||||
public async openDialog(dialogName?: string, recommendations?: contracts.SkuRecommendationResult) {
|
||||
if (!this._isOpen) {
|
||||
this._isOpen = true;
|
||||
this.instanceRequirements = recommendations?.instanceRequirements;
|
||||
|
||||
@@ -5,10 +5,23 @@
|
||||
|
||||
import * as vscode from 'vscode';
|
||||
import { DashboardWidget } from './dashboard/sqlServerDashboard';
|
||||
import * as constants from './constants/strings';
|
||||
import { ServiceClient } from './service/serviceClient';
|
||||
import { migrationServiceProvider } from './service/provider';
|
||||
import { TelemetryReporter } from './telemetry';
|
||||
|
||||
let widget: DashboardWidget;
|
||||
export async function activate(context: vscode.ExtensionContext): Promise<DashboardWidget> {
|
||||
if (!migrationServiceProvider) {
|
||||
await vscode.window.showErrorMessage(constants.serviceProviderInitializationError);
|
||||
}
|
||||
// asynchronously starting the service
|
||||
const outputChannel = vscode.window.createOutputChannel(constants.serviceName);
|
||||
const serviceClient = new ServiceClient(outputChannel);
|
||||
serviceClient.startService(context).catch((e) => {
|
||||
console.error(e);
|
||||
});
|
||||
|
||||
widget = new DashboardWidget(context);
|
||||
await widget.register();
|
||||
context.subscriptions.push(TelemetryReporter);
|
||||
|
||||
@@ -6,7 +6,8 @@
|
||||
import * as azdata from 'azdata';
|
||||
import * as azurecore from 'azurecore';
|
||||
import * as vscode from 'vscode';
|
||||
import * as mssql from 'mssql';
|
||||
import * as contracts from '../service/contracts';
|
||||
import * as features from '../service/features';
|
||||
import { SqlMigrationService, SqlManagedInstance, startDatabaseMigration, StartDatabaseMigrationRequest, StorageAccount, SqlVMServer, getLocationDisplayName, getSqlManagedInstanceDatabases, AzureSqlDatabaseServer, VirtualMachineInstanceView } from '../api/azure';
|
||||
import * as constants from '../constants/strings';
|
||||
import * as nls from 'vscode-nls';
|
||||
@@ -222,7 +223,7 @@ export class MigrationStateModel implements Model, vscode.Disposable {
|
||||
public _assessmentResults!: ServerAssessment;
|
||||
public _assessedDatabaseList!: string[];
|
||||
public _runAssessments: boolean = true;
|
||||
private _assessmentApiResponse!: mssql.AssessmentResult;
|
||||
private _assessmentApiResponse!: contracts.AssessmentResult;
|
||||
public _assessmentReportFilePath: string;
|
||||
public mementoString: string;
|
||||
|
||||
@@ -241,7 +242,7 @@ export class MigrationStateModel implements Model, vscode.Disposable {
|
||||
|
||||
public _skuRecommendationResults!: SkuRecommendation;
|
||||
public _skuRecommendationPerformanceDataSource!: PerformanceDataSourceOptions;
|
||||
private _skuRecommendationApiResponse!: mssql.SkuRecommendationResult;
|
||||
private _skuRecommendationApiResponse!: contracts.SkuRecommendationResult;
|
||||
public _skuRecommendationReportFilePaths: string[];
|
||||
public _skuRecommendationPerformanceLocation!: string;
|
||||
|
||||
@@ -254,7 +255,7 @@ export class MigrationStateModel implements Model, vscode.Disposable {
|
||||
|
||||
public _loginsForMigration!: LoginTableInfo[];
|
||||
public _aadDomainName!: string;
|
||||
public _loginMigrationsResult!: mssql.StartLoginMigrationResult;
|
||||
public _loginMigrationsResult!: contracts.StartLoginMigrationResult;
|
||||
public _loginMigrationsError: any;
|
||||
public _loginMigrationModel: LoginMigrationModel;
|
||||
|
||||
@@ -288,16 +289,15 @@ export class MigrationStateModel implements Model, vscode.Disposable {
|
||||
private _currentState: State;
|
||||
private _gatheringInformationError: string | undefined;
|
||||
private _skuRecommendationRecommendedDatabaseList!: string[];
|
||||
private _startPerfDataCollectionApiResponse!: mssql.StartPerfDataCollectionResult;
|
||||
private _stopPerfDataCollectionApiResponse!: mssql.StopPerfDataCollectionResult;
|
||||
private _refreshPerfDataCollectionApiResponse!: mssql.RefreshPerfDataCollectionResult;
|
||||
private _startPerfDataCollectionApiResponse!: contracts.StartPerfDataCollectionResult;
|
||||
private _stopPerfDataCollectionApiResponse!: contracts.StopPerfDataCollectionResult;
|
||||
private _refreshPerfDataCollectionApiResponse!: contracts.RefreshPerfDataCollectionResult;
|
||||
private _autoRefreshPerfDataCollectionHandle!: NodeJS.Timeout;
|
||||
private _autoRefreshGetSkuRecommendationHandle!: NodeJS.Timeout;
|
||||
|
||||
constructor(
|
||||
public extensionContext: vscode.ExtensionContext,
|
||||
public readonly migrationService: mssql.ISqlMigrationService,
|
||||
public readonly tdeMigrationService: mssql.ITdeMigrationService
|
||||
public readonly migrationService: features.SqlMigrationService,
|
||||
) {
|
||||
this._currentState = State.INIT;
|
||||
this._databaseBackup = {} as DatabaseBackupModel;
|
||||
@@ -398,10 +398,10 @@ export class MigrationStateModel implements Model, vscode.Disposable {
|
||||
}
|
||||
|
||||
public async getDatabaseAssessments(targetType: MigrationTargetType[]): Promise<ServerAssessment> {
|
||||
const ownerUri = await getSourceConnectionUri();
|
||||
const connectionString = await getSourceConnectionString();
|
||||
try {
|
||||
const xEventsFilesFolderPath = ''; // to-do: collect by prompting the user in the UI - for now, blank = disabled
|
||||
const response = (await this.migrationService.getAssessments(ownerUri, this._databasesForAssessment, xEventsFilesFolderPath))!;
|
||||
const response = (await this.migrationService.getAssessments(connectionString, this._databasesForAssessment, xEventsFilesFolderPath))!;
|
||||
this._assessmentApiResponse = response;
|
||||
this._assessedDatabaseList = this._databasesForAssessment.slice();
|
||||
|
||||
@@ -548,7 +548,7 @@ export class MigrationStateModel implements Model, vscode.Disposable {
|
||||
return this._targetServerName;
|
||||
}
|
||||
|
||||
private updateLoginMigrationResults(newResult: mssql.StartLoginMigrationResult): void {
|
||||
private updateLoginMigrationResults(newResult: contracts.StartLoginMigrationResult): void {
|
||||
if (this._loginMigrationsResult && this._loginMigrationsResult.exceptionMap) {
|
||||
for (var key in newResult.exceptionMap) {
|
||||
this._loginMigrationsResult.exceptionMap[key] = [...this._loginMigrationsResult.exceptionMap[key] || [], newResult.exceptionMap[key]]
|
||||
@@ -781,9 +781,9 @@ export class MigrationStateModel implements Model, vscode.Disposable {
|
||||
page: SKURecommendationPage): Promise<boolean> {
|
||||
try {
|
||||
if (!this.performanceCollectionInProgress()) {
|
||||
const ownerUri = await getSourceConnectionUri();
|
||||
const connectionString = await getSourceConnectionString();
|
||||
const response = await this.migrationService.startPerfDataCollection(
|
||||
ownerUri,
|
||||
connectionString,
|
||||
dataFolder,
|
||||
perfQueryIntervalInSec,
|
||||
staticQueryIntervalInSec,
|
||||
@@ -1106,7 +1106,7 @@ export class MigrationStateModel implements Model, vscode.Disposable {
|
||||
|
||||
try {
|
||||
|
||||
const migrationResult = await this.tdeMigrationService.migrateCertificate(
|
||||
const migrationResult = await this.migrationService.migrateCertificate(
|
||||
tdeEnabledDatabases,
|
||||
connectionString,
|
||||
this._targetSubscription?.id,
|
||||
@@ -1116,11 +1116,11 @@ export class MigrationStateModel implements Model, vscode.Disposable {
|
||||
accessToken,
|
||||
reportUpdate);
|
||||
|
||||
opResult.errors = migrationResult.migrationStatuses
|
||||
opResult.errors = migrationResult!.migrationStatuses
|
||||
.filter(entry => !entry.success)
|
||||
.map(entry => constants.TDE_MIGRATION_ERROR_DB(entry.dbName, entry.message));
|
||||
|
||||
opResult.result = migrationResult.migrationStatuses.map(m => ({
|
||||
opResult.result = migrationResult!.migrationStatuses.map(m => ({
|
||||
name: m.dbName,
|
||||
success: m.success,
|
||||
message: m.message
|
||||
@@ -1477,18 +1477,18 @@ export class MigrationStateModel implements Model, vscode.Disposable {
|
||||
}
|
||||
|
||||
export interface ServerAssessment {
|
||||
issues: mssql.SqlMigrationAssessmentResultItem[];
|
||||
issues: contracts.SqlMigrationAssessmentResultItem[];
|
||||
databaseAssessments: {
|
||||
name: string;
|
||||
issues: mssql.SqlMigrationAssessmentResultItem[];
|
||||
errors?: mssql.ErrorModel[];
|
||||
issues: contracts.SqlMigrationAssessmentResultItem[];
|
||||
errors?: contracts.ErrorModel[];
|
||||
}[];
|
||||
errors?: mssql.ErrorModel[];
|
||||
errors?: contracts.ErrorModel[];
|
||||
assessmentError?: Error;
|
||||
}
|
||||
|
||||
export interface SkuRecommendation {
|
||||
recommendations?: mssql.SkuRecommendationResult;
|
||||
recommendations?: contracts.SkuRecommendationResult;
|
||||
recommendationError?: Error;
|
||||
}
|
||||
|
||||
|
||||
550
extensions/sql-migration/src/service/contracts.ts
Normal file
550
extensions/sql-migration/src/service/contracts.ts
Normal file
@@ -0,0 +1,550 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { RequestType, NotificationType } from 'vscode-languageclient';
|
||||
import * as azdata from 'azdata';
|
||||
|
||||
export interface IMessage {
|
||||
jsonrpc: string;
|
||||
}
|
||||
|
||||
export interface SqlMigrationAssessmentParams {
|
||||
connectionString: string;
|
||||
databases: string[];
|
||||
xEventsFilesFolderPath: string;
|
||||
}
|
||||
|
||||
export interface SqlMigrationImpactedObjectInfo {
|
||||
name: string;
|
||||
impactDetail: string;
|
||||
objectType: string;
|
||||
}
|
||||
|
||||
export interface SqlMigrationAssessmentResultItem {
|
||||
rulesetVersion: string;
|
||||
rulesetName: string;
|
||||
ruleId: string;
|
||||
targetType: string;
|
||||
checkId: string;
|
||||
tags: string[];
|
||||
displayName: string;
|
||||
description: string;
|
||||
helpLink: string;
|
||||
level: string;
|
||||
timestamp: string;
|
||||
kind: azdata.sqlAssessment.SqlAssessmentResultItemKind;
|
||||
message: string;
|
||||
appliesToMigrationTargetPlatform: string;
|
||||
issueCategory: string;
|
||||
databaseName: string;
|
||||
impactedObjects: SqlMigrationImpactedObjectInfo[];
|
||||
databaseRestoreFails: boolean;
|
||||
}
|
||||
|
||||
export interface ServerTargetReadiness {
|
||||
numberOfDatabasesReadyForMigration: number;
|
||||
numberOfNonOnlineDatabases: number;
|
||||
totalNumberOfDatabases: number;
|
||||
}
|
||||
|
||||
export interface ErrorModel {
|
||||
errorId: number;
|
||||
message: string;
|
||||
errorSummary: string;
|
||||
possibleCauses: string;
|
||||
guidance: string;
|
||||
}
|
||||
|
||||
export interface DatabaseTargetReadiness {
|
||||
noSelectionForMigration: boolean;
|
||||
numOfBlockerIssues: number;
|
||||
}
|
||||
|
||||
export interface DatabaseAssessmentProperties {
|
||||
compatibilityLevel: string;
|
||||
databaseSize: number;
|
||||
isReplicationEnabled: boolean;
|
||||
assessmentTimeInMilliseconds: number;
|
||||
items: SqlMigrationAssessmentResultItem[];
|
||||
errors: ErrorModel[];
|
||||
sqlManagedInstanceTargetReadiness: DatabaseTargetReadiness;
|
||||
name: string;
|
||||
}
|
||||
|
||||
export interface ServerAssessmentProperties {
|
||||
cpuCoreCount: number;
|
||||
physicalServerMemory: number;
|
||||
serverHostPlatform: string;
|
||||
serverVersion: string;
|
||||
serverEngineEdition: string;
|
||||
serverEdition: string;
|
||||
isClustered: boolean;
|
||||
numberOfUserDatabases: number;
|
||||
sqlAssessmentStatus: number;
|
||||
assessedDatabaseCount: number;
|
||||
sqlManagedInstanceTargetReadiness: ServerTargetReadiness;
|
||||
items: SqlMigrationAssessmentResultItem[];
|
||||
errors: ErrorModel[];
|
||||
databases: DatabaseAssessmentProperties[];
|
||||
name: string;
|
||||
}
|
||||
|
||||
export interface AssessmentResult {
|
||||
startTime: string;
|
||||
endedTime: string;
|
||||
assessmentResult: ServerAssessmentProperties;
|
||||
rawAssessmentResult: any;
|
||||
errors: ErrorModel[];
|
||||
assessmentReportPath: string;
|
||||
}
|
||||
|
||||
export namespace GetSqlMigrationAssessmentItemsRequest {
|
||||
export const type = new RequestType<SqlMigrationAssessmentParams, AssessmentResult, void, void>('migration/getassessments');
|
||||
}
|
||||
|
||||
export interface SqlMigrationSkuRecommendationsParams {
|
||||
dataFolder: string;
|
||||
perfQueryIntervalInSec: number;
|
||||
targetPlatforms: string[];
|
||||
targetSqlInstance: string;
|
||||
targetPercentile: number;
|
||||
scalingFactor: number;
|
||||
startTime: string;
|
||||
endTime: string;
|
||||
includePreviewSkus: boolean;
|
||||
databaseAllowList: string[];
|
||||
}
|
||||
|
||||
export interface AzureSqlSkuCategory {
|
||||
sqlTargetPlatform: AzureSqlTargetPlatform;
|
||||
computeTier: ComputeTier;
|
||||
}
|
||||
|
||||
export interface AzureSqlSkuPaaSCategory extends AzureSqlSkuCategory {
|
||||
sqlPurchasingModel: AzureSqlPurchasingModel;
|
||||
sqlServiceTier: AzureSqlPaaSServiceTier;
|
||||
hardwareType: AzureSqlPaaSHardwareType;
|
||||
}
|
||||
|
||||
export interface AzureSqlSkuIaaSCategory extends AzureSqlSkuCategory {
|
||||
virtualMachineFamilyType: VirtualMachineFamilyType;
|
||||
}
|
||||
|
||||
export interface AzureManagedDiskSku {
|
||||
tier: AzureManagedDiskTier;
|
||||
size: string;
|
||||
caching: AzureManagedDiskCaching;
|
||||
}
|
||||
|
||||
export interface AzureVirtualMachineSku {
|
||||
virtualMachineFamily: VirtualMachineFamily;
|
||||
sizeName: string;
|
||||
computeSize: number;
|
||||
azureSkuName: string;
|
||||
vCPUsAvailable: number;
|
||||
}
|
||||
|
||||
export interface AzureSqlSkuMonthlyCost {
|
||||
computeCost: number;
|
||||
storageCost: number;
|
||||
totalCost: number;
|
||||
}
|
||||
|
||||
export interface AzureSqlSku {
|
||||
category: AzureSqlSkuPaaSCategory | AzureSqlSkuIaaSCategory;
|
||||
computeSize: number;
|
||||
predictedDataSizeInMb: number;
|
||||
predictedLogSizeInMb: number;
|
||||
}
|
||||
|
||||
export interface AzureSqlPaaSSku extends AzureSqlSku {
|
||||
category: AzureSqlSkuPaaSCategory;
|
||||
storageMaxSizeInMb: number;
|
||||
}
|
||||
|
||||
export interface AzureSqlIaaSSku extends AzureSqlSku {
|
||||
category: AzureSqlSkuIaaSCategory;
|
||||
virtualMachineSize: AzureVirtualMachineSku;
|
||||
dataDiskSizes: AzureManagedDiskSku[];
|
||||
logDiskSizes: AzureManagedDiskSku[];
|
||||
tempDbDiskSizes: AzureManagedDiskSku[];
|
||||
}
|
||||
|
||||
export interface SkuRecommendationResultItem {
|
||||
sqlInstanceName: string;
|
||||
databaseName: string;
|
||||
targetSku: AzureSqlIaaSSku | AzureSqlPaaSSku;
|
||||
monthlyCost: AzureSqlSkuMonthlyCost;
|
||||
ranking: number;
|
||||
positiveJustifications: string[];
|
||||
negativeJustifications: string[];
|
||||
}
|
||||
|
||||
export interface SqlInstanceRequirements {
|
||||
cpuRequirementInCores: number;
|
||||
dataStorageRequirementInMB: number;
|
||||
logStorageRequirementInMB: number;
|
||||
memoryRequirementInMB: number;
|
||||
dataIOPSRequirement: number;
|
||||
logIOPSRequirement: number;
|
||||
ioLatencyRequirementInMs: number;
|
||||
ioThroughputRequirementInMBps: number;
|
||||
tempDBSizeInMB: number;
|
||||
dataPointsStartTime: string;
|
||||
dataPointsEndTime: string;
|
||||
aggregationTargetPercentile: number;
|
||||
perfDataCollectionIntervalInSeconds: number;
|
||||
databaseLevelRequirements: SqlDatabaseRequirements[];
|
||||
numberOfDataPointsAnalyzed: number;
|
||||
}
|
||||
|
||||
export interface SqlDatabaseRequirements {
|
||||
cpuRequirementInCores: number;
|
||||
dataIOPSRequirement: number;
|
||||
logIOPSRequirement: number;
|
||||
ioLatencyRequirementInMs: number;
|
||||
ioThroughputRequirementInMBps: number;
|
||||
dataStorageRequirementInMB: number;
|
||||
logStorageRequirementInMB: number;
|
||||
databaseName: string;
|
||||
memoryRequirementInMB: number;
|
||||
cpuRequirementInPercentageOfTotalInstance: number;
|
||||
numberOfDataPointsAnalyzed: number;
|
||||
fileLevelRequirements: SqlFileRequirements[];
|
||||
}
|
||||
|
||||
export interface SqlFileRequirements {
|
||||
fileName: string;
|
||||
fileType: DatabaseFileType;
|
||||
sizeInMB: number;
|
||||
readLatencyInMs: number;
|
||||
writeLatencyInMs: number;
|
||||
iopsRequirement: number;
|
||||
ioThroughputRequirementInMBps: number;
|
||||
numberOfDataPointsAnalyzed: number;
|
||||
}
|
||||
|
||||
export interface PaaSSkuRecommendationResultItem extends SkuRecommendationResultItem {
|
||||
targetSku: AzureSqlPaaSSku;
|
||||
}
|
||||
|
||||
export interface IaaSSkuRecommendationResultItem extends SkuRecommendationResultItem {
|
||||
targetSku: AzureSqlIaaSSku;
|
||||
}
|
||||
|
||||
export interface SkuRecommendationResult {
|
||||
sqlDbRecommendationResults: PaaSSkuRecommendationResultItem[];
|
||||
sqlDbRecommendationDurationInMs: number;
|
||||
sqlMiRecommendationResults: PaaSSkuRecommendationResultItem[];
|
||||
sqlMiRecommendationDurationInMs: number;
|
||||
sqlVmRecommendationResults: IaaSSkuRecommendationResultItem[];
|
||||
sqlVmRecommendationDurationInMs: number;
|
||||
elasticSqlDbRecommendationResults: PaaSSkuRecommendationResultItem[];
|
||||
elasticSqlDbRecommendationDurationInMs: number;
|
||||
elasticSqlMiRecommendationResults: PaaSSkuRecommendationResultItem[];
|
||||
elasticSqlMiRecommendationDurationInMs: number;
|
||||
elasticSqlVmRecommendationResults: IaaSSkuRecommendationResultItem[];
|
||||
elasticSqlVmRecommendationDurationInMs: number;
|
||||
instanceRequirements: SqlInstanceRequirements;
|
||||
skuRecommendationReportPaths: string[];
|
||||
elasticSkuRecommendationReportPaths: string[];
|
||||
}
|
||||
|
||||
// SKU recommendation enums, mirrored from Microsoft.SqlServer.Migration.SkuRecommendation
|
||||
export const enum DatabaseFileType {
|
||||
Rows = 0,
|
||||
Log = 1,
|
||||
Filestream = 2,
|
||||
NotSupported = 3,
|
||||
Fulltext = 4
|
||||
}
|
||||
|
||||
export const enum AzureSqlTargetPlatform {
|
||||
AzureSqlDatabase = 0,
|
||||
AzureSqlManagedInstance = 1,
|
||||
AzureSqlVirtualMachine = 2
|
||||
}
|
||||
|
||||
export const enum ComputeTier {
|
||||
Provisioned = 0,
|
||||
ServerLess = 1
|
||||
}
|
||||
|
||||
export const enum AzureManagedDiskTier {
|
||||
Standard = 0,
|
||||
Premium = 1,
|
||||
Ultra = 2
|
||||
}
|
||||
|
||||
export const enum AzureManagedDiskCaching {
|
||||
NotApplicable = 0,
|
||||
None = 1,
|
||||
ReadOnly = 2,
|
||||
ReadWrite = 3
|
||||
}
|
||||
|
||||
export const enum AzureSqlPurchasingModel {
|
||||
vCore = 0,
|
||||
}
|
||||
|
||||
export const enum AzureSqlPaaSServiceTier {
|
||||
GeneralPurpose = 0,
|
||||
BusinessCritical,
|
||||
HyperScale,
|
||||
}
|
||||
|
||||
export const enum AzureSqlPaaSHardwareType {
|
||||
Gen5 = 0,
|
||||
PremiumSeries,
|
||||
PremiumSeriesMemoryOptimized
|
||||
}
|
||||
|
||||
export const enum VirtualMachineFamilyType {
|
||||
GeneralPurpose,
|
||||
ComputeOptimized,
|
||||
MemoryOptimized,
|
||||
StorageOptimized,
|
||||
GPU,
|
||||
HighPerformanceCompute
|
||||
}
|
||||
|
||||
export const enum VirtualMachineFamily {
|
||||
basicAFamily,
|
||||
standardA0_A7Family,
|
||||
standardAv2Family,
|
||||
standardBSFamily,
|
||||
standardDFamily,
|
||||
standardDv2Family,
|
||||
standardDv2PromoFamily,
|
||||
standardDADSv5Family,
|
||||
standardDASv4Family,
|
||||
standardDASv5Family,
|
||||
standardDAv4Family,
|
||||
standardDDSv4Family,
|
||||
standardDDSv5Family,
|
||||
standardDDv4Family,
|
||||
standardDDv5Family,
|
||||
standardDSv3Family,
|
||||
standardDSv4Family,
|
||||
standardDSv5Family,
|
||||
standardDv3Family,
|
||||
standardDv4Family,
|
||||
standardDv5Family,
|
||||
standardDCADSv5Family,
|
||||
standardDCASv5Family,
|
||||
standardDCSv2Family,
|
||||
standardDSFamily,
|
||||
standardDSv2Family,
|
||||
standardDSv2PromoFamily,
|
||||
standardEIDSv5Family,
|
||||
standardEIDv5Family,
|
||||
standardEISv5Family,
|
||||
standardEIv5Family,
|
||||
standardEADSv5Family,
|
||||
standardEASv4Family,
|
||||
standardEASv5Family,
|
||||
standardEDSv4Family,
|
||||
standardEDSv5Family,
|
||||
standardEBDSv5Family,
|
||||
standardESv3Family,
|
||||
standardESv4Family,
|
||||
standardESv5Family,
|
||||
standardEBSv5Family,
|
||||
standardEAv4Family,
|
||||
standardEDv4Family,
|
||||
standardEDv5Family,
|
||||
standardEv3Family,
|
||||
standardEv4Family,
|
||||
standardEv5Family,
|
||||
standardEISv3Family,
|
||||
standardEIv3Family,
|
||||
standardXEIDSv4Family,
|
||||
standardXEISv4Family,
|
||||
standardECADSv5Family,
|
||||
standardECASv5Family,
|
||||
standardECIADSv5Family,
|
||||
standardECIASv5Family,
|
||||
standardFFamily,
|
||||
standardFSFamily,
|
||||
standardFSv2Family,
|
||||
standardGFamily,
|
||||
standardGSFamily,
|
||||
standardHFamily,
|
||||
standardHPromoFamily,
|
||||
standardLSFamily,
|
||||
standardLSv2Family,
|
||||
standardMSFamily,
|
||||
standardMDSMediumMemoryv2Family,
|
||||
standardMSMediumMemoryv2Family,
|
||||
standardMIDSMediumMemoryv2Family,
|
||||
standardMISMediumMemoryv2Family,
|
||||
standardMSv2Family,
|
||||
standardNCSv3Family,
|
||||
StandardNCASv3_T4Family,
|
||||
standardNVSv2Family,
|
||||
standardNVSv3Family,
|
||||
standardNVSv4Family
|
||||
}
|
||||
|
||||
export namespace GetSqlMigrationSkuRecommendationsRequest {
|
||||
export const type = new RequestType<SqlMigrationSkuRecommendationsParams, SkuRecommendationResult, void, void>('migration/getskurecommendations');
|
||||
}
|
||||
|
||||
export interface SqlMigrationStartPerfDataCollectionParams {
|
||||
connectionString: string,
|
||||
dataFolder: string,
|
||||
perfQueryIntervalInSec: number,
|
||||
staticQueryIntervalInSec: number,
|
||||
numberOfIterations: number
|
||||
}
|
||||
|
||||
export interface StartPerfDataCollectionResult {
|
||||
dateTimeStarted: Date;
|
||||
}
|
||||
|
||||
export namespace SqlMigrationStartPerfDataCollectionRequest {
|
||||
export const type = new RequestType<SqlMigrationStartPerfDataCollectionParams, StartPerfDataCollectionResult, void, void>('migration/startperfdatacollection');
|
||||
}
|
||||
|
||||
export interface SqlMigrationStopPerfDataCollectionParams {
|
||||
}
|
||||
|
||||
export interface StopPerfDataCollectionResult {
|
||||
dateTimeStopped: Date;
|
||||
}
|
||||
|
||||
export namespace SqlMigrationStopPerfDataCollectionRequest {
|
||||
export const type = new RequestType<SqlMigrationStopPerfDataCollectionParams, StopPerfDataCollectionResult, void, void>('migration/stopperfdatacollection');
|
||||
}
|
||||
|
||||
export interface SqlMigrationRefreshPerfDataCollectionParams {
|
||||
lastRefreshTime: Date
|
||||
}
|
||||
export interface RefreshPerfDataCollectionResult {
|
||||
isCollecting: boolean;
|
||||
messages: string[];
|
||||
errors: string[];
|
||||
refreshTime: Date;
|
||||
}
|
||||
|
||||
export namespace SqlMigrationRefreshPerfDataCollectionRequest {
|
||||
export const type = new RequestType<SqlMigrationRefreshPerfDataCollectionParams, RefreshPerfDataCollectionResult, void, void>('migration/refreshperfdatacollection');
|
||||
}
|
||||
|
||||
export interface StartLoginMigrationsParams {
|
||||
sourceConnectionString: string;
|
||||
targetConnectionString: string;
|
||||
loginList: string[];
|
||||
aadDomainName: string;
|
||||
}
|
||||
|
||||
export enum LoginMigrationStep {
|
||||
StartValidations = 0,
|
||||
MigrateLogins = 1,
|
||||
EstablishUserMapping = 2,
|
||||
MigrateServerRoles = 3,
|
||||
EstablishServerRoleMapping = 4,
|
||||
SetLoginPermissions = 5,
|
||||
SetServerRolePermissions = 6,
|
||||
}
|
||||
|
||||
export interface StartLoginMigrationResult {
|
||||
exceptionMap: { [login: string]: any };
|
||||
completedStep: LoginMigrationStep;
|
||||
elapsedTime: string;
|
||||
}
|
||||
|
||||
export namespace StartLoginMigrationRequest {
|
||||
export const type = new RequestType<StartLoginMigrationsParams, StartLoginMigrationResult, void, void>('migration/startloginmigration');
|
||||
}
|
||||
|
||||
export namespace ValidateLoginMigrationRequest {
|
||||
export const type = new RequestType<StartLoginMigrationsParams, StartLoginMigrationResult, void, void>('migration/validateloginmigration');
|
||||
}
|
||||
|
||||
export namespace MigrateLoginsRequest {
|
||||
export const type = new RequestType<StartLoginMigrationsParams, StartLoginMigrationResult, void, void>('migration/migratelogins');
|
||||
}
|
||||
|
||||
export namespace EstablishUserMappingRequest {
|
||||
export const type = new RequestType<StartLoginMigrationsParams, StartLoginMigrationResult, void, void>('migration/establishusermapping');
|
||||
}
|
||||
|
||||
export namespace MigrateServerRolesAndSetPermissionsRequest {
|
||||
export const type = new RequestType<StartLoginMigrationsParams, StartLoginMigrationResult, void, void>('migration/migrateserverrolesandsetpermissions');
|
||||
}
|
||||
|
||||
export namespace LoginMigrationNotification {
|
||||
export const type = new NotificationType<StartLoginMigrationResult, void>('migration/loginmigrationnotification"');
|
||||
}
|
||||
|
||||
export interface ISqlMigrationService {
|
||||
providerId: string;
|
||||
getAssessments(ownerUri: string, databases: string[], xEventsFilesFolderPath: string): Thenable<AssessmentResult | undefined>;
|
||||
getSkuRecommendations(dataFolder: string, perfQueryIntervalInSec: number, targetPlatforms: string[], targetSqlInstance: string, targetPercentile: number, scalingFactor: number, startTime: string, endTime: string, includePreviewSkus: boolean, databaseAllowList: string[]): Promise<SkuRecommendationResult | undefined>;
|
||||
startPerfDataCollection(ownerUri: string, dataFolder: string, perfQueryIntervalInSec: number, staticQueryIntervalInSec: number, numberOfIterations: number): Promise<StartPerfDataCollectionResult | undefined>;
|
||||
stopPerfDataCollection(): Promise<StopPerfDataCollectionResult | undefined>;
|
||||
refreshPerfDataCollection(lastRefreshedTime: Date): Promise<RefreshPerfDataCollectionResult | undefined>;
|
||||
startLoginMigration(sourceConnectionString: string, targetConnectionString: string, loginList: string[], aadDomainName: string): Promise<StartLoginMigrationResult | undefined>;
|
||||
validateLoginMigration(sourceConnectionString: string, targetConnectionString: string, loginList: string[], aadDomainName: string): Promise<StartLoginMigrationResult | undefined>;
|
||||
migrateLogins(sourceConnectionString: string, targetConnectionString: string, loginList: string[], aadDomainName: string): Promise<StartLoginMigrationResult | undefined>;
|
||||
establishUserMapping(sourceConnectionString: string, targetConnectionString: string, loginList: string[], aadDomainName: string): Promise<StartLoginMigrationResult | undefined>;
|
||||
migrateServerRolesAndSetPermissions(sourceConnectionString: string, targetConnectionString: string, loginList: string[], aadDomainName: string): Promise<StartLoginMigrationResult | undefined>;
|
||||
migrateCertificate(
|
||||
encryptedDatabases: string[],
|
||||
sourceSqlConnectionString: string,
|
||||
targetSubscriptionId: string,
|
||||
targetResourceGroupName: string,
|
||||
targetManagedInstanceName: string,
|
||||
networkSharePath: string,
|
||||
accessToken: string,
|
||||
reportUpdate: (dbName: string, succeeded: boolean, message: string) => void): Promise<TdeMigrationResult | undefined>;
|
||||
}
|
||||
|
||||
export interface TdeMigrationRequest {
|
||||
encryptedDatabases: string[];
|
||||
sourceSqlConnectionString: string;
|
||||
targetSubscriptionId: string;
|
||||
targetResourceGroupName: string;
|
||||
targetManagedInstanceName: string;
|
||||
}
|
||||
|
||||
export interface TdeMigrationEntryResult {
|
||||
dbName: string;
|
||||
success: boolean;
|
||||
message: string;
|
||||
}
|
||||
|
||||
export interface TdeMigrationResult {
|
||||
migrationStatuses: TdeMigrationEntryResult[];
|
||||
}
|
||||
|
||||
export namespace TdeMigrateRequest {
|
||||
export const type = new RequestType<TdeMigrationParams, TdeMigrationResult, void, void>('migration/tdemigration');
|
||||
}
|
||||
|
||||
export interface TdeMigrationParams {
|
||||
encryptedDatabases: string[];
|
||||
sourceSqlConnectionString: string;
|
||||
targetSubscriptionId: string;
|
||||
targetResourceGroupName: string;
|
||||
targetManagedInstanceName: string;
|
||||
networkSharePath: string;
|
||||
networkShareDomain: string;
|
||||
networkShareUserName: string;
|
||||
networkSharePassword: string;
|
||||
accessToken: string;
|
||||
}
|
||||
|
||||
export namespace TdeMigrateProgressEvent {
|
||||
export const type = new NotificationType<TdeMigrateProgressParams, void>('migration/tdemigrationprogress');
|
||||
}
|
||||
|
||||
|
||||
export interface TdeMigrateProgressParams {
|
||||
name: string;
|
||||
success: boolean;
|
||||
message: string;
|
||||
}
|
||||
320
extensions/sql-migration/src/service/features.ts
Normal file
320
extensions/sql-migration/src/service/features.ts
Normal file
@@ -0,0 +1,320 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { SqlOpsDataClient, SqlOpsFeature } from 'dataprotocol-client';
|
||||
import {
|
||||
ClientCapabilities,
|
||||
RPCMessageType,
|
||||
ServerCapabilities,
|
||||
} from 'vscode-languageclient';
|
||||
|
||||
import * as UUID from 'vscode-languageclient/lib/utils/uuid';
|
||||
import { Disposable } from 'vscode';
|
||||
|
||||
import * as contracts from './contracts';
|
||||
import { migrationServiceProvider } from './provider';
|
||||
|
||||
export enum ApiType {
|
||||
SqlMigrationProvider = 'SqlMigrationProvider',
|
||||
}
|
||||
|
||||
|
||||
export abstract class MigrationExtensionService extends SqlOpsFeature<undefined> {
|
||||
abstract providerId: ApiType;
|
||||
}
|
||||
|
||||
export class SqlMigrationService extends MigrationExtensionService implements contracts.ISqlMigrationService {
|
||||
private _reportUpdate: ((dbName: string, succeeded: boolean, error: string) => void) | undefined = undefined;
|
||||
|
||||
override providerId = ApiType.SqlMigrationProvider;
|
||||
|
||||
private static readonly messagesTypes: RPCMessageType[] = [
|
||||
contracts.GetSqlMigrationAssessmentItemsRequest.type,
|
||||
contracts.GetSqlMigrationSkuRecommendationsRequest.type,
|
||||
contracts.SqlMigrationStartPerfDataCollectionRequest.type,
|
||||
contracts.SqlMigrationRefreshPerfDataCollectionRequest.type,
|
||||
contracts.SqlMigrationStopPerfDataCollectionRequest.type,
|
||||
contracts.StartLoginMigrationRequest.type,
|
||||
contracts.ValidateLoginMigrationRequest.type,
|
||||
contracts.MigrateLoginsRequest.type,
|
||||
contracts.EstablishUserMappingRequest.type,
|
||||
contracts.MigrateServerRolesAndSetPermissionsRequest.type,
|
||||
contracts.TdeMigrateRequest.type
|
||||
];
|
||||
|
||||
constructor(client: SqlOpsDataClient) {
|
||||
super(client, SqlMigrationService.messagesTypes);
|
||||
}
|
||||
|
||||
public initialize(capabilities: ServerCapabilities): void {
|
||||
this.register(this.messages, {
|
||||
id: UUID.generateUuid(),
|
||||
registerOptions: undefined
|
||||
});
|
||||
|
||||
this._client.onNotification(contracts.TdeMigrateProgressEvent.type, e => {
|
||||
if (this._reportUpdate === undefined) {
|
||||
return;
|
||||
}
|
||||
this._reportUpdate(e.name, e.success, e.message);
|
||||
});
|
||||
}
|
||||
|
||||
protected registerProvider(options: undefined): Disposable {
|
||||
migrationServiceProvider.addService(this);
|
||||
return this;
|
||||
}
|
||||
|
||||
public fillClientCapabilities(capabilities: ClientCapabilities): void {
|
||||
// this isn't explicitly necessary
|
||||
}
|
||||
|
||||
async getAssessments(connectionString: string, databases: string[], xEventsFilesFolderPath: string): Promise<contracts.AssessmentResult | undefined> {
|
||||
let params: contracts.SqlMigrationAssessmentParams = { connectionString: connectionString, databases: databases, xEventsFilesFolderPath: xEventsFilesFolderPath };
|
||||
try {
|
||||
return this._client.sendRequest(contracts.GetSqlMigrationAssessmentItemsRequest.type, params);
|
||||
}
|
||||
catch (e) {
|
||||
this._client.logFailedRequest(contracts.GetSqlMigrationAssessmentItemsRequest.type, e);
|
||||
}
|
||||
|
||||
return undefined;
|
||||
}
|
||||
|
||||
async getSkuRecommendations(
|
||||
dataFolder: string,
|
||||
perfQueryIntervalInSec: number,
|
||||
targetPlatforms: string[],
|
||||
targetSqlInstance: string,
|
||||
targetPercentile: number,
|
||||
scalingFactor: number,
|
||||
startTime: string,
|
||||
endTime: string,
|
||||
includePreviewSkus: boolean,
|
||||
databaseAllowList: string[]): Promise<contracts.SkuRecommendationResult | undefined> {
|
||||
let params: contracts.SqlMigrationSkuRecommendationsParams = {
|
||||
dataFolder,
|
||||
perfQueryIntervalInSec,
|
||||
targetPlatforms,
|
||||
targetSqlInstance,
|
||||
targetPercentile,
|
||||
scalingFactor,
|
||||
startTime,
|
||||
endTime,
|
||||
includePreviewSkus,
|
||||
databaseAllowList
|
||||
};
|
||||
|
||||
try {
|
||||
return this._client.sendRequest(contracts.GetSqlMigrationSkuRecommendationsRequest.type, params);
|
||||
}
|
||||
catch (e) {
|
||||
this._client.logFailedRequest(contracts.GetSqlMigrationSkuRecommendationsRequest.type, e);
|
||||
}
|
||||
|
||||
return undefined;
|
||||
}
|
||||
|
||||
async startPerfDataCollection(
|
||||
connectionString: string,
|
||||
dataFolder: string,
|
||||
perfQueryIntervalInSec: number,
|
||||
staticQueryIntervalInSec: number,
|
||||
numberOfIterations: number): Promise<contracts.StartPerfDataCollectionResult | undefined> {
|
||||
let params: contracts.SqlMigrationStartPerfDataCollectionParams = {
|
||||
connectionString: connectionString,
|
||||
dataFolder,
|
||||
perfQueryIntervalInSec,
|
||||
staticQueryIntervalInSec,
|
||||
numberOfIterations
|
||||
};
|
||||
|
||||
try {
|
||||
return this._client.sendRequest(contracts.SqlMigrationStartPerfDataCollectionRequest.type, params);
|
||||
}
|
||||
catch (e) {
|
||||
this._client.logFailedRequest(contracts.SqlMigrationStartPerfDataCollectionRequest.type, e);
|
||||
}
|
||||
|
||||
return undefined;
|
||||
}
|
||||
|
||||
async stopPerfDataCollection(): Promise<contracts.StopPerfDataCollectionResult | undefined> {
|
||||
let params: contracts.SqlMigrationStopPerfDataCollectionParams = {};
|
||||
|
||||
try {
|
||||
return this._client.sendRequest(contracts.SqlMigrationStopPerfDataCollectionRequest.type, params);
|
||||
}
|
||||
catch (e) {
|
||||
this._client.logFailedRequest(contracts.SqlMigrationStopPerfDataCollectionRequest.type, e);
|
||||
}
|
||||
|
||||
return undefined;
|
||||
}
|
||||
|
||||
async refreshPerfDataCollection(lastRefreshedTime: Date): Promise<contracts.RefreshPerfDataCollectionResult | undefined> {
|
||||
let params: contracts.SqlMigrationStopPerfDataCollectionParams = {
|
||||
lastRefreshedTime
|
||||
};
|
||||
|
||||
try {
|
||||
return this._client.sendRequest(contracts.SqlMigrationRefreshPerfDataCollectionRequest.type, params);
|
||||
}
|
||||
catch (e) {
|
||||
this._client.logFailedRequest(contracts.SqlMigrationRefreshPerfDataCollectionRequest.type, e);
|
||||
}
|
||||
|
||||
return undefined;
|
||||
}
|
||||
|
||||
async startLoginMigration(
|
||||
sourceConnectionString: string,
|
||||
targetConnectionString: string,
|
||||
loginList: string[],
|
||||
aadDomainName: string): Promise<contracts.StartLoginMigrationResult | undefined> {
|
||||
let params: contracts.StartLoginMigrationsParams = {
|
||||
sourceConnectionString,
|
||||
targetConnectionString,
|
||||
loginList,
|
||||
aadDomainName
|
||||
};
|
||||
|
||||
try {
|
||||
return this._client.sendRequest(contracts.StartLoginMigrationRequest.type, params);
|
||||
}
|
||||
catch (e) {
|
||||
this._client.logFailedRequest(contracts.StartLoginMigrationRequest.type, e);
|
||||
}
|
||||
|
||||
return undefined;
|
||||
}
|
||||
|
||||
async validateLoginMigration(
|
||||
sourceConnectionString: string,
|
||||
targetConnectionString: string,
|
||||
loginList: string[],
|
||||
aadDomainName: string): Promise<contracts.StartLoginMigrationResult | undefined> {
|
||||
let params: contracts.StartLoginMigrationsParams = {
|
||||
sourceConnectionString,
|
||||
targetConnectionString,
|
||||
loginList,
|
||||
aadDomainName
|
||||
};
|
||||
|
||||
try {
|
||||
return this._client.sendRequest(contracts.ValidateLoginMigrationRequest.type, params);
|
||||
|
||||
}
|
||||
catch (e) {
|
||||
this._client.logFailedRequest(contracts.ValidateLoginMigrationRequest.type, e);
|
||||
}
|
||||
|
||||
return undefined;
|
||||
}
|
||||
|
||||
async migrateLogins(
|
||||
sourceConnectionString: string,
|
||||
targetConnectionString: string,
|
||||
loginList: string[],
|
||||
aadDomainName: string): Promise<contracts.StartLoginMigrationResult | undefined> {
|
||||
let params: contracts.StartLoginMigrationsParams = {
|
||||
sourceConnectionString,
|
||||
targetConnectionString,
|
||||
loginList,
|
||||
aadDomainName
|
||||
};
|
||||
|
||||
try {
|
||||
return this._client.sendRequest(contracts.MigrateLoginsRequest.type, params);
|
||||
}
|
||||
catch (e) {
|
||||
this._client.logFailedRequest(contracts.MigrateLoginsRequest.type, e);
|
||||
}
|
||||
|
||||
return undefined;
|
||||
}
|
||||
|
||||
async establishUserMapping(
|
||||
sourceConnectionString: string,
|
||||
targetConnectionString: string,
|
||||
loginList: string[],
|
||||
aadDomainName: string): Promise<contracts.StartLoginMigrationResult | undefined> {
|
||||
let params: contracts.StartLoginMigrationsParams = {
|
||||
sourceConnectionString,
|
||||
targetConnectionString,
|
||||
loginList,
|
||||
aadDomainName
|
||||
};
|
||||
|
||||
try {
|
||||
return this._client.sendRequest(contracts.EstablishUserMappingRequest.type, params);
|
||||
}
|
||||
catch (e) {
|
||||
this._client.logFailedRequest(contracts.EstablishUserMappingRequest.type, e);
|
||||
}
|
||||
|
||||
return undefined;
|
||||
}
|
||||
|
||||
async migrateServerRolesAndSetPermissions(
|
||||
sourceConnectionString: string,
|
||||
targetConnectionString: string,
|
||||
loginList: string[],
|
||||
aadDomainName: string): Promise<contracts.StartLoginMigrationResult | undefined> {
|
||||
let params: contracts.StartLoginMigrationsParams = {
|
||||
sourceConnectionString,
|
||||
targetConnectionString,
|
||||
loginList,
|
||||
aadDomainName
|
||||
};
|
||||
|
||||
try {
|
||||
return this._client.sendRequest(contracts.MigrateServerRolesAndSetPermissionsRequest.type, params);
|
||||
}
|
||||
catch (e) {
|
||||
this._client.logFailedRequest(contracts.MigrateServerRolesAndSetPermissionsRequest.type, e);
|
||||
}
|
||||
|
||||
return undefined;
|
||||
}
|
||||
|
||||
async migrateCertificate(
|
||||
tdeEnabledDatabases: string[],
|
||||
sourceSqlConnectionString: string,
|
||||
targetSubscriptionId: string,
|
||||
targetResourceGroupName: string,
|
||||
targetManagedInstanceName: string,
|
||||
networkSharePath: string,
|
||||
accessToken: string,
|
||||
reportUpdate: (dbName: string, succeeded: boolean, message: string) => void): Promise<contracts.TdeMigrationResult | undefined> {
|
||||
|
||||
this._reportUpdate = reportUpdate;
|
||||
let params: contracts.TdeMigrationParams = {
|
||||
encryptedDatabases: tdeEnabledDatabases,
|
||||
sourceSqlConnectionString: sourceSqlConnectionString,
|
||||
targetSubscriptionId: targetSubscriptionId,
|
||||
targetResourceGroupName: targetResourceGroupName,
|
||||
targetManagedInstanceName: targetManagedInstanceName,
|
||||
networkSharePath: networkSharePath,
|
||||
networkShareDomain: 'a', // Will remove this on the next STS version
|
||||
networkShareUserName: 'b',
|
||||
networkSharePassword: 'c',
|
||||
accessToken: accessToken
|
||||
};
|
||||
|
||||
try {
|
||||
// This call needs to be awaited so, the updates are sent during the execution of the task.
|
||||
// If the task is not await, the finally block will execute and no update will be sent.
|
||||
const result = await this._client.sendRequest(contracts.TdeMigrateRequest.type, params);
|
||||
return result;
|
||||
}
|
||||
catch (e) {
|
||||
this._client.logFailedRequest(contracts.TdeMigrateRequest.type, e);
|
||||
}
|
||||
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
|
||||
46
extensions/sql-migration/src/service/provider.ts
Normal file
46
extensions/sql-migration/src/service/provider.ts
Normal file
@@ -0,0 +1,46 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { ApiType, MigrationExtensionService } from './features';
|
||||
import * as constants from '../constants/strings';
|
||||
import * as vscode from 'vscode';
|
||||
|
||||
export class MigrationServiceProvider {
|
||||
private services: Map<ApiType, MigrationExtensionService> = new Map();
|
||||
|
||||
constructor() {
|
||||
}
|
||||
|
||||
public addService(service: MigrationExtensionService) {
|
||||
this.services.set(service.providerId, service);
|
||||
}
|
||||
|
||||
public async getService(serviceId: ApiType): Promise<MigrationExtensionService> {
|
||||
if (this.services.has(serviceId)) {
|
||||
return this.services.get(serviceId)!;
|
||||
}
|
||||
return this.waitUntilProviderReady(serviceId);
|
||||
}
|
||||
|
||||
public async waitUntilProviderReady(serviceId: ApiType): Promise<MigrationExtensionService> {
|
||||
const service = await vscode.window.withProgress({
|
||||
location: vscode.ProgressLocation.Notification,
|
||||
title: constants.waitingForService(serviceId),
|
||||
cancellable: false
|
||||
}, (progress, token) => {
|
||||
return new Promise<MigrationExtensionService>(resolve => {
|
||||
const interval = setInterval(() => {
|
||||
if (this.services.has(serviceId)) {
|
||||
clearInterval(interval);
|
||||
resolve(this.services.get(serviceId)!);
|
||||
}
|
||||
}, 250);
|
||||
});
|
||||
});
|
||||
return service;
|
||||
}
|
||||
}
|
||||
|
||||
export const migrationServiceProvider = new MigrationServiceProvider();
|
||||
230
extensions/sql-migration/src/service/serviceClient.ts
Normal file
230
extensions/sql-migration/src/service/serviceClient.ts
Normal file
@@ -0,0 +1,230 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { SqlOpsDataClient, ClientOptions } from 'dataprotocol-client';
|
||||
import { ServerProvider, Events, LogLevel, IConfig } from '@microsoft/ads-service-downloader';
|
||||
import { ServerOptions, TransportKind } from 'vscode-languageclient';
|
||||
import * as vscode from 'vscode';
|
||||
import * as nls from 'vscode-nls';
|
||||
const localize = nls.loadMessageBundle();
|
||||
import * as path from 'path';
|
||||
import { EventAndListener } from 'eventemitter2';
|
||||
import { SqlMigrationService } from './features';
|
||||
import { promises as fs } from 'fs';
|
||||
import * as constants from '../constants/strings';
|
||||
import { IMessage } from './contracts';
|
||||
import { ErrorAction, CloseAction } from 'vscode-languageclient';
|
||||
import { env } from 'process';
|
||||
import { exists } from './utils';
|
||||
import { logError, TelemetryViews } from '../telemetry';
|
||||
|
||||
export class ServiceClient {
|
||||
private statusView: vscode.StatusBarItem;
|
||||
|
||||
constructor(
|
||||
private outputChannel: vscode.OutputChannel,
|
||||
) {
|
||||
this.statusView = vscode.window.createStatusBarItem(vscode.StatusBarAlignment.Left);
|
||||
}
|
||||
|
||||
public async startService(context: vscode.ExtensionContext): Promise<SqlOpsDataClient | undefined> {
|
||||
const rawConfig = await fs.readFile(path.join(context.extensionPath, 'config.json'));
|
||||
let clientOptions: ClientOptions = this.createClientOptions();
|
||||
try {
|
||||
let client: SqlOpsDataClient;
|
||||
let serviceBinary: string = '';
|
||||
let downloadBinary = true;
|
||||
if (env['ADS_MIGRATIONSERVICE']) {
|
||||
const config = <IConfig>JSON.parse(rawConfig.toString());
|
||||
for (let executableFile of config.executableFiles) {
|
||||
const executableFilePath = path.join(env['ADS_MIGRATIONSERVICE'], executableFile);
|
||||
if (await exists(executableFilePath)) {
|
||||
downloadBinary = false;
|
||||
serviceBinary = executableFilePath;
|
||||
}
|
||||
}
|
||||
if (!downloadBinary) {
|
||||
vscode.window.showInformationMessage('Using Migration service found at: ' + serviceBinary).then((v) => { }, (r) => { });
|
||||
} else {
|
||||
vscode.window.showErrorMessage('Failed to find migration service binary falling back to downloaded binary').then((v) => { }, (r) => { });
|
||||
}
|
||||
}
|
||||
if (downloadBinary) {
|
||||
serviceBinary = await this.downloadBinaries(context, rawConfig);
|
||||
}
|
||||
let serverOptions = this.generateServerOptions(serviceBinary, context);
|
||||
client = new SqlOpsDataClient(constants.serviceName, serverOptions, clientOptions);
|
||||
client.onReady().then(() => {
|
||||
this.statusView.text = localize('serviceStarted', "{0} Started", constants.serviceName);
|
||||
setTimeout(() => {
|
||||
this.statusView.hide();
|
||||
}, 1500);
|
||||
}).catch(e => {
|
||||
console.error(e);
|
||||
});
|
||||
this.statusView.show();
|
||||
this.statusView.text = localize('serviceStarting', "Starting {0}", constants.serviceName);
|
||||
let disposable = client.start();
|
||||
context.subscriptions.push(disposable);
|
||||
return client;
|
||||
}
|
||||
catch (error) {
|
||||
await vscode.window.showErrorMessage(localize('flatFileImport.serviceStartFailed', "Failed to start {0}: {1}", constants.serviceName, error.stack.toString()));
|
||||
logError(TelemetryViews.SqlServerDashboard, error.stack.toString(), error);
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
|
||||
public async downloadBinaries(context: vscode.ExtensionContext, rawConfig: Buffer): Promise<string> {
|
||||
const config = JSON.parse(rawConfig.toString());
|
||||
config.installDirectory = path.join(context.extensionPath, config.installDirectory);
|
||||
config.proxy = vscode.workspace.getConfiguration('http').get('proxy');
|
||||
config.strictSSL = vscode.workspace.getConfiguration('http').get('proxyStrictSSL') || true;
|
||||
const serverdownloader = new ServerProvider(config);
|
||||
serverdownloader.eventEmitter.onAny(this.generateHandleServerProviderEvent());
|
||||
return serverdownloader.getOrDownloadServer();
|
||||
}
|
||||
|
||||
private createClientOptions(): ClientOptions {
|
||||
return {
|
||||
providerId: constants.providerId,
|
||||
errorHandler: new LanguageClientErrorHandler(),
|
||||
synchronize: {
|
||||
configurationSection: [constants.extensionConfigSectionName, constants.sqlConfigSectionName]
|
||||
},
|
||||
features: [
|
||||
// we only want to add new features
|
||||
SqlMigrationService,
|
||||
],
|
||||
outputChannel: this.outputChannel
|
||||
};
|
||||
}
|
||||
|
||||
private generateServerOptions(executablePath: string, context: vscode.ExtensionContext): ServerOptions {
|
||||
let launchArgs = [];
|
||||
launchArgs.push(`--locale`, vscode.env.language);
|
||||
launchArgs.push('--log-file', path.join(context.logUri.fsPath));
|
||||
launchArgs.push('--tracing-level', this.getConfigTracingLevel());
|
||||
launchArgs.push('--autoflush-log');
|
||||
return { command: executablePath, args: launchArgs, transport: TransportKind.stdio };
|
||||
}
|
||||
|
||||
private getConfigTracingLevel(): TracingLevel {
|
||||
let config = vscode.workspace.getConfiguration('mssql');
|
||||
if (config) {
|
||||
return config['tracingLevel'];
|
||||
} else {
|
||||
return TracingLevel.Critical;
|
||||
}
|
||||
}
|
||||
|
||||
private generateHandleServerProviderEvent(): EventAndListener {
|
||||
let dots = 0;
|
||||
return (e: string | string[], ...args: any[]) => {
|
||||
switch (e) {
|
||||
case Events.INSTALL_START:
|
||||
this.outputChannel.show(true);
|
||||
this.statusView.show();
|
||||
this.outputChannel.appendLine(localize('installingServiceDetailed', "Installing {0} to {1}", constants.serviceName, args[0]));
|
||||
this.statusView.text = localize('installingService', "Installing {0} Service", constants.serviceName);
|
||||
break;
|
||||
case Events.INSTALL_END:
|
||||
this.outputChannel.appendLine(localize('serviceInstalled', "Installed {0}", constants.serviceName));
|
||||
break;
|
||||
case Events.DOWNLOAD_START:
|
||||
this.outputChannel.appendLine(localize('downloadingService', "Downloading {0}", args[0]));
|
||||
this.outputChannel.append(localize('downloadingServiceSize', "({0} KB)", Math.ceil(args[1] / 1024).toLocaleString(vscode.env.language)));
|
||||
this.statusView.text = localize('downloadingServiceStatus', "Downloading {0}", constants.serviceName);
|
||||
break;
|
||||
case Events.DOWNLOAD_PROGRESS:
|
||||
let newDots = Math.ceil(args[0] / 5);
|
||||
if (newDots > dots) {
|
||||
this.outputChannel.append('.'.repeat(newDots - dots));
|
||||
dots = newDots;
|
||||
}
|
||||
break;
|
||||
case Events.DOWNLOAD_END:
|
||||
this.outputChannel.appendLine(localize('downloadingServiceComplete', "Done downloading {0}", constants.serviceName));
|
||||
break;
|
||||
case Events.ENTRY_EXTRACTED:
|
||||
this.outputChannel.appendLine(localize('entryExtractedChannelMsg', "Extracted {0} ({1}/{2})", args[0], args[1], args[2]));
|
||||
break;
|
||||
case Events.LOG_EMITTED:
|
||||
if (args[0] >= LogLevel.Warning) {
|
||||
this.outputChannel.appendLine(args[1]);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle Language Service client errors
|
||||
*/
|
||||
class LanguageClientErrorHandler {
|
||||
|
||||
/**
|
||||
* Creates an instance of LanguageClientErrorHandler.
|
||||
* @memberOf LanguageClientErrorHandler
|
||||
*/
|
||||
constructor() {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Show an error message prompt with a link to known issues wiki page
|
||||
* @memberOf LanguageClientErrorHandler
|
||||
*/
|
||||
showOnErrorPrompt(error: Error): void {
|
||||
// TODO add telemetry
|
||||
// Telemetry.sendTelemetryEvent('SqlToolsServiceCrash');
|
||||
console.log(error);
|
||||
vscode.window.showErrorMessage(
|
||||
constants.serviceCrashMessage(error.message),
|
||||
).then(() => { }, () => { });
|
||||
}
|
||||
|
||||
/**
|
||||
* Callback for language service client error
|
||||
*
|
||||
* @memberOf LanguageClientErrorHandler
|
||||
*/
|
||||
error(error: Error, message: IMessage, count: number): ErrorAction {
|
||||
this.showOnErrorPrompt(error);
|
||||
|
||||
// we don't retry running the service since crashes leave the extension
|
||||
// in a bad, unrecovered state
|
||||
return ErrorAction.Shutdown;
|
||||
}
|
||||
|
||||
/**
|
||||
* Callback for language service client closed
|
||||
*
|
||||
* @memberOf LanguageClientErrorHandler
|
||||
*/
|
||||
closed(): CloseAction {
|
||||
this.showOnErrorPrompt({ name: 'Service crashed', message: constants.serviceCrashed });
|
||||
|
||||
// we don't retry running the service since crashes leave the extension
|
||||
// in a bad, unrecovered state
|
||||
return CloseAction.DoNotRestart;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The tracing level defined in the package.json
|
||||
*/
|
||||
enum TracingLevel {
|
||||
All = 'All',
|
||||
Off = 'Off',
|
||||
Critical = 'Critical',
|
||||
Error = 'Error',
|
||||
Warning = 'Warning',
|
||||
Information = 'Information',
|
||||
Verbose = 'Verbose'
|
||||
}
|
||||
16
extensions/sql-migration/src/service/utils.ts
Normal file
16
extensions/sql-migration/src/service/utils.ts
Normal file
@@ -0,0 +1,16 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { promises as fs } from 'fs';
|
||||
|
||||
|
||||
export async function exists(path: string): Promise<boolean> {
|
||||
try {
|
||||
await fs.access(path);
|
||||
return true;
|
||||
} catch (e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -6,7 +6,7 @@
|
||||
import * as azdata from 'azdata';
|
||||
import * as vscode from 'vscode';
|
||||
import * as utils from '../api/utils';
|
||||
import * as mssql from 'mssql';
|
||||
import * as contracts from '../service/contracts';
|
||||
import { MigrationWizardPage } from '../models/migrationWizardPage';
|
||||
import { MigrationStateModel, MigrationTargetType, PerformanceDataSourceOptions, StateChangeEvent, AssessmentRuleId } from '../models/stateMachine';
|
||||
import { AssessmentResultsDialog } from '../dialog/assessmentResults/assessmentResultsDialog';
|
||||
@@ -708,12 +708,12 @@ export class SKURecommendationPage extends MigrationWizardPage {
|
||||
constants.SKU_RECOMMENDATION_NO_RECOMMENDATION;
|
||||
}
|
||||
else {
|
||||
const serviceTier = recommendation.targetSku.category?.sqlServiceTier === mssql.AzureSqlPaaSServiceTier.GeneralPurpose
|
||||
const serviceTier = recommendation.targetSku.category?.sqlServiceTier === contracts.AzureSqlPaaSServiceTier.GeneralPurpose
|
||||
? constants.GENERAL_PURPOSE
|
||||
: constants.BUSINESS_CRITICAL;
|
||||
const hardwareType = recommendation.targetSku.category?.hardwareType === mssql.AzureSqlPaaSHardwareType.Gen5
|
||||
const hardwareType = recommendation.targetSku.category?.hardwareType === contracts.AzureSqlPaaSHardwareType.Gen5
|
||||
? constants.GEN5
|
||||
: recommendation.targetSku.category?.hardwareType === mssql.AzureSqlPaaSHardwareType.PremiumSeries
|
||||
: recommendation.targetSku.category?.hardwareType === contracts.AzureSqlPaaSHardwareType.PremiumSeries
|
||||
? constants.PREMIUM_SERIES
|
||||
: constants.PREMIUM_SERIES_MEMORY_OPTIMIZED;
|
||||
this._rbg.cards[index].descriptions[CardDescriptionIndex.SKU_RECOMMENDATION].textValue =
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
import * as azdata from 'azdata';
|
||||
import * as vscode from 'vscode';
|
||||
import * as mssql from 'mssql';
|
||||
import { MigrationStateModel, NetworkContainerType, Page } from '../models/stateMachine';
|
||||
import * as loc from '../constants/strings';
|
||||
import { MigrationWizardPage } from '../models/migrationWizardPage';
|
||||
@@ -35,19 +34,13 @@ export class WizardController {
|
||||
}
|
||||
|
||||
public async openWizard(): Promise<void> {
|
||||
const api = (await vscode.extensions.getExtension(mssql.extension.name)?.activate()) as mssql.IExtension;
|
||||
if (api) {
|
||||
this.extensionContext.subscriptions.push(this._model);
|
||||
await this.createWizard(this._model);
|
||||
}
|
||||
this.extensionContext.subscriptions.push(this._model);
|
||||
await this.createWizard(this._model);
|
||||
}
|
||||
|
||||
public async openLoginWizard(): Promise<void> {
|
||||
const api = (await vscode.extensions.getExtension(mssql.extension.name)?.activate()) as mssql.IExtension;
|
||||
if (api) {
|
||||
this.extensionContext.subscriptions.push(this._model);
|
||||
await this.createLoginWizard(this._model);
|
||||
}
|
||||
this.extensionContext.subscriptions.push(this._model);
|
||||
await this.createLoginWizard(this._model);
|
||||
}
|
||||
|
||||
private async createWizard(stateModel: MigrationStateModel): Promise<void> {
|
||||
|
||||
@@ -9,6 +9,35 @@
|
||||
dependencies:
|
||||
"@vscode/extension-telemetry" "0.6.1"
|
||||
|
||||
"@microsoft/ads-service-downloader@^1.1.0":
|
||||
version "1.1.0"
|
||||
resolved "https://registry.yarnpkg.com/@microsoft/ads-service-downloader/-/ads-service-downloader-1.1.0.tgz#c51ba28bc17a137e92f99a2b050821965588d7d6"
|
||||
integrity sha512-WSJ4NZvpuebg/CjlTUpqXPUYV5y5mSNJQE/dd+kuOt0nkMYzCmp5IYyFFpMFUR1CiZy/19V7DH2wGdy60+9SRg==
|
||||
dependencies:
|
||||
async-retry "^1.2.3"
|
||||
eventemitter2 "^5.0.1"
|
||||
http-proxy-agent "^5.0.0"
|
||||
https-proxy-agent "^5.0.1"
|
||||
mkdirp "1.0.4"
|
||||
tar "^6.1.11"
|
||||
tmp "^0.0.33"
|
||||
yauzl "^2.10.0"
|
||||
|
||||
"@tootallnate/once@2":
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/@tootallnate/once/-/once-2.0.0.tgz#f544a148d3ab35801c1f633a7441fd87c2e484bf"
|
||||
integrity sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==
|
||||
|
||||
"@tootallnate/once@2":
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/@tootallnate/once/-/once-2.0.0.tgz#f544a148d3ab35801c1f633a7441fd87c2e484bf"
|
||||
integrity sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==
|
||||
|
||||
"@tootallnate/once@2":
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/@tootallnate/once/-/once-2.0.0.tgz#f544a148d3ab35801c1f633a7441fd87c2e484bf"
|
||||
integrity sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==
|
||||
|
||||
"@types/uuid@^8.3.1":
|
||||
version "8.3.1"
|
||||
resolved "https://registry.yarnpkg.com/@types/uuid/-/uuid-8.3.1.tgz#1a32969cf8f0364b3d8c8af9cc3555b7805df14f"
|
||||
@@ -19,12 +48,234 @@
|
||||
resolved "https://registry.yarnpkg.com/@vscode/extension-telemetry/-/extension-telemetry-0.6.1.tgz#f8d1f7145baf932b75077c48107edff48501fc14"
|
||||
integrity sha512-Y4Oc8yGURGVF4WhCZcu+EVy+MAIeQDLDVeDlLn59H0C1w+7xr8dL2ZtDBioy+Hog1Edrd6zOwr3Na7xe1iC/UA==
|
||||
|
||||
agent-base@6:
|
||||
version "6.0.2"
|
||||
resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-6.0.2.tgz#49fff58577cfee3f37176feab4c22e00f86d7f77"
|
||||
integrity sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==
|
||||
dependencies:
|
||||
debug "4"
|
||||
|
||||
async-retry@^1.2.3:
|
||||
version "1.3.3"
|
||||
resolved "https://registry.yarnpkg.com/async-retry/-/async-retry-1.3.3.tgz#0e7f36c04d8478e7a58bdbed80cedf977785f280"
|
||||
integrity sha512-wfr/jstw9xNi/0teMHrRW7dsz3Lt5ARhYNZ2ewpadnhaIp5mbALhOAP+EAdsC7t4Z6wqsDVv9+W6gm1Dk9mEyw==
|
||||
dependencies:
|
||||
retry "0.13.1"
|
||||
|
||||
buffer-crc32@~0.2.3:
|
||||
version "0.2.13"
|
||||
resolved "https://registry.yarnpkg.com/buffer-crc32/-/buffer-crc32-0.2.13.tgz#0d333e3f00eac50aa1454abd30ef8c2a5d9a7242"
|
||||
integrity sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==
|
||||
|
||||
chownr@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/chownr/-/chownr-2.0.0.tgz#15bfbe53d2eab4cf70f18a8cd68ebe5b3cb1dece"
|
||||
integrity sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==
|
||||
|
||||
"dataprotocol-client@github:Microsoft/sqlops-dataprotocolclient#1.3.1":
|
||||
version "1.3.1"
|
||||
resolved "https://codeload.github.com/Microsoft/sqlops-dataprotocolclient/tar.gz/2df6982e07c0208c2b8a5f8cd4b3d65944138d15"
|
||||
dependencies:
|
||||
vscode-languageclient "5.2.1"
|
||||
|
||||
debug@4:
|
||||
version "4.3.4"
|
||||
resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865"
|
||||
integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==
|
||||
dependencies:
|
||||
ms "2.1.2"
|
||||
|
||||
eventemitter2@^5.0.1:
|
||||
version "5.0.1"
|
||||
resolved "https://registry.yarnpkg.com/eventemitter2/-/eventemitter2-5.0.1.tgz#6197a095d5fb6b57e8942f6fd7eaad63a09c9452"
|
||||
integrity sha512-5EM1GHXycJBS6mauYAbVKT1cVs7POKWb2NXD4Vyt8dDqeZa7LaDK1/sjtL+Zb0lzTpSNil4596Dyu97hz37QLg==
|
||||
|
||||
fd-slicer@~1.1.0:
|
||||
version "1.1.0"
|
||||
resolved "https://registry.yarnpkg.com/fd-slicer/-/fd-slicer-1.1.0.tgz#25c7c89cb1f9077f8891bbe61d8f390eae256f1e"
|
||||
integrity sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g==
|
||||
dependencies:
|
||||
pend "~1.2.0"
|
||||
|
||||
fs-minipass@^2.0.0:
|
||||
version "2.1.0"
|
||||
resolved "https://registry.yarnpkg.com/fs-minipass/-/fs-minipass-2.1.0.tgz#7f5036fdbf12c63c169190cbe4199c852271f9fb"
|
||||
integrity sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==
|
||||
dependencies:
|
||||
minipass "^3.0.0"
|
||||
|
||||
http-proxy-agent@^5.0.0:
|
||||
version "5.0.0"
|
||||
resolved "https://registry.yarnpkg.com/http-proxy-agent/-/http-proxy-agent-5.0.0.tgz#5129800203520d434f142bc78ff3c170800f2b43"
|
||||
integrity sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w==
|
||||
dependencies:
|
||||
"@tootallnate/once" "2"
|
||||
agent-base "6"
|
||||
debug "4"
|
||||
|
||||
https-proxy-agent@^5.0.1:
|
||||
version "5.0.1"
|
||||
resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz#c59ef224a04fe8b754f3db0063a25ea30d0005d6"
|
||||
integrity sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==
|
||||
dependencies:
|
||||
agent-base "6"
|
||||
debug "4"
|
||||
|
||||
minipass@^3.0.0:
|
||||
version "3.3.6"
|
||||
resolved "https://registry.yarnpkg.com/minipass/-/minipass-3.3.6.tgz#7bba384db3a1520d18c9c0e5251c3444e95dd94a"
|
||||
integrity sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==
|
||||
dependencies:
|
||||
yallist "^4.0.0"
|
||||
|
||||
minipass@^4.0.0:
|
||||
version "4.0.0"
|
||||
resolved "https://registry.yarnpkg.com/minipass/-/minipass-4.0.0.tgz#7cebb0f9fa7d56f0c5b17853cbe28838a8dbbd3b"
|
||||
integrity sha512-g2Uuh2jEKoht+zvO6vJqXmYpflPqzRBT+Th2h01DKh5z7wbY/AZ2gCQ78cP70YoHPyFdY30YBV5WxgLOEwOykw==
|
||||
dependencies:
|
||||
yallist "^4.0.0"
|
||||
|
||||
minizlib@^2.1.1:
|
||||
version "2.1.2"
|
||||
resolved "https://registry.yarnpkg.com/minizlib/-/minizlib-2.1.2.tgz#e90d3466ba209b932451508a11ce3d3632145931"
|
||||
integrity sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==
|
||||
dependencies:
|
||||
minipass "^3.0.0"
|
||||
yallist "^4.0.0"
|
||||
|
||||
mkdirp@1.0.4, mkdirp@^1.0.3:
|
||||
version "1.0.4"
|
||||
resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-1.0.4.tgz#3eb5ed62622756d79a5f0e2a221dfebad75c2f7e"
|
||||
integrity sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==
|
||||
|
||||
ms@2.1.2:
|
||||
version "2.1.2"
|
||||
resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009"
|
||||
integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==
|
||||
|
||||
os-tmpdir@~1.0.2:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274"
|
||||
integrity sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g==
|
||||
|
||||
pend@~1.2.0:
|
||||
version "1.2.0"
|
||||
resolved "https://registry.yarnpkg.com/pend/-/pend-1.2.0.tgz#7a57eb550a6783f9115331fcf4663d5c8e007a50"
|
||||
integrity sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==
|
||||
|
||||
retry@0.13.1:
|
||||
version "0.13.1"
|
||||
resolved "https://registry.yarnpkg.com/retry/-/retry-0.13.1.tgz#185b1587acf67919d63b357349e03537b2484658"
|
||||
integrity sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==
|
||||
|
||||
semver@^5.5.0:
|
||||
version "5.7.1"
|
||||
resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7"
|
||||
integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==
|
||||
|
||||
tar@^6.1.11:
|
||||
version "6.1.13"
|
||||
resolved "https://registry.yarnpkg.com/tar/-/tar-6.1.13.tgz#46e22529000f612180601a6fe0680e7da508847b"
|
||||
integrity sha512-jdIBIN6LTIe2jqzay/2vtYLlBHa3JF42ot3h1dW8Q0PaAG4v8rm0cvpVePtau5C6OKXGGcgO9q2AMNSWxiLqKw==
|
||||
dependencies:
|
||||
chownr "^2.0.0"
|
||||
fs-minipass "^2.0.0"
|
||||
minipass "^4.0.0"
|
||||
minizlib "^2.1.1"
|
||||
mkdirp "^1.0.3"
|
||||
yallist "^4.0.0"
|
||||
|
||||
tmp@^0.0.33:
|
||||
version "0.0.33"
|
||||
resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.33.tgz#6d34335889768d21b2bcda0aa277ced3b1bfadf9"
|
||||
integrity sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==
|
||||
dependencies:
|
||||
os-tmpdir "~1.0.2"
|
||||
|
||||
uuid@^8.3.2:
|
||||
version "8.3.2"
|
||||
resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.3.2.tgz#80d5b5ced271bb9af6c445f21a1a04c606cefbe2"
|
||||
integrity sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==
|
||||
|
||||
vscode-jsonrpc@^4.0.0:
|
||||
version "4.0.0"
|
||||
resolved "https://registry.yarnpkg.com/vscode-jsonrpc/-/vscode-jsonrpc-4.0.0.tgz#a7bf74ef3254d0a0c272fab15c82128e378b3be9"
|
||||
integrity sha512-perEnXQdQOJMTDFNv+UF3h1Y0z4iSiaN9jIlb0OqIYgosPCZGYh/MCUlkFtV2668PL69lRDO32hmvL2yiidUYg==
|
||||
|
||||
vscode-languageclient@5.2.1:
|
||||
version "5.2.1"
|
||||
resolved "https://registry.yarnpkg.com/vscode-languageclient/-/vscode-languageclient-5.2.1.tgz#7cfc83a294c409f58cfa2b910a8cfeaad0397193"
|
||||
integrity sha512-7jrS/9WnV0ruqPamN1nE7qCxn0phkH5LjSgSp9h6qoJGoeAKzwKz/PF6M+iGA/aklx4GLZg1prddhEPQtuXI1Q==
|
||||
dependencies:
|
||||
semver "^5.5.0"
|
||||
vscode-languageserver-protocol "3.14.1"
|
||||
|
||||
vscode-languageserver-protocol@3.14.1:
|
||||
version "3.14.1"
|
||||
resolved "https://registry.yarnpkg.com/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.14.1.tgz#b8aab6afae2849c84a8983d39a1cf742417afe2f"
|
||||
integrity sha512-IL66BLb2g20uIKog5Y2dQ0IiigW0XKrvmWiOvc0yXw80z3tMEzEnHjaGAb3ENuU7MnQqgnYJ1Cl2l9RvNgDi4g==
|
||||
dependencies:
|
||||
vscode-jsonrpc "^4.0.0"
|
||||
vscode-languageserver-types "3.14.0"
|
||||
|
||||
vscode-languageserver-types@3.14.0:
|
||||
version "3.14.0"
|
||||
resolved "https://registry.yarnpkg.com/vscode-languageserver-types/-/vscode-languageserver-types-3.14.0.tgz#d3b5952246d30e5241592b6dde8280e03942e743"
|
||||
integrity sha512-lTmS6AlAlMHOvPQemVwo3CezxBp0sNB95KNPkqp3Nxd5VFEnuG1ByM0zlRWos0zjO3ZWtkvhal0COgiV1xIA4A==
|
||||
|
||||
vscode-jsonrpc@^4.0.0:
|
||||
version "4.0.0"
|
||||
resolved "https://registry.yarnpkg.com/vscode-jsonrpc/-/vscode-jsonrpc-4.0.0.tgz#a7bf74ef3254d0a0c272fab15c82128e378b3be9"
|
||||
integrity sha512-perEnXQdQOJMTDFNv+UF3h1Y0z4iSiaN9jIlb0OqIYgosPCZGYh/MCUlkFtV2668PL69lRDO32hmvL2yiidUYg==
|
||||
|
||||
vscode-languageclient@5.2.1:
|
||||
version "5.2.1"
|
||||
resolved "https://registry.yarnpkg.com/vscode-languageclient/-/vscode-languageclient-5.2.1.tgz#7cfc83a294c409f58cfa2b910a8cfeaad0397193"
|
||||
integrity sha512-7jrS/9WnV0ruqPamN1nE7qCxn0phkH5LjSgSp9h6qoJGoeAKzwKz/PF6M+iGA/aklx4GLZg1prddhEPQtuXI1Q==
|
||||
dependencies:
|
||||
semver "^5.5.0"
|
||||
vscode-languageserver-protocol "3.14.1"
|
||||
|
||||
vscode-languageserver-protocol@3.14.1:
|
||||
version "3.14.1"
|
||||
resolved "https://registry.yarnpkg.com/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.14.1.tgz#b8aab6afae2849c84a8983d39a1cf742417afe2f"
|
||||
integrity sha512-IL66BLb2g20uIKog5Y2dQ0IiigW0XKrvmWiOvc0yXw80z3tMEzEnHjaGAb3ENuU7MnQqgnYJ1Cl2l9RvNgDi4g==
|
||||
dependencies:
|
||||
vscode-jsonrpc "^4.0.0"
|
||||
vscode-languageserver-types "3.14.0"
|
||||
|
||||
vscode-languageserver-types@3.14.0:
|
||||
version "3.14.0"
|
||||
resolved "https://registry.yarnpkg.com/vscode-languageserver-types/-/vscode-languageserver-types-3.14.0.tgz#d3b5952246d30e5241592b6dde8280e03942e743"
|
||||
integrity sha512-lTmS6AlAlMHOvPQemVwo3CezxBp0sNB95KNPkqp3Nxd5VFEnuG1ByM0zlRWos0zjO3ZWtkvhal0COgiV1xIA4A==
|
||||
|
||||
vscode-nls@^4.1.2:
|
||||
version "4.1.2"
|
||||
resolved "https://registry.yarnpkg.com/vscode-nls/-/vscode-nls-4.1.2.tgz#ca8bf8bb82a0987b32801f9fddfdd2fb9fd3c167"
|
||||
integrity sha512-7bOHxPsfyuCqmP+hZXscLhiHwe7CSuFE4hyhbs22xPIhQ4jv99FcR4eBzfYYVLP356HNFpdvz63FFb/xw6T4Iw==
|
||||
|
||||
yallist@^4.0.0:
|
||||
version "4.0.0"
|
||||
resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72"
|
||||
integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==
|
||||
|
||||
yauzl@^2.10.0:
|
||||
version "2.10.0"
|
||||
resolved "https://registry.yarnpkg.com/yauzl/-/yauzl-2.10.0.tgz#c7eb17c93e112cb1086fa6d8e51fb0667b79a5f9"
|
||||
integrity sha512-p4a9I6X6nu6IhoGmBqAcbJy1mlC4j27vEPZX9F4L4/vZT3Lyq1VkFHw/V/PUcB9Buo+DG3iHkT0x3Qya58zc3g==
|
||||
dependencies:
|
||||
buffer-crc32 "~0.2.3"
|
||||
fd-slicer "~1.1.0"
|
||||
|
||||
yallist@^4.0.0:
|
||||
version "4.0.0"
|
||||
resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72"
|
||||
integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==
|
||||
|
||||
yauzl@^2.10.0:
|
||||
version "2.10.0"
|
||||
resolved "https://registry.yarnpkg.com/yauzl/-/yauzl-2.10.0.tgz#c7eb17c93e112cb1086fa6d8e51fb0667b79a5f9"
|
||||
integrity sha512-p4a9I6X6nu6IhoGmBqAcbJy1mlC4j27vEPZX9F4L4/vZT3Lyq1VkFHw/V/PUcB9Buo+DG3iHkT0x3Qya58zc3g==
|
||||
dependencies:
|
||||
buffer-crc32 "~0.2.3"
|
||||
fd-slicer "~1.1.0"
|
||||
|
||||
Reference in New Issue
Block a user