mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-02-09 17:52:34 -05:00
Junierch/mi tde (#21573)
* WIP * wip tde wizard * wip for merge w master * wip * wip share * tde wizard * PR reviews updates * PR review updates * PR updates * PR review updates * PR reviews updates * Bump STS to 4.4.0.22 * PR reviews updates * fix localize build issue * fix build issue with localize * remove unused function * Windows only flag. Bug Bash fixes * Use azdata with latest STS changes * revert azdata, other PR comments * sts and extesion version upgraded. logins back
This commit is contained in:
@@ -8,7 +8,7 @@ import * as vscode from 'vscode';
|
||||
import * as utils from '../api/utils';
|
||||
import * as mssql from 'mssql';
|
||||
import { MigrationWizardPage } from '../models/migrationWizardPage';
|
||||
import { MigrationStateModel, MigrationTargetType, PerformanceDataSourceOptions, StateChangeEvent } from '../models/stateMachine';
|
||||
import { MigrationStateModel, MigrationTargetType, PerformanceDataSourceOptions, StateChangeEvent, AssessmentRuleId } from '../models/stateMachine';
|
||||
import { AssessmentResultsDialog } from '../dialog/assessmentResults/assessmentResultsDialog';
|
||||
import { SkuRecommendationResultsDialog } from '../dialog/skuRecommendationResults/skuRecommendationResultsDialog';
|
||||
import { GetAzureRecommendationDialog } from '../dialog/skuRecommendationResults/getAzureRecommendationDialog';
|
||||
@@ -19,6 +19,9 @@ import { WIZARD_INPUT_COMPONENT_WIDTH } from './wizardController';
|
||||
import * as styles from '../constants/styles';
|
||||
import { SkuEditParametersDialog } from '../dialog/skuRecommendationResults/skuEditParametersDialog';
|
||||
import { logError, TelemetryViews } from '../telemtery';
|
||||
import { TdeConfigurationDialog } from '../dialog/tdeConfiguration/tdeConfigurationDialog';
|
||||
import { TdeMigrationModel } from '../models/tdeModels';
|
||||
import * as os from 'os';
|
||||
|
||||
export interface Product {
|
||||
type: MigrationTargetType;
|
||||
@@ -46,6 +49,7 @@ export class SKURecommendationPage extends MigrationWizardPage {
|
||||
private _rootContainer!: azdata.FlexContainer;
|
||||
private _viewAssessmentsHelperText!: azdata.TextComponent;
|
||||
private _databaseSelectedHelperText!: azdata.TextComponent;
|
||||
private _tdedatabaseSelectedHelperText!: azdata.TextComponent;
|
||||
|
||||
private _azureRecommendationSectionText!: azdata.TextComponent;
|
||||
|
||||
@@ -71,7 +75,10 @@ export class SKURecommendationPage extends MigrationWizardPage {
|
||||
private _skuEnableElasticRecommendationsText!: azdata.TextComponent;
|
||||
|
||||
private assessmentGroupContainer!: azdata.FlexContainer;
|
||||
private _tdeInfoContainer!: azdata.FlexContainer;
|
||||
private _disposables: vscode.Disposable[] = [];
|
||||
private _tdeConfigurationDialog!: TdeConfigurationDialog;
|
||||
private _previousMiTdeMigrationConfig: TdeMigrationModel = new TdeMigrationModel(); // avoid null checks
|
||||
|
||||
private _serverName: string = '';
|
||||
private _supportedProducts: Product[] = [
|
||||
@@ -172,12 +179,14 @@ export class SKURecommendationPage extends MigrationWizardPage {
|
||||
this._chooseTargetComponent = await this.createChooseTargetComponent(view);
|
||||
const _azureRecommendationsContainer = this.createAzureRecommendationContainer(view);
|
||||
this.assessmentGroupContainer = await this.createViewAssessmentsContainer();
|
||||
this._tdeInfoContainer = await this.createTdeInfoContainer();
|
||||
this._formContainer = view.modelBuilder.formContainer()
|
||||
.withFormItems([
|
||||
{ component: statusContainer, title: '' },
|
||||
{ component: this._chooseTargetComponent },
|
||||
{ component: _azureRecommendationsContainer },
|
||||
{ component: this.assessmentGroupContainer }])
|
||||
{ component: this.assessmentGroupContainer },
|
||||
{ component: this._tdeInfoContainer }])
|
||||
.withProps({
|
||||
CSSStyles: {
|
||||
'display': 'none',
|
||||
@@ -207,6 +216,7 @@ export class SKURecommendationPage extends MigrationWizardPage {
|
||||
await this._view.initializeModel(this._rootContainer);
|
||||
}
|
||||
|
||||
|
||||
private createStatusComponent(view: azdata.ModelView): azdata.TextComponent {
|
||||
const component = view.modelBuilder.text()
|
||||
.withProps({
|
||||
@@ -333,6 +343,7 @@ export class SKURecommendationPage extends MigrationWizardPage {
|
||||
if (value) {
|
||||
this.assessmentGroupContainer.display = 'inline';
|
||||
this.changeTargetType(value.cardId);
|
||||
await this.refreshTdeView();
|
||||
}
|
||||
}));
|
||||
|
||||
@@ -346,6 +357,40 @@ export class SKURecommendationPage extends MigrationWizardPage {
|
||||
return component;
|
||||
}
|
||||
|
||||
private async createTdeInfoContainer(): Promise<azdata.FlexContainer> {
|
||||
const container = this._view.modelBuilder.flexContainer().withProps({
|
||||
CSSStyles: {
|
||||
'flex-direction': 'column'
|
||||
}
|
||||
}).component();
|
||||
|
||||
const editButton = this._view.modelBuilder.button().withProps({
|
||||
label: constants.TDE_BUTTON_CAPTION,
|
||||
width: 180,
|
||||
CSSStyles: {
|
||||
...styles.BODY_CSS,
|
||||
'margin': '0',
|
||||
}
|
||||
}).component();
|
||||
this._tdeConfigurationDialog = new TdeConfigurationDialog(this, this.wizard, this.migrationStateModel, () => this._onTdeConfigClosed());
|
||||
this._disposables.push(editButton.onDidClick(
|
||||
async (e) => await this._tdeConfigurationDialog.openDialog()));
|
||||
|
||||
this._tdedatabaseSelectedHelperText = this._view.modelBuilder.text()
|
||||
.withProps({
|
||||
CSSStyles: { ...styles.BODY_CSS },
|
||||
ariaLive: 'polite',
|
||||
}).component();
|
||||
|
||||
container.addItems([
|
||||
editButton,
|
||||
this._tdedatabaseSelectedHelperText]);
|
||||
|
||||
await utils.updateControlDisplay(container, false);
|
||||
|
||||
return container;
|
||||
}
|
||||
|
||||
private async createViewAssessmentsContainer(): Promise<azdata.FlexContainer> {
|
||||
this._viewAssessmentsHelperText = this._view.modelBuilder.text().withProps({
|
||||
value: constants.SKU_RECOMMENDATION_VIEW_ASSESSMENT_MI,
|
||||
@@ -586,6 +631,7 @@ export class SKURecommendationPage extends MigrationWizardPage {
|
||||
});
|
||||
await this.constructDetails();
|
||||
this.wizard.nextButton.enabled = this.migrationStateModel._assessmentResults !== undefined;
|
||||
this._previousMiTdeMigrationConfig = this.migrationStateModel.tdeMigrationConfig;
|
||||
}
|
||||
|
||||
public async onPageLeave(pageChangeInfo: azdata.window.WizardPageChangeInfo): Promise<void> {
|
||||
@@ -739,9 +785,77 @@ export class SKURecommendationPage extends MigrationWizardPage {
|
||||
this.changeTargetType(this._rbg.selectedCardId);
|
||||
}
|
||||
|
||||
await this.refreshTdeView();
|
||||
|
||||
this._rbgLoader.loading = false;
|
||||
}
|
||||
|
||||
|
||||
private _resetTdeConfiguration() {
|
||||
this._previousMiTdeMigrationConfig = this.migrationStateModel.tdeMigrationConfig;
|
||||
this.migrationStateModel.tdeMigrationConfig = new TdeMigrationModel();
|
||||
}
|
||||
|
||||
private async refreshTdeView() {
|
||||
|
||||
if (this.migrationStateModel._targetType !== MigrationTargetType.SQLMI) {
|
||||
|
||||
//Reset the encrypted databases counter on the model to ensure the certificates migration is ignored.
|
||||
this._resetTdeConfiguration();
|
||||
|
||||
} else {
|
||||
|
||||
const encryptedDbFound = this.migrationStateModel._assessmentResults.databaseAssessments
|
||||
.filter(
|
||||
db => this.migrationStateModel._databasesForMigration.findIndex(dba => dba === db.name) >= 0 &&
|
||||
db.issues.findIndex(iss => iss.ruleId === AssessmentRuleId.TdeEnabled && iss.appliesToMigrationTargetPlatform === MigrationTargetType.SQLMI) >= 0
|
||||
)
|
||||
.map(db => db.name);
|
||||
|
||||
if (this._matchWithEncryptedDatabases(encryptedDbFound)) {
|
||||
this.migrationStateModel.tdeMigrationConfig = this._previousMiTdeMigrationConfig;
|
||||
} else {
|
||||
if (os.platform() !== 'win32') //Only available for windows for now.
|
||||
return;
|
||||
|
||||
//Set encrypted databases
|
||||
this.migrationStateModel.tdeMigrationConfig.setTdeEnabledDatabasesCount(encryptedDbFound);
|
||||
|
||||
if (this.migrationStateModel.tdeMigrationConfig.hasTdeEnabledDatabases()) {
|
||||
//Set the text when there are encrypted databases.
|
||||
|
||||
if (!this.migrationStateModel.tdeMigrationConfig.shownBefore()) {
|
||||
await this._tdeConfigurationDialog.openDialog();
|
||||
}
|
||||
} else {
|
||||
this._tdedatabaseSelectedHelperText.value = constants.TDE_WIZARD_MSG_EMPTY;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
await utils.updateControlDisplay(this._tdeInfoContainer, this.migrationStateModel.tdeMigrationConfig.hasTdeEnabledDatabases());
|
||||
}
|
||||
|
||||
private _onTdeConfigClosed() {
|
||||
const tdeMsg = (this.migrationStateModel.tdeMigrationConfig.isTdeMigrationMethodAdsConfirmed()) ? constants.TDE_WIZARD_MSG_TDE : constants.TDE_WIZARD_MSG_MANUAL;
|
||||
this._tdedatabaseSelectedHelperText.value = constants.TDE_MSG_DATABASES_SELECTED(this.migrationStateModel.tdeMigrationConfig.getTdeEnabledDatabasesCount(), tdeMsg);
|
||||
}
|
||||
|
||||
private _matchWithEncryptedDatabases(encryptedDbList: string[]): boolean {
|
||||
var currentTdeDbs = this._previousMiTdeMigrationConfig.getTdeEnabledDatabases();
|
||||
|
||||
if (encryptedDbList.length === 0 || encryptedDbList.length !== currentTdeDbs.length)
|
||||
return false;
|
||||
|
||||
if (encryptedDbList.filter(db => currentTdeDbs.findIndex(dba => dba === db) < 0).length > 0)
|
||||
return false; //There is at least one element that is not in the other array. There should be no risk of duplicates table names
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
public async startCardLoading(): Promise<void> {
|
||||
// TO-DO: ideally the short SKU recommendation loading time should have a spinning indicator,
|
||||
// but updating the card text will do for now
|
||||
|
||||
@@ -163,6 +163,11 @@ export class SummaryPage extends MigrationWizardPage {
|
||||
constants.SHIR,
|
||||
this.migrationStateModel._nodeNames.join(', ')));
|
||||
}
|
||||
|
||||
this.wizard.registerNavigationValidator(async (pageChangeInfo) => {
|
||||
this.wizard.message = { text: '' };
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
public async onPageLeave(pageChangeInfo: azdata.window.WizardPageChangeInfo): Promise<void> {
|
||||
|
||||
@@ -16,6 +16,9 @@ import { azureResource } from 'azurecore';
|
||||
import { AzureSqlDatabaseServer, getVMInstanceView, SqlVMServer } from '../api/azure';
|
||||
import { collectTargetDatabaseInfo, TargetDatabaseInfo } from '../api/sqlUtils';
|
||||
import { MigrationLocalStorage, MigrationServiceContext } from '../models/migrationLocalStorage';
|
||||
import { TdeMigrationDialog } from '../dialog/tdeConfiguration/tdeMigrationDialog';
|
||||
|
||||
const TDE_MIGRATION_BUTTON_INDEX = 1;
|
||||
|
||||
export class TargetSelectionPage extends MigrationWizardPage {
|
||||
private _view!: azdata.ModelView;
|
||||
@@ -81,10 +84,49 @@ export class TargetSelectionPage extends MigrationWizardPage {
|
||||
await this.populateAzureAccountsDropdown();
|
||||
}
|
||||
|
||||
this._disposables.push(
|
||||
this.wizard.customButtons[TDE_MIGRATION_BUTTON_INDEX].onClick(
|
||||
async e => await this._startTdeMigration()));
|
||||
|
||||
await this._view.initializeModel(form);
|
||||
}
|
||||
|
||||
private async _startTdeMigration(): Promise<void> {
|
||||
const dialog = new TdeMigrationDialog(this.migrationStateModel);
|
||||
|
||||
await dialog.openDialog();
|
||||
}
|
||||
|
||||
public async onPageEnter(pageChangeInfo: azdata.window.WizardPageChangeInfo): Promise<void> {
|
||||
this.wizard.customButtons[TDE_MIGRATION_BUTTON_INDEX].hidden = !this.migrationStateModel.tdeMigrationConfig.shouldAdsMigrateCertificates();
|
||||
this._updateTdeMigrationButtonStatus();
|
||||
|
||||
if (pageChangeInfo.newPage < pageChangeInfo.lastPage) {
|
||||
return;
|
||||
}
|
||||
switch (this.migrationStateModel._targetType) {
|
||||
case MigrationTargetType.SQLMI:
|
||||
this._pageDescription.value = constants.AZURE_SQL_TARGET_PAGE_DESCRIPTION(constants.SKU_RECOMMENDATION_MI_CARD_TEXT);
|
||||
this._azureResourceDropdownLabel.value = constants.AZURE_SQL_DATABASE_MANAGED_INSTANCE;
|
||||
this._azureResourceDropdown.ariaLabel = constants.AZURE_SQL_DATABASE_MANAGED_INSTANCE;
|
||||
break;
|
||||
case MigrationTargetType.SQLVM:
|
||||
this._pageDescription.value = constants.AZURE_SQL_TARGET_PAGE_DESCRIPTION(constants.SKU_RECOMMENDATION_VM_CARD_TEXT);
|
||||
this._azureResourceDropdownLabel.value = constants.AZURE_SQL_DATABASE_VIRTUAL_MACHINE;
|
||||
this._azureResourceDropdown.ariaLabel = constants.AZURE_SQL_DATABASE_VIRTUAL_MACHINE;
|
||||
break;
|
||||
case MigrationTargetType.SQLDB:
|
||||
this._pageDescription.value = constants.AZURE_SQL_TARGET_PAGE_DESCRIPTION(constants.SKU_RECOMMENDATION_SQLDB_CARD_TEXT);
|
||||
this._azureResourceDropdownLabel.value = constants.AZURE_SQL_DATABASE;
|
||||
this._azureResourceDropdown.ariaLabel = constants.AZURE_SQL_DATABASE;
|
||||
this._updateConnectionButtonState();
|
||||
if (this.migrationStateModel._didUpdateDatabasesForMigration) {
|
||||
await this._resetTargetMapping();
|
||||
this.migrationStateModel._didUpdateDatabasesForMigration = false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
this.wizard.registerNavigationValidator((pageChangeInfo) => {
|
||||
this.wizard.message = { text: '' };
|
||||
if (pageChangeInfo.newPage < pageChangeInfo.lastPage) {
|
||||
@@ -174,6 +216,7 @@ export class TargetSelectionPage extends MigrationWizardPage {
|
||||
};
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
});
|
||||
|
||||
@@ -240,6 +283,8 @@ export class TargetSelectionPage extends MigrationWizardPage {
|
||||
public async onPageLeave(pageChangeInfo: azdata.window.WizardPageChangeInfo): Promise<void> {
|
||||
this.wizard.registerNavigationValidator(pageChangeInfo => true);
|
||||
this.wizard.message = { text: '' };
|
||||
|
||||
this.wizard.customButtons[TDE_MIGRATION_BUTTON_INDEX].hidden = true;
|
||||
}
|
||||
|
||||
protected async handleStateChange(e: StateChangeEvent): Promise<void> {
|
||||
@@ -701,6 +746,9 @@ export class TargetSelectionPage extends MigrationWizardPage {
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
this.migrationStateModel.tdeMigrationConfig.resetTdeMigrationResult();
|
||||
|
||||
break;
|
||||
case MigrationTargetType.SQLDB:
|
||||
const sqlDatabaseServer = this.migrationStateModel._targetSqlDatabaseServers?.find(
|
||||
@@ -975,6 +1023,8 @@ export class TargetSelectionPage extends MigrationWizardPage {
|
||||
this.migrationStateModel._targetManagedInstances,
|
||||
this.migrationStateModel._location,
|
||||
this.migrationStateModel._resourceGroup);
|
||||
|
||||
this._updateTdeMigrationButtonStatus();
|
||||
break;
|
||||
case MigrationTargetType.SQLVM:
|
||||
this._azureResourceDropdown.values = await utils.getVirtualMachinesDropdownValues(
|
||||
@@ -1014,6 +1064,12 @@ export class TargetSelectionPage extends MigrationWizardPage {
|
||||
}
|
||||
}
|
||||
|
||||
private _updateTdeMigrationButtonStatus() {
|
||||
|
||||
this.wizard.customButtons[TDE_MIGRATION_BUTTON_INDEX].enabled = this.migrationStateModel.tdeMigrationConfig.shouldAdsMigrateCertificates() &&
|
||||
this.migrationStateModel._targetManagedInstances.length > 0;
|
||||
}
|
||||
|
||||
private async _populateResourceMappingTable(targetDatabases: TargetDatabaseInfo[]): Promise<void> {
|
||||
// populate target database list
|
||||
const databaseValues = this._getTargetDatabaseDropdownValues(
|
||||
|
||||
@@ -79,7 +79,13 @@ export class WizardController {
|
||||
validateButton.secondary = false;
|
||||
validateButton.hidden = true;
|
||||
|
||||
this._wizardObject.customButtons = [validateButton, saveAndCloseButton];
|
||||
const tdeMigrateButton = azdata.window.createButton(
|
||||
loc.TDE_MIGRATE_BUTTON,
|
||||
'left');
|
||||
tdeMigrateButton.secondary = false;
|
||||
tdeMigrateButton.hidden = true;
|
||||
|
||||
this._wizardObject.customButtons = [validateButton, tdeMigrateButton, saveAndCloseButton];
|
||||
const databaseSelectorPage = new DatabaseSelectorPage(this._wizardObject, stateModel);
|
||||
const skuRecommendationPage = new SKURecommendationPage(this._wizardObject, stateModel);
|
||||
const targetSelectionPage = new TargetSelectionPage(this._wizardObject, stateModel);
|
||||
|
||||
Reference in New Issue
Block a user