mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-01-23 17:23:02 -05:00
Add IR Migration configuration Validation to SQL Migration extension (#21386)
* re-factor and consolidate wizard pages * validation WIP 11/10 * validate ir dialog * navigation fixes * bump version to 1.2.0 * add resource strings and fix navigatin issue * map validation state to resource string clean up * address review comments * fix typos, address review comments * address review feedback, readability * fix res string, validation check, col width * bug fixes, nav, sqldb migration * fix nav/refresh/visibility issues * fix nav issues, cancel pending validation items * update error text / position * fix localization bug
This commit is contained in:
@@ -6,7 +6,7 @@
|
||||
import * as azdata from 'azdata';
|
||||
import * as vscode from 'vscode';
|
||||
import { MigrationWizardPage } from '../models/migrationWizardPage';
|
||||
import { MigrationStateModel, MigrationTargetType, NetworkContainerType, StateChangeEvent } from '../models/stateMachine';
|
||||
import { MigrationMode, MigrationStateModel, NetworkContainerType, StateChangeEvent } from '../models/stateMachine';
|
||||
import { CreateSqlMigrationServiceDialog } from '../dialog/createSqlMigrationService/createSqlMigrationServiceDialog';
|
||||
import * as constants from '../constants/strings';
|
||||
import { WIZARD_INPUT_COMPONENT_WIDTH } from './wizardController';
|
||||
@@ -32,10 +32,22 @@ export class IntergrationRuntimePage extends MigrationWizardPage {
|
||||
private _copy2!: azdata.ButtonComponent;
|
||||
private _refresh1!: azdata.ButtonComponent;
|
||||
private _refresh2!: azdata.ButtonComponent;
|
||||
private _onlineButton!: azdata.RadioButtonComponent;
|
||||
private _offlineButton!: azdata.RadioButtonComponent;
|
||||
private _modeContainer!: azdata.FlexContainer;
|
||||
private _radioButtonContainer!: azdata.FlexContainer;
|
||||
private _networkShareButton!: azdata.RadioButtonComponent;
|
||||
private _blobContainerButton!: azdata.RadioButtonComponent;
|
||||
private _originalMigrationMode!: MigrationMode;
|
||||
private _disposables: vscode.Disposable[] = [];
|
||||
|
||||
constructor(wizard: azdata.window.Wizard, migrationStateModel: MigrationStateModel) {
|
||||
super(wizard, azdata.window.createWizardPage(constants.IR_PAGE_TITLE), migrationStateModel);
|
||||
this.migrationStateModel._databaseBackup.migrationMode =
|
||||
this.migrationStateModel._databaseBackup.migrationMode ||
|
||||
this.migrationStateModel.isSqlDbTarget
|
||||
? MigrationMode.OFFLINE
|
||||
: MigrationMode.ONLINE;
|
||||
}
|
||||
|
||||
protected async registerContent(view: azdata.ModelView): Promise<void> {
|
||||
@@ -49,8 +61,13 @@ export class IntergrationRuntimePage extends MigrationWizardPage {
|
||||
.withItems([this._statusLoadingComponent])
|
||||
.component();
|
||||
|
||||
this._radioButtonContainer = this.createBackupLocationComponent();
|
||||
this._modeContainer = this.migrationModeContainer();
|
||||
|
||||
const form = view.modelBuilder.formContainer()
|
||||
.withFormItems([
|
||||
{ component: this._modeContainer },
|
||||
{ component: this._radioButtonContainer },
|
||||
{ component: this.migrationServiceDropdownContainer() },
|
||||
{ component: this._dmsInfoContainer }])
|
||||
.withProps({ CSSStyles: { 'padding-top': '0' } })
|
||||
@@ -64,26 +81,132 @@ export class IntergrationRuntimePage extends MigrationWizardPage {
|
||||
await view.initializeModel(form);
|
||||
}
|
||||
|
||||
private migrationModeContainer(): azdata.FlexContainer {
|
||||
const buttonGroup = 'migrationMode';
|
||||
this._onlineButton = this._view.modelBuilder.radioButton()
|
||||
.withProps({
|
||||
label: constants.DATABASE_BACKUP_MIGRATION_MODE_ONLINE_LABEL,
|
||||
name: buttonGroup,
|
||||
checked: this.migrationStateModel._databaseBackup.migrationMode === MigrationMode.ONLINE,
|
||||
CSSStyles: { ...styles.LABEL_CSS, },
|
||||
}).component();
|
||||
const onlineDescription = this._view.modelBuilder.text()
|
||||
.withProps({
|
||||
value: constants.DATABASE_BACKUP_MIGRATION_MODE_ONLINE_DESCRIPTION,
|
||||
CSSStyles: { ...styles.NOTE_CSS, 'margin-left': '20px' }
|
||||
}).component();
|
||||
this._disposables.push(
|
||||
this._onlineButton.onDidChangeCheckedState(checked => {
|
||||
if (checked) {
|
||||
this.migrationStateModel._databaseBackup.migrationMode = MigrationMode.ONLINE;
|
||||
this.migrationStateModel.refreshDatabaseBackupPage = true;
|
||||
}
|
||||
}));
|
||||
|
||||
this._offlineButton = this._view.modelBuilder.radioButton()
|
||||
.withProps({
|
||||
label: constants.DATABASE_BACKUP_MIGRATION_MODE_OFFLINE_LABEL,
|
||||
name: buttonGroup,
|
||||
checked: this.migrationStateModel._databaseBackup.migrationMode === MigrationMode.OFFLINE,
|
||||
CSSStyles: { ...styles.LABEL_CSS, 'margin-top': '12px' },
|
||||
}).component();
|
||||
const offlineDescription = this._view.modelBuilder.text()
|
||||
.withProps({
|
||||
value: constants.DATABASE_BACKUP_MIGRATION_MODE_OFFLINE_DESCRIPTION,
|
||||
CSSStyles: { ...styles.NOTE_CSS, 'margin-left': '20px' }
|
||||
}).component();
|
||||
this._disposables.push(
|
||||
this._offlineButton.onDidChangeCheckedState(checked => {
|
||||
if (checked) {
|
||||
this.migrationStateModel._databaseBackup.migrationMode = MigrationMode.OFFLINE;
|
||||
this.migrationStateModel.refreshDatabaseBackupPage = true;
|
||||
}
|
||||
}));
|
||||
|
||||
const flexContainer = this._view.modelBuilder.flexContainer()
|
||||
.withItems([
|
||||
this._onlineButton,
|
||||
onlineDescription,
|
||||
this._offlineButton,
|
||||
offlineDescription]
|
||||
).withLayout({ flexFlow: 'column' })
|
||||
.component();
|
||||
|
||||
return flexContainer;
|
||||
}
|
||||
|
||||
private createBackupLocationComponent(): azdata.FlexContainer {
|
||||
const buttonGroup = 'networkContainer';
|
||||
|
||||
const selectLocationText = this._view.modelBuilder.text()
|
||||
.withProps({
|
||||
value: constants.DATABASE_BACKUP_PAGE_DESCRIPTION,
|
||||
CSSStyles: { ...styles.BODY_CSS }
|
||||
}).component();
|
||||
|
||||
this._networkShareButton = this._view.modelBuilder.radioButton()
|
||||
.withProps({
|
||||
name: buttonGroup,
|
||||
label: constants.DATABASE_BACKUP_NC_NETWORK_SHARE_RADIO_LABEL,
|
||||
checked: this.migrationStateModel.isBackupContainerNetworkShare,
|
||||
CSSStyles: { ...styles.BODY_CSS, 'margin': '0' }
|
||||
}).component();
|
||||
|
||||
this._disposables.push(
|
||||
this._networkShareButton.onDidChangeCheckedState(async checked => {
|
||||
if (checked) {
|
||||
this.migrationStateModel._databaseBackup.networkContainerType = NetworkContainerType.NETWORK_SHARE;
|
||||
await utils.updateControlDisplay(this._dmsInfoContainer, true);
|
||||
this.migrationStateModel.refreshDatabaseBackupPage = true;
|
||||
}
|
||||
}));
|
||||
|
||||
this._blobContainerButton = this._view.modelBuilder.radioButton()
|
||||
.withProps({
|
||||
name: buttonGroup,
|
||||
label: constants.DATABASE_BACKUP_NC_BLOB_STORAGE_RADIO_LABEL,
|
||||
checked: this.migrationStateModel._databaseBackup.networkContainerType === NetworkContainerType.BLOB_CONTAINER,
|
||||
CSSStyles: { ...styles.BODY_CSS, 'margin': '0' }
|
||||
}).component();
|
||||
|
||||
this._disposables.push(
|
||||
this._blobContainerButton.onDidChangeCheckedState(async checked => {
|
||||
if (checked) {
|
||||
this.migrationStateModel._databaseBackup.networkContainerType = NetworkContainerType.BLOB_CONTAINER;
|
||||
await utils.updateControlDisplay(this._dmsInfoContainer, false);
|
||||
this.migrationStateModel.refreshDatabaseBackupPage = true;
|
||||
}
|
||||
}));
|
||||
|
||||
const flexContainer = this._view.modelBuilder.flexContainer()
|
||||
.withItems([
|
||||
selectLocationText,
|
||||
this._blobContainerButton,
|
||||
this._networkShareButton,
|
||||
])
|
||||
.withLayout({ flexFlow: 'column' })
|
||||
.component();
|
||||
|
||||
return flexContainer;
|
||||
}
|
||||
|
||||
public async onPageEnter(pageChangeInfo: azdata.window.WizardPageChangeInfo): Promise<void> {
|
||||
if (pageChangeInfo.newPage < pageChangeInfo.lastPage) {
|
||||
return;
|
||||
}
|
||||
const isSqlDbTarget = this.migrationStateModel.isSqlDbTarget;
|
||||
const isNetworkShare = this.migrationStateModel.isBackupContainerNetworkShare;
|
||||
|
||||
this._subscription.value = this.migrationStateModel._targetSubscription.name;
|
||||
this._location.value = await getLocationDisplayName(
|
||||
this.migrationStateModel._targetServerInstance.location);
|
||||
|
||||
await utils.updateControlDisplay(
|
||||
this._dmsInfoContainer,
|
||||
this.migrationStateModel._targetType === MigrationTargetType.SQLDB ||
|
||||
this.migrationStateModel._databaseBackup.networkContainerType === NetworkContainerType.NETWORK_SHARE);
|
||||
|
||||
await this.loadResourceGroupDropdown();
|
||||
this.wizard.registerNavigationValidator((pageChangeInfo) => {
|
||||
this.wizard.message = { text: '' };
|
||||
if (pageChangeInfo.newPage < pageChangeInfo.lastPage) {
|
||||
return true;
|
||||
}
|
||||
const isSqlDbTarget = this.migrationStateModel.isSqlDbTarget;
|
||||
if (!isSqlDbTarget && !this._networkShareButton.checked && !this._blobContainerButton.checked) {
|
||||
this.wizard.message = {
|
||||
level: azdata.window.MessageLevel.Error,
|
||||
text: constants.SERVICE_SELECTION_LOCATION_MESSAGE,
|
||||
};
|
||||
return false;
|
||||
}
|
||||
|
||||
const state = this.migrationStateModel._sqlMigrationService?.properties?.integrationRuntimeState;
|
||||
if (!this.migrationStateModel._sqlMigrationService) {
|
||||
@@ -93,10 +216,7 @@ export class IntergrationRuntimePage extends MigrationWizardPage {
|
||||
};
|
||||
return false;
|
||||
}
|
||||
if ((this.migrationStateModel._targetType === MigrationTargetType.SQLDB ||
|
||||
this.migrationStateModel._databaseBackup.networkContainerType === NetworkContainerType.NETWORK_SHARE)
|
||||
&& state !== 'Online') {
|
||||
|
||||
if ((isSqlDbTarget || isNetworkShare) && state !== 'Online') {
|
||||
this.wizard.message = {
|
||||
level: azdata.window.MessageLevel.Error,
|
||||
text: constants.SERVICE_OFFLINE_ERROR
|
||||
@@ -105,10 +225,43 @@ export class IntergrationRuntimePage extends MigrationWizardPage {
|
||||
}
|
||||
return true;
|
||||
});
|
||||
|
||||
if (pageChangeInfo.newPage < pageChangeInfo.lastPage) {
|
||||
return;
|
||||
}
|
||||
|
||||
await utils.updateControlDisplay(this._modeContainer, !isSqlDbTarget);
|
||||
this._onlineButton.enabled = !isSqlDbTarget;
|
||||
|
||||
if (isSqlDbTarget) {
|
||||
this.migrationStateModel._databaseBackup.migrationMode = MigrationMode.OFFLINE;
|
||||
this._offlineButton.checked = true;
|
||||
}
|
||||
this._originalMigrationMode = this.migrationStateModel._databaseBackup.migrationMode;
|
||||
|
||||
this._networkShareButton.checked = this.migrationStateModel.isBackupContainerNetworkShare;
|
||||
this._blobContainerButton.checked = this.migrationStateModel._databaseBackup.networkContainerType === NetworkContainerType.BLOB_CONTAINER;
|
||||
await utils.updateControlDisplay(
|
||||
this._radioButtonContainer,
|
||||
!isSqlDbTarget);
|
||||
|
||||
this._subscription.value = this.migrationStateModel._targetSubscription.name;
|
||||
this._location.value = await getLocationDisplayName(
|
||||
this.migrationStateModel._targetServerInstance.location);
|
||||
|
||||
await utils.updateControlDisplay(
|
||||
this._dmsInfoContainer,
|
||||
isSqlDbTarget || isNetworkShare);
|
||||
|
||||
await this.loadResourceGroupDropdown();
|
||||
}
|
||||
|
||||
public async onPageLeave(pageChangeInfo: azdata.window.WizardPageChangeInfo): Promise<void> {
|
||||
this.wizard.registerNavigationValidator((pageChangeInfo) => true);
|
||||
this.wizard.registerNavigationValidator(pageChangeInfo => true);
|
||||
this.wizard.message = { text: '' };
|
||||
if (this._originalMigrationMode !== this.migrationStateModel._databaseBackup.migrationMode) {
|
||||
this.migrationStateModel.refreshDatabaseBackupPage = true;
|
||||
}
|
||||
}
|
||||
|
||||
protected async handleStateChange(e: StateChangeEvent): Promise<void> {
|
||||
@@ -195,18 +348,20 @@ export class IntergrationRuntimePage extends MigrationWizardPage {
|
||||
async (value) => {
|
||||
if (value && value !== 'undefined' && value !== constants.SQL_MIGRATION_SERVICE_NOT_FOUND_ERROR) {
|
||||
this.wizard.message = { text: '' };
|
||||
|
||||
await utils.updateControlDisplay(
|
||||
this._dmsInfoContainer,
|
||||
this.migrationStateModel._targetType === MigrationTargetType.SQLDB ||
|
||||
this.migrationStateModel._databaseBackup.networkContainerType === NetworkContainerType.NETWORK_SHARE);
|
||||
|
||||
const resourceGroupName = this.migrationStateModel._sqlMigrationServiceResourceGroup.name.toLowerCase();
|
||||
const selectedDms = this.migrationStateModel._sqlMigrationServices.find(
|
||||
dms => dms.name === value && dms.properties.resourceGroup.toLowerCase() === this.migrationStateModel._sqlMigrationServiceResourceGroup.name.toLowerCase());
|
||||
dms => dms.name === value
|
||||
&& dms.properties.resourceGroup.toLowerCase() === resourceGroupName);
|
||||
|
||||
if (selectedDms) {
|
||||
this.migrationStateModel._sqlMigrationService = selectedDms;
|
||||
await this.loadStatus();
|
||||
}
|
||||
|
||||
await utils.updateControlDisplay(
|
||||
this._dmsInfoContainer,
|
||||
this.migrationStateModel.isSqlDbTarget ||
|
||||
this.migrationStateModel.isBackupContainerNetworkShare);
|
||||
} else {
|
||||
this.migrationStateModel._sqlMigrationService = undefined;
|
||||
await utils.updateControlDisplay(this._dmsInfoContainer, false);
|
||||
@@ -276,7 +431,7 @@ export class IntergrationRuntimePage extends MigrationWizardPage {
|
||||
|
||||
this._disposables.push(
|
||||
this._refreshButton.onDidClick(
|
||||
async (e) => this.loadStatus()));
|
||||
async (e) => await this.loadStatus()));
|
||||
|
||||
const connectionLabelContainer = this._view.modelBuilder.flexContainer()
|
||||
.component();
|
||||
@@ -398,7 +553,7 @@ export class IntergrationRuntimePage extends MigrationWizardPage {
|
||||
this._dmsDropdown.values = utils.getAzureResourceDropdownValues(
|
||||
this.migrationStateModel._sqlMigrationServices,
|
||||
this.migrationStateModel._location,
|
||||
this.migrationStateModel._sqlMigrationServiceResourceGroup.name,
|
||||
this.migrationStateModel._sqlMigrationServiceResourceGroup?.name,
|
||||
constants.SQL_MIGRATION_SERVICE_NOT_FOUND_ERROR);
|
||||
|
||||
utils.selectDefaultDropdownValue(
|
||||
|
||||
Reference in New Issue
Block a user