Adding windows auth support to sql-migration and misc bug fixes. (#14816)

* - Added coming soon message for learn more.
- Potential fix for learn more message

* Renaming of controller to sqlMigrationService

* Surfacing some errors
-Azure account is stale error
-Migration Service creation error.

* Adding refresh azure token validation.

* Fixing some errors pointed during PR
-Fixing property names
-Fixing count

* Fixing migration status
- Adding special error handling for resource not found error
- Deleting unfound migrations from local cache
- Using prefetched migration status for view all

Misc fixes:
- Using SQL server version name instead of number
- Fixing Icons on sku recommendation page
- Fixing table column width in cutover dialog
- Adding spinner button to refresh.

* Fixing all strings in migration service page and dialog

* fixed a string error in create service dialog

* Adding source config page to migration to support windows auth
Some refactorings for sqlDatabaseTree (still WIP)

* refactoring assessments code 1
introducing new interface for server assessments

* Filtering out non windows sql vms
Retaining selections made by user on assessments dialog

* Fix compile errors on sqlDatabaseTree

* Exposing migration status errors in cutover dialog

* Updating extension verion

* Correcting typos
Fixing compilation erros
Removing en-us from url
Fixing function names
Make UI calls unblocking

* Unblocking dialog in case of failed assessments
Localizing string
removing blocking code from UI
Fixing comments

* Fixed broken assessment page logic
This commit is contained in:
Aasim Khan
2021-03-23 07:48:26 -07:00
committed by GitHub
parent 780ca84f9a
commit 339d908d1d
20 changed files with 652 additions and 630 deletions

View File

@@ -19,19 +19,19 @@ export class DatabaseBackupPage extends MigrationWizardPage {
private _windowsUserAccountText!: azdata.InputBoxComponent;
private _passwordText!: azdata.InputBoxComponent;
private _networkShareDatabaseConfigContainer!: azdata.FlexContainer;
private _networkShareLocations!: azdata.InputBoxComponent[];
private _networkShareLocations: azdata.InputBoxComponent[] = [];
private _blobContainer!: azdata.FlexContainer;
private _blobContainerSubscriptionDropdown!: azdata.DropDownComponent;
private _blobContainerStorageAccountDropdown!: azdata.DropDownComponent;
private _blobContainerDatabaseConfigContainer!: azdata.FlexContainer;
private _blobContainerDropdowns!: azdata.DropDownComponent[];
private _blobContainerDropdowns: azdata.DropDownComponent[] = [];
private _fileShareContainer!: azdata.FlexContainer;
private _fileShareSubscriptionDropdown!: azdata.DropDownComponent;
private _fileShareStorageAccountDropdown!: azdata.DropDownComponent;
private _fileShareDatabaseConfigContainer!: azdata.FlexContainer;
private _fileShareDropdowns!: azdata.DropDownComponent[];
private _fileShareDropdowns: azdata.DropDownComponent[] = [];
constructor(wizard: azdata.window.Wizard, migrationStateModel: MigrationStateModel) {
super(wizard, azdata.window.createWizardPage(constants.DATABASE_BACKUP_PAGE_TITLE), migrationStateModel);

View File

@@ -26,8 +26,14 @@ export class MigrationModePage extends MigrationWizardPage {
}
public async onPageEnter(): Promise<void> {
this.wizard.registerNavigationValidator((e) => {
return true;
});
}
public async onPageLeave(): Promise<void> {
this.wizard.registerNavigationValidator((e) => {
return true;
});
}
protected async handleStateChange(e: StateChangeEvent): Promise<void> {
}

View File

@@ -5,53 +5,50 @@
import * as azdata from 'azdata';
import { MigrationWizardPage } from '../models/migrationWizardPage';
import { MigrationStateModel, StateChangeEvent } from '../models/stateMachine';
import { Product } from '../models/product';
import { MigrationStateModel, MigrationTargetType, StateChangeEvent } from '../models/stateMachine';
import { AssessmentResultsDialog } from '../dialog/assessmentResults/assessmentResultsDialog';
import * as constants from '../constants/strings';
import * as vscode from 'vscode';
import { EOL } from 'os';
import { IconPathHelper } from '../constants/iconPathHelper';
import { IconPath, IconPathHelper } from '../constants/iconPathHelper';
// import { SqlMigrationService } from '../../../../extensions/mssql/src/sqlMigration/sqlMigrationService';
export interface Product {
type: MigrationTargetType;
name: string,
icon: IconPath;
}
export class SKURecommendationPage extends MigrationWizardPage {
private supportedProducts: Product[] = [
private _view!: azdata.ModelView;
private _igComponent!: azdata.TextComponent;
private _detailsComponent!: azdata.TextComponent;
private _chooseTargetComponent!: azdata.DivContainer;
private _azureSubscriptionText!: azdata.TextComponent;
private _managedInstanceSubscriptionDropdown!: azdata.DropDownComponent;
private _resourceDropdownLabel!: azdata.TextComponent;
private _resourceDropdown!: azdata.DropDownComponent;
private _rbg!: azdata.RadioCardGroupComponent;
private eventListener!: vscode.Disposable;
private _supportedProducts: Product[] = [
{
type: 'AzureSQLMI',
type: MigrationTargetType.SQLMI,
name: constants.SKU_RECOMMENDATION_MI_CARD_TEXT,
icon: IconPathHelper.sqlMiLogo
},
{
type: 'AzureSQLVM',
type: MigrationTargetType.SQLVM,
name: constants.SKU_RECOMMENDATION_VM_CARD_TEXT,
icon: IconPathHelper.sqlVmLogo
}
];
// For future reference: DO NOT EXPOSE WIZARD DIRECTLY THROUGH HERE.
constructor(wizard: azdata.window.Wizard, migrationStateModel: MigrationStateModel) {
super(wizard, azdata.window.createWizardPage(constants.SKU_RECOMMENDATION_PAGE_TITLE), migrationStateModel);
}
protected async registerContent(view: azdata.ModelView) {
await this.initialState(view);
}
private _igComponent: azdata.FormComponent<azdata.TextComponent> | undefined;
private _detailsComponent: azdata.FormComponent<azdata.TextComponent> | undefined;
private _chooseTargetComponent: azdata.FormComponent<azdata.DivContainer> | undefined;
private _azureSubscriptionText: azdata.FormComponent<azdata.TextComponent> | undefined;
private _managedInstanceSubscriptionDropdown!: azdata.DropDownComponent;
private _resourceDropdownLabel!: azdata.TextComponent;
private _resourceDropdown!: azdata.DropDownComponent;
private _view: azdata.ModelView | undefined;
private _rbg!: azdata.RadioCardGroupComponent;
private _dbCount!: number;
private _serverName!: string;
private async initialState(view: azdata.ModelView) {
this._view = view;
this._igComponent = this.createStatusComponent(view); // The first component giving basic information
this._detailsComponent = this.createDetailsComponent(view); // The details of what can be moved
@@ -81,12 +78,11 @@ export class SKURecommendationPage extends MigrationWizardPage {
e.selected !== constants.NO_MANAGED_INSTANCE_FOUND &&
e.selected !== constants.NO_VIRTUAL_MACHINE_FOUND) {
this.migrationStateModel._sqlMigrationServices = undefined!;
if (this._rbg.selectedCardId === 'AzureSQLVM') {
if (this._rbg.selectedCardId === MigrationTargetType.SQLVM) {
this.migrationStateModel._targetServerInstance = this.migrationStateModel.getVirtualMachine(e.index);
} else {
this.migrationStateModel._targetServerInstance = this.migrationStateModel.getManagedInstance(e.index);
}
}
});
@@ -101,100 +97,51 @@ export class SKURecommendationPage extends MigrationWizardPage {
flexFlow: 'column'
}).component();
let connectionUri: string = await azdata.connection.getUriForConnection(this.migrationStateModel.sourceConnectionId);
this.migrationStateModel.migrationService.getAssessments(connectionUri).then(results => {
if (results) {
this.migrationStateModel.assessmentResults = results.items;
}
});
this._view = view;
const formContainer = view.modelBuilder.formContainer().withFormItems(
[
this._igComponent,
this._detailsComponent,
this._chooseTargetComponent,
this._azureSubscriptionText,
{
title: '',
component: this._igComponent
},
{
title: '',
component: this._detailsComponent
},
{
title: constants.SKU_RECOMMENDATION_CHOOSE_A_TARGET,
component: this._chooseTargetComponent
},
{
component: this._azureSubscriptionText
},
{
component: targetContainer
},
}
]
);
let data = connectionUri.split('|');
data.forEach(element => {
if (element.startsWith('server:')) {
let serverArray = element.split(':');
this._serverName = serverArray[1];
}
});
this._dbCount = (await azdata.connection.listDatabases(this.migrationStateModel.sourceConnectionId)).length;
await view.initializeModel(formContainer.component());
}
private createStatusComponent(view: azdata.ModelView): azdata.FormComponent<azdata.TextComponent> {
const component = view.modelBuilder.text().withProperties<azdata.TextComponentProperties>({
value: '',
private createStatusComponent(view: azdata.ModelView): azdata.TextComponent {
const component = view.modelBuilder.text().withProps({
CSSStyles: {
'font-size': '14px'
}
});
return {
title: '',
component: component.component(),
};
}).component();
return component;
}
private createDetailsComponent(view: azdata.ModelView): azdata.FormComponent<azdata.TextComponent> {
const component = view.modelBuilder.text().withProperties<azdata.TextComponentProperties>({
value: '',
});
return {
title: '',
component: component.component(),
};
private createDetailsComponent(view: azdata.ModelView): azdata.TextComponent {
const component = view.modelBuilder.text().component();
return component;
}
private createChooseTargetComponent(view: azdata.ModelView) {
const component = view.modelBuilder.divContainer();
private createChooseTargetComponent(view: azdata.ModelView): azdata.DivContainer {
return {
title: constants.SKU_RECOMMENDATION_CHOOSE_A_TARGET,
component: component.component()
};
}
private constructDetails(): void {
this._chooseTargetComponent?.component.clearItems();
this._igComponent!.component.value = constants.ASSESSMENT_COMPLETED(this._serverName);
if (this.migrationStateModel.assessmentResults) {
let dbIssueCount = 0;
let last = '';
this.migrationStateModel.assessmentResults.forEach(element => {
if (element.targetName !== this._serverName && element.targetName !== last) {
dbIssueCount += 1;
last = element.targetName;
}
});
if (dbIssueCount === this._dbCount) {
this._detailsComponent!.component.value = constants.SKU_RECOMMENDATION_NONE_SUCCESSFUL;
} else if (dbIssueCount > 0) {
this._detailsComponent!.component.value = constants.SKU_RECOMMENDATION_SOME_SUCCESSFUL(this._dbCount - dbIssueCount, this._dbCount);
} else {
this._detailsComponent!.component.value = constants.SKU_RECOMMENDATION_ALL_SUCCESSFUL(this._dbCount);
}
}
this.constructTargets();
}
private constructTargets(): void {
const products: Product[] = this.supportedProducts;
this._rbg = this._view!.modelBuilder.radioCardGroup().withProperties<azdata.RadioCardGroupComponentProperties>({
this._rbg = this._view!.modelBuilder.radioCardGroup().withProps({
cards: [],
cardWidth: '600px',
cardHeight: '40px',
@@ -203,13 +150,7 @@ export class SKURecommendationPage extends MigrationWizardPage {
iconWidth: '30px'
}).component();
products.forEach((product) => {
let dbCount = 0;
if (product.type === 'AzureSQLVM') {
dbCount = this._dbCount;
} else {
dbCount = this.migrationStateModel._migrationDbs.length;
}
this._supportedProducts.forEach((product) => {
const descriptions: azdata.RadioCardDescription[] = [
{
textValue: product.name,
@@ -230,7 +171,7 @@ export class SKURecommendationPage extends MigrationWizardPage {
},
},
{
textValue: `${dbCount} databases will be migrated`,
textValue: '0 selected',
textStyles: {
'font-size': '13px',
'line-height': '18px'
@@ -254,49 +195,73 @@ export class SKURecommendationPage extends MigrationWizardPage {
descriptions
});
});
let miDialog = new AssessmentResultsDialog('ownerUri', this.migrationStateModel, 'Assessment Dialog', this, 'mi');
let vmDialog = new AssessmentResultsDialog('ownerUri', this.migrationStateModel, 'Assessment Dialog', this, 'vm');
let miDialog = new AssessmentResultsDialog('ownerUri', this.migrationStateModel, constants.ASSESSMENT_TILE, this, MigrationTargetType.SQLMI);
let vmDialog = new AssessmentResultsDialog('ownerUri', this.migrationStateModel, constants.ASSESSMENT_TILE, this, MigrationTargetType.SQLVM);
this._rbg.onLinkClick(async (value) => {
//check which card is being selected, and open correct dialog based on link
if (value.description.linkDisplayValue === 'View/Change') {
if (value.cardId === 'AzureSQLVM') {
if (value.cardId === MigrationTargetType.SQLVM) {
this._rbg.selectedCardId = MigrationTargetType.SQLVM;
if (value.description.linkDisplayValue === 'View/Change') {
await vmDialog.openDialog();
} else if (value.cardId === 'AzureSQLMI') {
await miDialog.openDialog();
} else if (value.description.linkDisplayValue === 'Learn more') {
vscode.env.openExternal(vscode.Uri.parse('https://docs.microsoft.com/azure/azure-sql/virtual-machines/windows/sql-server-on-azure-vm-iaas-what-is-overview'));
}
} else if (value.description.linkDisplayValue === 'Learn more') {
if (value.cardId === 'AzureSQLVM') {
vscode.env.openExternal(vscode.Uri.parse('https://docs.microsoft.com/en-us/azure/azure-sql/virtual-machines/windows/sql-server-on-azure-vm-iaas-what-is-overview'));
} else if (value.cardId === 'AzureSQLMI') {
vscode.env.openExternal(vscode.Uri.parse('https://docs.microsoft.com/en-us/azure/azure-sql/managed-instance/sql-managed-instance-paas-overview '));
} else if (value.cardId === MigrationTargetType.SQLMI) {
this._rbg.selectedCardId = MigrationTargetType.SQLMI;
if (value.description.linkDisplayValue === 'View/Change') {
await miDialog.openDialog();
} else if (value.description.linkDisplayValue === 'Learn more') {
vscode.env.openExternal(vscode.Uri.parse('https://docs.microsoft.com/azure/azure-sql/managed-instance/sql-managed-instance-paas-overview '));
}
}
});
this._rbg.onSelectionChanged((value) => {
this.populateResourceInstanceDropdown();
this.changeTargetType(value.cardId);
});
this._rbg.selectedCardId = 'AzureSQLMI';
this._rbg.selectedCardId = MigrationTargetType.SQLMI;
this._chooseTargetComponent?.component.addItem(this._rbg);
const component = view.modelBuilder.divContainer().withItems(
[
this._rbg
]
).component();
return component;
}
private createAzureSubscriptionText(view: azdata.ModelView): azdata.FormComponent<azdata.TextComponent> {
const component = view.modelBuilder.text().withProperties<azdata.TextComponentProperties>({
value: 'Select an Azure subscription and an Azure SQL Managed Instance for your target.', //TODO: Localize
private changeTargetType(newTargetType: string) {
if (newTargetType === MigrationTargetType.SQLMI) {
this._azureSubscriptionText.value = constants.SELECT_AZURE_MI;
this.migrationStateModel._migrationDbs = this.migrationStateModel._miDbs;
} else {
this._azureSubscriptionText.value = constants.SELECT_AZURE_VM;
this.migrationStateModel._migrationDbs = this.migrationStateModel._vmDbs;
}
this.migrationStateModel.refreshDatabaseBackupPage = true;
this.populateResourceInstanceDropdown();
}
private async constructDetails(): Promise<void> {
const serverName = (await this.migrationStateModel.getSourceConnectionProfile()).serverName;
this._igComponent.value = constants.ASSESSMENT_COMPLETED(serverName);
await this.migrationStateModel.getServerAssessments();
if (this.migrationStateModel._assessmentResults) {
this._detailsComponent.value = constants.SKU_RECOMMENDATION_ALL_SUCCESSFUL(this.migrationStateModel._assessmentResults.databaseAssessments.length);
}
this.refreshCardText();
}
private createAzureSubscriptionText(view: azdata.ModelView): azdata.TextComponent {
const component = view.modelBuilder.text().withProps({
CSSStyles: {
'font-size': '13px',
'line-height': '18px'
}
});
}).component();
return {
title: '',
component: component.component(),
};
return component;
}
private async populateSubscriptionDropdown(): Promise<void> {
@@ -316,7 +281,7 @@ export class SKURecommendationPage extends MigrationWizardPage {
private async populateResourceInstanceDropdown(): Promise<void> {
this._resourceDropdown.loading = true;
try {
if (this._rbg.selectedCardId === 'AzureSQLVM') {
if (this._rbg.selectedCardId === MigrationTargetType.SQLVM) {
this._resourceDropdownLabel.value = constants.AZURE_SQL_DATABASE_VIRTUAL_MACHINE;
this._resourceDropdown.values = await this.migrationStateModel.getSqlVirtualMachineValues(this.migrationStateModel._targetSubscription);
@@ -331,12 +296,17 @@ export class SKURecommendationPage extends MigrationWizardPage {
}
}
private eventListener: vscode.Disposable | undefined;
public async onPageEnter(): Promise<void> {
this.eventListener = this.migrationStateModel.stateChangeEvent(async (e) => this.onStateChangeEvent(e));
this.populateSubscriptionDropdown();
this.constructDetails();
public async onPageEnter(): Promise<void> {
try {
this.migrationStateModel.getServerAssessments().then((result) => {
this.constructDetails();
});
} catch (e) {
console.log(e);
}
this.populateSubscriptionDropdown();
this.wizard.registerNavigationValidator((pageChangeInfo) => {
const errors: string[] = [];
this.wizard.message = {
@@ -384,23 +354,53 @@ export class SKURecommendationPage extends MigrationWizardPage {
}
protected async handleStateChange(e: StateChangeEvent): Promise<void> {
switch (e.newState) {
}
}
public refreshDatabaseCount(count: number): void {
public refreshDatabaseCount(selectedDbs: string[]): void {
this.migrationStateModel._migrationDbs = selectedDbs;
this.refreshCardText();
}
public refreshCardText(): void {
this.wizard.message = {
text: '',
level: azdata.window.MessageLevel.Error
};
const textValue: string = `${count} databases will be migrated`;
this._rbg.cards[0].descriptions[1].textValue = textValue;
this._rbg.cards[1].descriptions[1].textValue = textValue;
this._rbg.updateProperties({
cards: this._rbg.cards
});
if (this._rbg.selectedCardId === MigrationTargetType.SQLMI) {
this.migrationStateModel._migrationDbs = this.migrationStateModel._miDbs;
} else {
this.migrationStateModel._migrationDbs = this.migrationStateModel._vmDbs;
}
if (this.migrationStateModel._assessmentResults) {
const dbCount = this.migrationStateModel._assessmentResults.databaseAssessments.length;
const dbWithIssuesCount = this.migrationStateModel._assessmentResults.databaseAssessments.filter(db => db.issues.length > 0).length;
const miCardText = `${dbWithIssuesCount} out of ${dbCount} databases can be migrated (${this.migrationStateModel._miDbs.length} selected)`;
this._rbg.cards[0].descriptions[1].textValue = miCardText;
const vmCardText = `${dbCount} out of ${dbCount} databases can be migrated (${this.migrationStateModel._vmDbs.length} selected)`;
this._rbg.cards[1].descriptions[1].textValue = vmCardText;
this._rbg.updateProperties({
cards: this._rbg.cards
});
} else {
const miCardText = `${this.migrationStateModel._miDbs.length} selected`;
this._rbg.cards[0].descriptions[1].textValue = miCardText;
const vmCardText = `${this.migrationStateModel._vmDbs.length} selected`;
this._rbg.cards[1].descriptions[1].textValue = vmCardText;
this._rbg.updateProperties({
cards: this._rbg.cards
});
}
}
}

View File

@@ -1,91 +0,0 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import * as azdata from 'azdata';
import { MigrationWizardPage } from '../models/migrationWizardPage';
import { SOURCE_CONFIGURATION_PAGE_TITLE, COLLECTING_SOURCE_CONFIGURATIONS, COLLECTING_SOURCE_CONFIGURATIONS_INFO, COLLECTING_SOURCE_CONFIGURATIONS_ERROR } from '../constants/strings';
import { MigrationStateModel, StateChangeEvent, State } from '../models/stateMachine';
import { Disposable } from 'vscode';
export class SourceConfigurationPage extends MigrationWizardPage {
// For future reference: DO NOT EXPOSE WIZARD DIRECTLY THROUGH HERE.
constructor(wizard: azdata.window.Wizard, migrationStateModel: MigrationStateModel) {
super(wizard, azdata.window.createWizardPage(SOURCE_CONFIGURATION_PAGE_TITLE), migrationStateModel);
}
protected async registerContent(view: azdata.ModelView) {
await this.initialState(view);
}
private gatheringInfoComponent!: azdata.FormComponent;
private async initialState(view: azdata.ModelView) {
this.gatheringInfoComponent = this.createGatheringInfoComponent(view);
const form = view.modelBuilder.formContainer().withFormItems(
[
this.gatheringInfoComponent
],
{
titleFontSize: '20px'
}
).component();
await view.initializeModel(form);
let connectionUri: string = await azdata.connection.getUriForConnection(this.migrationStateModel.sourceConnectionId);
this.migrationStateModel.migrationService.getAssessments(connectionUri).then(results => {
if (results) {
this.migrationStateModel.assessmentResults = results.items;
this.migrationStateModel.currentState = State.TARGET_SELECTION;
}
});
}
private async enterErrorState() {
const component = this.gatheringInfoComponent.component as azdata.TextComponent;
component.value = COLLECTING_SOURCE_CONFIGURATIONS_ERROR(this.migrationStateModel.gatheringInformationError);
}
private async enterTargetSelectionState() {
this.goToNextPage();
}
//#region component builders
private createGatheringInfoComponent(view: azdata.ModelView): azdata.FormComponent {
let explaination = view.modelBuilder.text().withProperties<azdata.TextComponentProperties>({
value: COLLECTING_SOURCE_CONFIGURATIONS_INFO,
CSSStyles: {
'font-size': '14px'
}
});
return {
component: explaination.component(),
title: COLLECTING_SOURCE_CONFIGURATIONS
};
}
//#endregion
private eventListener: Disposable | undefined;
public async onPageEnter(): Promise<void> {
this.eventListener = this.migrationStateModel.stateChangeEvent(async (e) => this.onStateChangeEvent(e));
}
public async onPageLeave(): Promise<void> {
this.eventListener?.dispose();
}
protected async handleStateChange(e: StateChangeEvent): Promise<void> {
switch (e.newState) {
case State.COLLECTION_SOURCE_INFO_ERROR:
return this.enterErrorState();
case State.TARGET_SELECTION:
return this.enterTargetSelectionState();
}
}
public async canLeave(): Promise<boolean> {
return this.migrationStateModel.currentState === State.TARGET_SELECTION;
}
}

View File

@@ -0,0 +1,115 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import * as azdata from 'azdata';
import * as os from 'os';
import { MigrationWizardPage } from '../models/migrationWizardPage';
import { MigrationStateModel, StateChangeEvent } from '../models/stateMachine';
import * as constants from '../constants/strings';
import { createLabelTextComponent, createHeadingTextComponent } from './wizardController';
export class SqlSourceConfigurationPage extends MigrationWizardPage {
private _view!: azdata.ModelView;
constructor(wizard: azdata.window.Wizard, migrationStateModel: MigrationStateModel) {
super(wizard, azdata.window.createWizardPage(constants.SOURCE_CONFIGURATION, 'MigrationModePage'), migrationStateModel);
}
protected async registerContent(view: azdata.ModelView): Promise<void> {
this._view = view;
const form = view.modelBuilder.formContainer()
.withFormItems(
[
await this.createSourceCredentialContainer(),
]
);
await view.initializeModel(form.component());
}
public async onPageEnter(): Promise<void> {
this.wizard.registerNavigationValidator((pageChangeInfo) => {
return true;
});
}
public async onPageLeave(): Promise<void> {
this.wizard.registerNavigationValidator((pageChangeInfo) => {
return true;
});
}
protected async handleStateChange(e: StateChangeEvent): Promise<void> {
}
private async createSourceCredentialContainer(): Promise<azdata.FormComponent> {
const connectionProfile = await this.migrationStateModel.getSourceConnectionProfile();
let username;
switch (connectionProfile.authenticationType) {
case 'SqlLogin':
username = connectionProfile.userName;
this.migrationStateModel._authenticationType = 'SqlAuthentication';
break;
case 'Integrated':
username = os.userInfo().username;
this.migrationStateModel._authenticationType = 'WindowsAuthentication';
break;
default:
username = '';
}
const sourceCredText = createHeadingTextComponent(this._view, constants.SOURCE_CREDENTIALS);
const enterYourCredText = createLabelTextComponent(
this._view,
constants.ENTER_YOUR_SQL_CREDS(connectionProfile.serverName),
{
'width': '400px'
}
);
const usernameLable = this._view.modelBuilder.text().withProps({
value: constants.USERNAME,
requiredIndicator: true
}).component();
const usernameInput = this._view.modelBuilder.inputBox().withProps({
value: username,
required: true
}).component();
usernameInput.onTextChanged(value => {
this.migrationStateModel._sqlServerUsername = value;
});
const passwordLabel = this._view.modelBuilder.text().withProps({
value: constants.DATABASE_BACKUP_NETWORK_SHARE_PASSWORD_LABEL,
requiredIndicator: true
}).component();
const passwordInput = this._view.modelBuilder.inputBox().withProps({
value: (await azdata.connection.getCredentials(this.migrationStateModel.sourceConnectionId)).password,
required: true,
inputType: 'password'
}).component();
passwordInput.onTextChanged(value => {
this.migrationStateModel._sqlServerPassword = value;
});
const container = this._view.modelBuilder.flexContainer().withItems(
[
sourceCredText,
enterYourCredText,
usernameLable,
usernameInput,
passwordLabel,
passwordInput
]
).withLayout({
flexFlow: 'column'
}).component();
return {
component: container
};
}
}

View File

@@ -15,6 +15,7 @@ import { AccountsSelectionPage } from './accountsSelectionPage';
import { IntergrationRuntimePage } from './integrationRuntimePage';
import { SummaryPage } from './summaryPage';
import { MigrationModePage } from './migrationModePage';
import { SqlSourceConfigurationPage } from './sqlSourceConfigurationPage';
export const WIZARD_INPUT_COMPONENT_WIDTH = '400px';
export class WizardController {
@@ -39,6 +40,7 @@ export class WizardController {
// const subscriptionSelectionPage = new SubscriptionSelectionPage(wizard, stateModel);
const migrationModePage = new MigrationModePage(wizard, stateModel);
const azureAccountsPage = new AccountsSelectionPage(wizard, stateModel);
const sourceConfigurationPage = new SqlSourceConfigurationPage(wizard, stateModel);
const databaseBackupPage = new DatabaseBackupPage(wizard, stateModel);
const integrationRuntimePage = new IntergrationRuntimePage(wizard, stateModel);
const summaryPage = new SummaryPage(wizard, stateModel);
@@ -46,6 +48,7 @@ export class WizardController {
const pages: MigrationWizardPage[] = [
// subscriptionSelectionPage,
azureAccountsPage,
sourceConfigurationPage,
skuRecommendationPage,
migrationModePage,
databaseBackupPage,
@@ -95,7 +98,7 @@ export function createInformationRow(view: azdata.ModelView, label: string, valu
})
.withItems(
[
creaetLabelTextComponent(view, label),
createLabelTextComponent(view, label),
createTextCompononent(view, value)
],
{
@@ -114,11 +117,9 @@ export function createHeadingTextComponent(view: azdata.ModelView, value: string
}
export function creaetLabelTextComponent(view: azdata.ModelView, value: string): azdata.TextComponent {
export function createLabelTextComponent(view: azdata.ModelView, value: string, styles: { [key: string]: string; } = { 'width': '300px' }): azdata.TextComponent {
const component = createTextCompononent(view, value);
component.updateCssStyles({
'width': '300px'
});
component.updateCssStyles(styles);
return component;
}