Added fetch logic for controllers (#14380)

* . Added fetch logic for controllers (no need to create a new one everytime)
. Fixed retention logic

* Fix field reloading logic.
Fixed localized string
Removing hardcoded colors
This commit is contained in:
Aasim Khan
2021-02-22 19:00:39 -08:00
committed by GitHub
parent 9daaa1c58b
commit d21ee4dc9e
11 changed files with 570 additions and 310 deletions

View File

@@ -96,12 +96,12 @@ export async function getMigrationController(account: azdata.Account, subscripti
export async function getMigrationControllers(account: azdata.Account, subscription: Subscription, resourceGroupName: string, regionName: string): Promise<MigrationController[]> {
const api = await getAzureCoreAPI();
const host = `https://${regionName}.management.azure.com`;
const path = `/subscriptions/${subscription.id}/resourceGroups/${resourceGroupName}/providers/Microsoft.DataMigration/Controllers?api-version=2020-09-01-preview`;
const path = `/subscriptions/${subscription.id}/providers/Microsoft.DataMigration/Controllers?api-version=2020-09-01-preview`;
const response = await api.makeAzureRestRequest(account, subscription, path, azurecore.HttpRequestMethod.GET, undefined, true, host);
if (response.errors.length > 0) {
throw new Error(response.errors.toString());
}
return response.response.data;
return response.response.data.value;
}
export async function createMigrationController(account: azdata.Account, subscription: Subscription, resourceGroupName: string, regionName: string, controllerName: string): Promise<MigrationController> {

View File

@@ -69,7 +69,7 @@ export class CreateMigrationControllerDialog {
}
try {
const createdController = await createMigrationController(this.migrationStateModel.azureAccount, subscription, resourceGroup, region, controllerName!);
const createdController = await createMigrationController(this.migrationStateModel._azureAccount, subscription, resourceGroup, region, controllerName!);
if (createdController.error) {
this.setDialogMessage(`${createdController.error.code} : ${createdController.error.message}`);
this._statusLoadingComponent.loading = false;
@@ -79,7 +79,7 @@ export class CreateMigrationControllerDialog {
this._dialogObject.message = {
text: ''
};
this.migrationStateModel.migrationController = createdController;
this.migrationStateModel._migrationController = createdController;
await this.refreshAuthTable();
await this.refreshStatus();
this._setupContainer.display = 'inline';
@@ -130,7 +130,7 @@ export class CreateMigrationControllerDialog {
this._dialogObject.okButton.enabled = false;
azdata.window.openDialog(this._dialogObject);
this._dialogObject.cancelButton.onClick((e) => {
this.migrationStateModel.migrationController = undefined!;
this.migrationStateModel._migrationController = undefined!;
});
this._dialogObject.okButton.onClick((e) => {
this.irPage.populateMigrationController();
@@ -242,7 +242,7 @@ export class CreateMigrationControllerDialog {
private async populateResourceGroups(): Promise<void> {
this.migrationControllerResourceGroupDropdown.loading = true;
let subscription = this.migrationStateModel._targetSubscription;
const resourceGroups = await getResourceGroups(this.migrationStateModel.azureAccount, subscription);
const resourceGroups = await getResourceGroups(this.migrationStateModel._azureAccount, subscription);
let resourceGroupDropdownValues: azdata.CategoryValue[] = [];
if (resourceGroups && resourceGroups.length > 0) {
resourceGroups.forEach((resourceGroup) => {
@@ -392,8 +392,8 @@ export class CreateMigrationControllerDialog {
const subscription = this.migrationStateModel._targetSubscription;
const resourceGroup = (this.migrationControllerResourceGroupDropdown.value as azdata.CategoryValue).name;
const region = (this.migrationControllerRegionDropdown.value as azdata.CategoryValue).name;
const controllerStatus = await getMigrationController(this.migrationStateModel.azureAccount, subscription, resourceGroup, region, this.migrationStateModel.migrationController!.name);
const controllerMonitoringStatus = await getMigrationControllerMonitoringData(this.migrationStateModel.azureAccount, subscription, resourceGroup, region, this.migrationStateModel.migrationController!.name);
const controllerStatus = await getMigrationController(this.migrationStateModel._azureAccount, subscription, resourceGroup, region, this.migrationStateModel._migrationController!.name);
const controllerMonitoringStatus = await getMigrationControllerMonitoringData(this.migrationStateModel._azureAccount, subscription, resourceGroup, region, this.migrationStateModel._migrationController!.name);
this.migrationStateModel._nodeNames = controllerMonitoringStatus.nodes.map((node) => {
return node.nodeName;
});
@@ -402,14 +402,14 @@ export class CreateMigrationControllerDialog {
if (state === 'Online') {
this._connectionStatus.updateProperties(<azdata.InfoBoxComponentProperties>{
text: constants.CONTROLLER_READY(this.migrationStateModel.migrationController!.name, this.migrationStateModel._nodeNames.join(', ')),
text: constants.CONTROLLER_READY(this.migrationStateModel._migrationController!.name, this.migrationStateModel._nodeNames.join(', ')),
style: 'success'
});
this._dialogObject.okButton.enabled = true;
} else {
this._connectionStatus.text = constants.CONTROLLER_NOT_READY(this.migrationStateModel.migrationController!.name);
this._connectionStatus.text = constants.CONTROLLER_NOT_READY(this.migrationStateModel._migrationController!.name);
this._connectionStatus.updateProperties(<azdata.InfoBoxComponentProperties>{
text: constants.CONTROLLER_NOT_READY(this.migrationStateModel.migrationController!.name),
text: constants.CONTROLLER_NOT_READY(this.migrationStateModel._migrationController!.name),
style: 'warning'
});
this._dialogObject.okButton.enabled = false;
@@ -421,7 +421,7 @@ export class CreateMigrationControllerDialog {
const subscription = this.migrationStateModel._targetSubscription;
const resourceGroup = (this.migrationControllerResourceGroupDropdown.value as azdata.CategoryValue).name;
const region = (this.migrationControllerRegionDropdown.value as azdata.CategoryValue).name;
const keys = await getMigrationControllerAuthKeys(this.migrationStateModel.azureAccount, subscription, resourceGroup, region, this.migrationStateModel.migrationController!.name);
const keys = await getMigrationControllerAuthKeys(this.migrationStateModel._azureAccount, subscription, resourceGroup, region, this.migrationStateModel._migrationController!.name);
this._copyKey1Button = this._view.modelBuilder.button().withProps({
iconPath: IconPathHelper.copy
@@ -445,16 +445,14 @@ export class CreateMigrationControllerDialog {
iconPath: IconPathHelper.refresh
}).component();
this._refreshKey1Button.onDidClick((e) => {
this.refreshAuthTable();
this._refreshKey1Button.onDidClick((e) => {//TODO: add refresh logic
});
this._refreshKey2Button = this._view.modelBuilder.button().withProps({
iconPath: IconPathHelper.refresh
}).component();
this._refreshKey2Button.onDidClick((e) => {
this.refreshAuthTable();
this._refreshKey2Button.onDidClick((e) => { //TODO: add refresh logic
});
this.migrationControllerAuthKeyTable.updateProperties({

View File

@@ -4,7 +4,7 @@
*--------------------------------------------------------------------------------------------*/
import * as vscode from 'vscode';
import { azureResource } from 'azureResource';
import { DatabaseMigration, SqlManagedInstance } from '../api/azure';
import { DatabaseMigration, MigrationController, SqlManagedInstance } from '../api/azure';
import * as azdata from 'azdata';
@@ -35,7 +35,13 @@ export class MigrationLocalStorage {
return dataBaseMigrations;
}
public static saveMigration(connectionProfile: azdata.connection.ConnectionProfile, migrationContext: DatabaseMigration, targetMI: SqlManagedInstance, azureAccount: azdata.Account, subscription: azureResource.AzureResourceSubscription): void {
public static saveMigration(
connectionProfile: azdata.connection.ConnectionProfile,
migrationContext: DatabaseMigration,
targetMI: SqlManagedInstance,
azureAccount: azdata.Account,
subscription: azureResource.AzureResourceSubscription,
controller: MigrationController): void {
try {
const migrationMementos: MigrationContext[] = this.context.globalState.get(this.mementoToken) || [];
migrationMementos.push({
@@ -43,7 +49,8 @@ export class MigrationLocalStorage {
migrationContext: migrationContext,
targetManagedInstance: targetMI,
subscription: subscription,
azureAccount: azureAccount
azureAccount: azureAccount,
controller: controller
});
this.context.globalState.update(this.mementoToken, migrationMementos);
} catch (e) {
@@ -61,5 +68,6 @@ export interface MigrationContext {
migrationContext: DatabaseMigration,
targetManagedInstance: SqlManagedInstance,
azureAccount: azdata.Account,
subscription: azureResource.AzureResourceSubscription
subscription: azureResource.AzureResourceSubscription,
controller: MigrationController
}

View File

@@ -65,8 +65,8 @@ export interface Model {
readonly currentState: State;
gatheringInformationError: string | undefined;
skuRecommendations: SKURecommendations | undefined;
azureAccount: azdata.Account | undefined;
databaseBackup: DatabaseBackupModel | undefined;
_azureAccount: azdata.Account | undefined;
_databaseBackup: DatabaseBackupModel | undefined;
}
export interface StateChangeEvent {
@@ -75,22 +75,22 @@ export interface StateChangeEvent {
}
export class MigrationStateModel implements Model, vscode.Disposable {
public azureAccounts!: azdata.Account[];
public azureAccount!: azdata.Account;
public _azureAccounts!: azdata.Account[];
public _azureAccount!: azdata.Account;
public subscriptions!: azureResource.AzureResourceSubscription[];
public _subscriptions!: azureResource.AzureResourceSubscription[];
public _targetSubscription!: azureResource.AzureResourceSubscription;
public _targetManagedInstances!: SqlManagedInstance[];
public _targetManagedInstance!: SqlManagedInstance;
public databaseBackup!: DatabaseBackupModel;
public _databaseBackup!: DatabaseBackupModel;
public _storageAccounts!: StorageAccount[];
public _fileShares!: azureResource.FileShare[];
public _blobContainers!: azureResource.BlobContainer[];
public migrationController!: MigrationController;
public migrationControllers!: MigrationController[];
public _migrationController!: MigrationController;
public _migrationControllers!: MigrationController[];
public _nodeNames!: string[];
private _stateChangeEventEmitter = new vscode.EventEmitter<StateChangeEvent>();
@@ -107,7 +107,7 @@ export class MigrationStateModel implements Model, vscode.Disposable {
public readonly migrationService: mssql.ISqlMigrationService
) {
this._currentState = State.INIT;
this.databaseBackup = {} as DatabaseBackupModel;
this._databaseBackup = {} as DatabaseBackupModel;
}
public get sourceConnectionId(): string {
@@ -165,14 +165,14 @@ export class MigrationStateModel implements Model, vscode.Disposable {
public async getAccountValues(): Promise<azdata.CategoryValue[]> {
let accountValues: azdata.CategoryValue[] = [];
try {
this.azureAccounts = await azdata.accounts.getAllAccounts();
if (this.azureAccounts.length === 0) {
this._azureAccounts = await azdata.accounts.getAllAccounts();
if (this._azureAccounts.length === 0) {
accountValues = [{
displayName: constants.ACCOUNT_SELECTION_PAGE_NO_LINKED_ACCOUNTS_ERROR,
name: ''
}];
}
accountValues = this.azureAccounts.map((account): azdata.CategoryValue => {
accountValues = this._azureAccounts.map((account): azdata.CategoryValue => {
return {
displayName: account.displayInfo.displayName,
name: account.displayInfo.userId
@@ -189,16 +189,16 @@ export class MigrationStateModel implements Model, vscode.Disposable {
}
public getAccount(index: number): azdata.Account {
return this.azureAccounts[index];
return this._azureAccounts[index];
}
public async getSubscriptionsDropdownValues(): Promise<azdata.CategoryValue[]> {
let subscriptionsValues: azdata.CategoryValue[] = [];
try {
if (!this.subscriptions) {
this.subscriptions = await getSubscriptions(this.azureAccount);
if (!this._subscriptions) {
this._subscriptions = await getSubscriptions(this._azureAccount);
}
this.subscriptions.forEach((subscription) => {
this._subscriptions.forEach((subscription) => {
subscriptionsValues.push({
name: subscription.id,
displayName: `${subscription.name} - ${subscription.id}`
@@ -227,15 +227,13 @@ export class MigrationStateModel implements Model, vscode.Disposable {
}
public getSubscription(index: number): azureResource.AzureResourceSubscription {
return this.subscriptions[index];
return this._subscriptions[index];
}
public async getManagedInstanceValues(subscription: azureResource.AzureResourceSubscription): Promise<azdata.CategoryValue[]> {
let managedInstanceValues: azdata.CategoryValue[] = [];
try {
if (!this._targetManagedInstances) {
this._targetManagedInstances = await getAvailableManagedInstanceProducts(this.azureAccount, subscription);
}
this._targetManagedInstances = await getAvailableManagedInstanceProducts(this._azureAccount, subscription);
this._targetManagedInstances.forEach((managedInstance) => {
managedInstanceValues.push({
name: managedInstance.id,
@@ -270,9 +268,7 @@ export class MigrationStateModel implements Model, vscode.Disposable {
public async getStorageAccountValues(subscription: azureResource.AzureResourceSubscription): Promise<azdata.CategoryValue[]> {
let storageAccountValues: azdata.CategoryValue[] = [];
try {
if (!this._storageAccounts) {
this._storageAccounts = await getAvailableStorageAccounts(this.azureAccount, subscription);
}
this._storageAccounts = await getAvailableStorageAccounts(this._azureAccount, subscription);
this._storageAccounts.forEach((storageAccount) => {
storageAccountValues.push({
name: storageAccount.id,
@@ -307,9 +303,7 @@ export class MigrationStateModel implements Model, vscode.Disposable {
public async getFileShareValues(subscription: azureResource.AzureResourceSubscription, storageAccount: StorageAccount): Promise<azdata.CategoryValue[]> {
let fileShareValues: azdata.CategoryValue[] = [];
try {
if (!this._fileShares) {
this._fileShares = await getFileShares(this.azureAccount, subscription, storageAccount);
}
this._fileShares = await getFileShares(this._azureAccount, subscription, storageAccount);
this._fileShares.forEach((fileShare) => {
fileShareValues.push({
name: fileShare.id,
@@ -344,9 +338,7 @@ export class MigrationStateModel implements Model, vscode.Disposable {
public async getBlobContainerValues(subscription: azureResource.AzureResourceSubscription, storageAccount: StorageAccount): Promise<azdata.CategoryValue[]> {
let blobContainerValues: azdata.CategoryValue[] = [];
try {
if (!this._blobContainers) {
this._blobContainers = await getBlobContainers(this.azureAccount, subscription, storageAccount);
}
this._blobContainers = await getBlobContainers(this._azureAccount, subscription, storageAccount);
this._blobContainers.forEach((blobContainer) => {
blobContainerValues.push({
name: blobContainer.id,
@@ -382,10 +374,8 @@ export class MigrationStateModel implements Model, vscode.Disposable {
public async getMigrationControllerValues(subscription: azureResource.AzureResourceSubscription, managedInstance: SqlManagedInstance): Promise<azdata.CategoryValue[]> {
let migrationControllerValues: azdata.CategoryValue[] = [];
try {
if (!this.migrationControllers) {
this.migrationControllers = await getMigrationControllers(this.azureAccount, subscription, managedInstance.resourceGroup!, managedInstance.location);
}
this.migrationControllers.forEach((migrationController) => {
this._migrationControllers = await getMigrationControllers(this._azureAccount, subscription, managedInstance.resourceGroup!, managedInstance.location);
this._migrationControllers.forEach((migrationController) => {
migrationControllerValues.push({
name: migrationController.id,
displayName: `${migrationController.name}`
@@ -413,7 +403,7 @@ export class MigrationStateModel implements Model, vscode.Disposable {
}
public getMigrationController(index: number): MigrationController {
return this.migrationControllers[index];
return this._migrationControllers[index];
}
public async startMigration() {
@@ -428,20 +418,20 @@ export class MigrationStateModel implements Model, vscode.Disposable {
const connectionPassword = await azdata.connection.getCredentials(this.sourceConnectionId);
const requestBody: StartDatabaseMigrationRequest = {
location: this.migrationController?.properties.location!,
location: this._migrationController?.properties.location!,
properties: {
SourceDatabaseName: currentConnection?.databaseName!,
MigrationController: this.migrationController?.id!,
MigrationController: this._migrationController?.id!,
BackupConfiguration: {
TargetLocation: {
StorageAccountResourceId: this.databaseBackup.storageAccount.id,
AccountKey: this.databaseBackup.storageKey,
StorageAccountResourceId: this._databaseBackup.storageAccount.id,
AccountKey: this._databaseBackup.storageKey,
},
SourceLocation: {
FileShare: {
Path: this.databaseBackup.networkShareLocation,
Username: this.databaseBackup.windowsUser,
Password: this.databaseBackup.password,
Path: this._databaseBackup.networkShareLocation,
Username: this._databaseBackup.windowsUser,
Password: this._databaseBackup.password,
}
},
},
@@ -455,17 +445,24 @@ export class MigrationStateModel implements Model, vscode.Disposable {
};
const response = await startDatabaseMigration(
this.azureAccount,
this._azureAccount,
this._targetSubscription,
this._targetManagedInstance.resourceGroup!,
this.migrationController?.properties.location!,
this._migrationController?.properties.location!,
this._targetManagedInstance.name,
this.migrationController?.name!,
this._migrationController?.name!,
requestBody
);
if (response.status === 201) {
MigrationLocalStorage.saveMigration(currentConnection!, response.databaseMigration, this._targetManagedInstance, this.azureAccount, this._targetSubscription);
MigrationLocalStorage.saveMigration(
currentConnection!,
response.databaseMigration,
this._targetManagedInstance,
this._azureAccount,
this._targetSubscription,
this._migrationController
);
}
vscode.window.showInformationMessage(constants.MIGRATION_STARTED);

View File

@@ -98,6 +98,12 @@ export const DEFAULT_SETUP_BUTTON = localize('sql.migration.default.setup.button
export const CUSTOM_SETUP_BUTTON = localize('sql.migration.custom.setup.button', "Custom setup: Add migration controller after customizing most options.");
export const MIGRATION_CONTROLLER_NOT_FOUND_ERROR = localize('sql.migration.ir.page.migration.controller.not.found', "No Migration Controllers found. Please create a new one");
export const CREATE_NEW = localize('sql.migration.create.new', "Create new");
export const INVALID_CONTROLLER_ERROR = localize('sql.migration.invalid.controller.error', "Please select a valid controller");
export const CONTROLLER_OFFLINE_ERROR = localize('sql.migration.invalid.controller.offline.error', "Please select a controller that is connected to a node");
export const AUTHENTICATION_KEYS = localize('sql.migration.authentication.types', "Authentication Keys");
export function CONTROLLER_DETAILS_HEADER(controllerName: string) {
return localize('sql.migration.controller.header', "Migration Controller \"{0}\" details:`", controllerName);
}
// create migration controller dialog
export const CONTROLLER_DIALOG_DESCRIPTION = localize('sql.migration.controller.container.description', "A migration controller is an ARM (Azure Resource Manager) resource created in your Azure subscription and it is needed to coordinate and monitor data migration activities. {0}");
@@ -128,7 +134,6 @@ export const INVALID_REGION_ERROR = localize('sql.migration.invalid.region.error
export const INVALID_CONTROLLER_NAME_ERROR = localize('sql.migration.invalid.controller.name.error', "Please enter a valid name for the migration controller.");
export const CONTROLLER_NOT_FOUND = localize('sql.migration.controller.not.found', "No Migration Controllers found. Please create a new one.");
export const CONTROLLER_NOT_SETUP_ERROR = localize('sql.migration.controller.not.setup', "Please add a migration controller to proceed.");
export const MANAGED_INSTANCE = localize('sql.migration.managed.instance', "Azure SQL managed instance");
export const NO_MANAGED_INSTANCE_FOUND = localize('sql.migration.no.managedInstance.found', "No managed instance found");
export const TARGET_SELECTION_PAGE_TITLE = localize('sql.migration.target.page.title', "Choose the target Azure SQL");

View File

@@ -48,8 +48,10 @@ export class AccountsSelectionPage extends MigrationWizardPage {
this._azureAccountsDropdown.onValueChanged(async (value) => {
if (value.selected) {
this.migrationStateModel.azureAccount = this.migrationStateModel.getAccount(value.index);
this.migrationStateModel.subscriptions = undefined!;
this.migrationStateModel._azureAccount = this.migrationStateModel.getAccount(value.index);
this.migrationStateModel._subscriptions = undefined!;
this.migrationStateModel._targetSubscription = undefined!;
this.migrationStateModel._databaseBackup.subscription = undefined!;
}
});
@@ -82,7 +84,6 @@ export class AccountsSelectionPage extends MigrationWizardPage {
this._azureAccountsDropdown.loading = true;
try {
this._azureAccountsDropdown.values = await this.migrationStateModel.getAccountValues();
this.migrationStateModel.azureAccount = this.migrationStateModel.getAccount(0);
} finally {
this._azureAccountsDropdown.loading = false;
}

View File

@@ -128,8 +128,8 @@ export class DatabaseBackupPage extends MigrationWizardPage {
}).component();
this._fileShareSubscriptionDropdown.onValueChanged(async (value) => {
if (value.selected) {
this.migrationStateModel.databaseBackup.subscription = this.migrationStateModel.getSubscription(value.index);
this.migrationStateModel._storageAccounts = undefined!;
this.migrationStateModel._databaseBackup.subscription = this.migrationStateModel.getSubscription(value.index);
this.migrationStateModel._databaseBackup.storageAccount = undefined!;
await this.loadFileShareStorageDropdown();
}
});
@@ -145,8 +145,8 @@ export class DatabaseBackupPage extends MigrationWizardPage {
}).component();
this._fileShareStorageAccountDropdown.onValueChanged(async (value) => {
if (value.selected) {
this.migrationStateModel.databaseBackup.storageAccount = this.migrationStateModel.getStorageAccount(value.index);
this.migrationStateModel._fileShares = undefined!;
this.migrationStateModel._databaseBackup.storageAccount = this.migrationStateModel.getStorageAccount(value.index);
this.migrationStateModel._databaseBackup.fileShare = undefined!;
await this.loadFileShareDropdown();
}
});
@@ -162,7 +162,7 @@ export class DatabaseBackupPage extends MigrationWizardPage {
}).component();
this._fileShareFileShareDropdown.onValueChanged((value) => {
if (value.selected) {
this.migrationStateModel.databaseBackup.fileShare = this.migrationStateModel.getFileShare(value.index);
this.migrationStateModel._databaseBackup.fileShare = this.migrationStateModel.getFileShare(value.index);
}
});
@@ -198,8 +198,8 @@ export class DatabaseBackupPage extends MigrationWizardPage {
}).component();
this._blobContainerSubscriptionDropdown.onValueChanged(async (value) => {
if (value.selected) {
this.migrationStateModel.databaseBackup.subscription = this.migrationStateModel.getSubscription(value.index);
this.migrationStateModel._storageAccounts = undefined!;
this.migrationStateModel._databaseBackup.subscription = this.migrationStateModel.getSubscription(value.index);
this.migrationStateModel._databaseBackup.storageAccount = undefined!;
await this.loadblobStorageDropdown();
}
});
@@ -215,8 +215,8 @@ export class DatabaseBackupPage extends MigrationWizardPage {
}).component();
this._blobContainerStorageAccountDropdown.onValueChanged(async (value) => {
if (value.selected) {
this.migrationStateModel.databaseBackup.storageAccount = this.migrationStateModel.getStorageAccount(value.index);
this.migrationStateModel._blobContainers = undefined!;
this.migrationStateModel._databaseBackup.storageAccount = this.migrationStateModel.getStorageAccount(value.index);
this.migrationStateModel._databaseBackup.blobContainer = undefined!;
await this.loadBlobContainerDropdown();
}
});
@@ -231,7 +231,7 @@ export class DatabaseBackupPage extends MigrationWizardPage {
}).component();
this._blobContainerBlobDropdown.onValueChanged((value) => {
if (value.selected) {
this.migrationStateModel.databaseBackup.blobContainer = this.migrationStateModel.getBlobContainer(value.index);
this.migrationStateModel._databaseBackup.blobContainer = this.migrationStateModel.getBlobContainer(value.index);
}
});
@@ -272,7 +272,7 @@ export class DatabaseBackupPage extends MigrationWizardPage {
validationErrorMessage: constants.INVALID_NETWORK_SHARE_LOCATION
})
.withValidation((component) => {
if (this.migrationStateModel.databaseBackup.networkContainerType === NetworkContainerType.NETWORK_SHARE) {
if (this.migrationStateModel._databaseBackup.networkContainerType === NetworkContainerType.NETWORK_SHARE) {
if (component.value) {
if (!/(?<=\\\\)[^\\]*/.test(component.value)) {
return false;
@@ -282,7 +282,7 @@ export class DatabaseBackupPage extends MigrationWizardPage {
return true;
}).component();
this._networkShareLocationText.onTextChanged((value) => {
this.migrationStateModel.databaseBackup.networkShareLocation = value;
this.migrationStateModel._databaseBackup.networkShareLocation = value;
});
const windowsUserAccountLabel = view.modelBuilder.text()
@@ -297,7 +297,7 @@ export class DatabaseBackupPage extends MigrationWizardPage {
validationErrorMessage: constants.INVALID_USER_ACCOUNT
})
.withValidation((component) => {
if (this.migrationStateModel.databaseBackup.networkContainerType === NetworkContainerType.NETWORK_SHARE) {
if (this.migrationStateModel._databaseBackup.networkContainerType === NetworkContainerType.NETWORK_SHARE) {
if (component.value) {
if (!/(?<=\\).*$/.test(component.value)) {
return false;
@@ -307,7 +307,7 @@ export class DatabaseBackupPage extends MigrationWizardPage {
return true;
}).component();
this._windowsUserAccountText.onTextChanged((value) => {
this.migrationStateModel.databaseBackup.windowsUser = value;
this.migrationStateModel._databaseBackup.windowsUser = value;
});
const passwordLabel = view.modelBuilder.text()
@@ -322,7 +322,7 @@ export class DatabaseBackupPage extends MigrationWizardPage {
required: true
}).component();
this._passwordText.onTextChanged((value) => {
this.migrationStateModel.databaseBackup.password = value;
this.migrationStateModel._databaseBackup.password = value;
});
const azureAccountHelpText = view.modelBuilder.text()
@@ -341,8 +341,8 @@ export class DatabaseBackupPage extends MigrationWizardPage {
}).component();
this._networkShareContainerSubscriptionDropdown.onValueChanged(async (value) => {
if (value.selected) {
this.migrationStateModel.databaseBackup.subscription = this.migrationStateModel.getSubscription(value.index);
this.migrationStateModel._storageAccounts = undefined!;
this.migrationStateModel._databaseBackup.subscription = this.migrationStateModel.getSubscription(value.index);
this.migrationStateModel._databaseBackup.storageAccount = undefined!;
await this.loadNetworkShareStorageDropdown();
}
});
@@ -358,7 +358,7 @@ export class DatabaseBackupPage extends MigrationWizardPage {
}).component();
this._networkShareContainerStorageAccountDropdown.onValueChanged((value) => {
if (value.selected) {
this.migrationStateModel.databaseBackup.storageAccount = this.migrationStateModel.getStorageAccount(value.index);
this.migrationStateModel._databaseBackup.storageAccount = this.migrationStateModel.getStorageAccount(value.index);
}
});
@@ -399,11 +399,11 @@ export class DatabaseBackupPage extends MigrationWizardPage {
checked: true
}).component();
this.migrationStateModel.databaseBackup.migrationCutover = MigrationCutover.ONLINE;
this.migrationStateModel._databaseBackup.migrationCutover = MigrationCutover.ONLINE;
onlineButton.onDidChangeCheckedState((e) => {
if (e) {
this.migrationStateModel.databaseBackup.migrationCutover = MigrationCutover.ONLINE;
this.migrationStateModel._databaseBackup.migrationCutover = MigrationCutover.ONLINE;
}
});
@@ -414,7 +414,7 @@ export class DatabaseBackupPage extends MigrationWizardPage {
offlineButton.onDidChangeCheckedState((e) => {
if (e) {
this.migrationStateModel.databaseBackup.migrationCutover = MigrationCutover.OFFLINE;
this.migrationStateModel._databaseBackup.migrationCutover = MigrationCutover.OFFLINE;
}
});
@@ -443,7 +443,7 @@ export class DatabaseBackupPage extends MigrationWizardPage {
const errors: string[] = [];
switch (this.migrationStateModel.databaseBackup.networkContainerType) {
switch (this.migrationStateModel._databaseBackup.networkContainerType) {
case NetworkContainerType.NETWORK_SHARE:
if ((<azdata.CategoryValue>this._networkShareContainerSubscriptionDropdown.value).displayName === constants.NO_SUBSCRIPTIONS_FOUND) {
errors.push(constants.INVALID_SUBSCRIPTION_ERROR);
@@ -488,15 +488,15 @@ export class DatabaseBackupPage extends MigrationWizardPage {
}
public async onPageLeave(): Promise<void> {
this.migrationStateModel.databaseBackup.storageKey = (await getStorageAccountAccessKeys(this.migrationStateModel.azureAccount, this.migrationStateModel.databaseBackup.subscription, this.migrationStateModel.databaseBackup.storageAccount)).keyName1;
console.log(this.migrationStateModel.databaseBackup);
this.migrationStateModel._databaseBackup.storageKey = (await getStorageAccountAccessKeys(this.migrationStateModel._azureAccount, this.migrationStateModel._databaseBackup.subscription, this.migrationStateModel._databaseBackup.storageAccount)).keyName1;
console.log(this.migrationStateModel._databaseBackup);
}
protected async handleStateChange(e: StateChangeEvent): Promise<void> {
}
private toggleNetworkContainerFields(containerType: NetworkContainerType): void {
this.migrationStateModel.databaseBackup.networkContainerType = containerType;
this.migrationStateModel._databaseBackup.networkContainerType = containerType;
this._fileShareContainer.updateCssStyles({ 'display': (containerType === NetworkContainerType.FILE_SHARE) ? 'inline' : 'none' });
this._blobContainer.updateCssStyles({ 'display': (containerType === NetworkContainerType.BLOB_CONTAINER) ? 'inline' : 'none' });
this._networkShareContainer.updateCssStyles({ 'display': (containerType === NetworkContainerType.NETWORK_SHARE) ? 'inline' : 'none' });
@@ -525,89 +525,92 @@ export class DatabaseBackupPage extends MigrationWizardPage {
}
private async getSubscriptionValues(): Promise<void> {
this._networkShareContainerSubscriptionDropdown.loading = true;
this._fileShareSubscriptionDropdown.loading = true;
this._blobContainerSubscriptionDropdown.loading = true;
try {
this._fileShareSubscriptionDropdown.values = await this.migrationStateModel.getSubscriptionsDropdownValues();
this._networkShareContainerSubscriptionDropdown.values = await this.migrationStateModel.getSubscriptionsDropdownValues();
this._blobContainerSubscriptionDropdown.values = await this.migrationStateModel.getSubscriptionsDropdownValues();
this.migrationStateModel.databaseBackup.subscription = this.migrationStateModel.getSubscription(0);
} catch (error) {
this.migrationStateModel._storageAccounts = undefined!;
} finally {
await this.loadNetworkShareStorageDropdown();
await this.loadFileShareStorageDropdown();
await this.loadblobStorageDropdown();
this._networkShareContainerSubscriptionDropdown.loading = false;
this._fileShareSubscriptionDropdown.loading = false;
this._blobContainerSubscriptionDropdown.loading = false;
if (!this.migrationStateModel._databaseBackup.subscription) {
this._networkShareContainerSubscriptionDropdown.loading = true;
this._fileShareSubscriptionDropdown.loading = true;
this._blobContainerSubscriptionDropdown.loading = true;
try {
const subscriptionDropdownValues = await this.migrationStateModel.getSubscriptionsDropdownValues();
this._fileShareSubscriptionDropdown.values = subscriptionDropdownValues;
this._networkShareContainerSubscriptionDropdown.values = subscriptionDropdownValues;
this._blobContainerSubscriptionDropdown.values = subscriptionDropdownValues;
} catch (error) {
console.log(error);
} finally {
this._networkShareContainerSubscriptionDropdown.loading = false;
this._fileShareSubscriptionDropdown.loading = false;
this._blobContainerSubscriptionDropdown.loading = false;
}
}
}
private async loadNetworkShareStorageDropdown(): Promise<void> {
this._networkShareContainerStorageAccountDropdown.loading = true;
try {
this._networkShareContainerStorageAccountDropdown.values = await this.migrationStateModel.getStorageAccountValues(this.migrationStateModel.databaseBackup.subscription);
this.migrationStateModel.databaseBackup.storageAccount = this.migrationStateModel.getStorageAccount(0);
} finally {
this._networkShareContainerStorageAccountDropdown.loading = false;
if (!this.migrationStateModel._databaseBackup.storageAccount) {
this._networkShareContainerStorageAccountDropdown.loading = true;
try {
this._networkShareContainerStorageAccountDropdown.values = await this.migrationStateModel.getStorageAccountValues(this.migrationStateModel._databaseBackup.subscription);
} catch (error) {
console.log(error);
} finally {
this._networkShareContainerStorageAccountDropdown.loading = false;
}
}
}
private async loadFileShareStorageDropdown(): Promise<void> {
this._fileShareStorageAccountDropdown.loading = true;
this._fileShareFileShareDropdown.loading = true;
try {
this._fileShareStorageAccountDropdown.values = await this.migrationStateModel.getStorageAccountValues(this.migrationStateModel.databaseBackup.subscription);
this.migrationStateModel.databaseBackup.storageAccount = this.migrationStateModel.getStorageAccount(0);
} catch (error) {
this.migrationStateModel._fileShares = undefined!;
} finally {
await this.loadFileShareDropdown();
this._fileShareStorageAccountDropdown.loading = false;
this._fileShareFileShareDropdown.loading = false;
if (!this.migrationStateModel._databaseBackup.storageAccount) {
this._fileShareStorageAccountDropdown.loading = true;
this._fileShareFileShareDropdown.loading = true;
try {
this._fileShareStorageAccountDropdown.values = await this.migrationStateModel.getStorageAccountValues(this.migrationStateModel._databaseBackup.subscription);
} catch (error) {
console.log(error);
} finally {
this._fileShareStorageAccountDropdown.loading = false;
this._fileShareFileShareDropdown.loading = false;
}
}
}
private async loadblobStorageDropdown(): Promise<void> {
this._blobContainerStorageAccountDropdown.loading = true;
this._blobContainerBlobDropdown.loading = true;
try {
this._blobContainerStorageAccountDropdown.values = await this.migrationStateModel.getStorageAccountValues(this.migrationStateModel.databaseBackup.subscription);
this.migrationStateModel.databaseBackup.storageAccount = this.migrationStateModel.getStorageAccount(0);
} catch (error) {
this.migrationStateModel._blobContainers = undefined!;
} finally {
await this.loadBlobContainerDropdown();
this._blobContainerStorageAccountDropdown.loading = false;
if (!this.migrationStateModel._databaseBackup.storageAccount) {
this._blobContainerStorageAccountDropdown.loading = true;
this._blobContainerBlobDropdown.loading = true;
try {
this._blobContainerStorageAccountDropdown.values = await this.migrationStateModel.getStorageAccountValues(this.migrationStateModel._databaseBackup.subscription);
} catch (error) {
console.log(error);
} finally {
this._blobContainerStorageAccountDropdown.loading = false;
this._blobContainerBlobDropdown.loading = true;
}
}
}
private async loadFileShareDropdown(): Promise<void> {
this._fileShareFileShareDropdown.loading = true;
try {
this._fileShareFileShareDropdown.values = await this.migrationStateModel.getFileShareValues(this.migrationStateModel.databaseBackup.subscription, this.migrationStateModel.databaseBackup.storageAccount);
this.migrationStateModel.databaseBackup.fileShare = this.migrationStateModel.getFileShare(0);
} catch (error) {
console.log(error);
} finally {
this._fileShareFileShareDropdown.loading = false;
if (!this.migrationStateModel._fileShares) {
this._fileShareFileShareDropdown.loading = true;
try {
this._fileShareFileShareDropdown.values = await this.migrationStateModel.getFileShareValues(this.migrationStateModel._databaseBackup.subscription, this.migrationStateModel._databaseBackup.storageAccount);
} catch (error) {
console.log(error);
} finally {
this._fileShareFileShareDropdown.loading = false;
}
}
}
private async loadBlobContainerDropdown(): Promise<void> {
this._blobContainerBlobDropdown.loading = true;
try {
this._blobContainerBlobDropdown.values = await this.migrationStateModel.getBlobContainerValues(this.migrationStateModel.databaseBackup.subscription, this.migrationStateModel.databaseBackup.storageAccount);
this.migrationStateModel.databaseBackup.blobContainer = this.migrationStateModel.getBlobContainer(0);
} catch (error) {
console.log(error);
} finally {
this._blobContainerBlobDropdown.loading = false;
if (!this.migrationStateModel._blobContainers) {
this._blobContainerBlobDropdown.loading = true;
try {
this._blobContainerBlobDropdown.values = await this.migrationStateModel.getBlobContainerValues(this.migrationStateModel._databaseBackup.subscription, this.migrationStateModel._databaseBackup.storageAccount);
} catch (error) {
console.log(error);
} finally {
this._blobContainerBlobDropdown.loading = false;
}
}
}
}

View File

@@ -4,19 +4,22 @@
*--------------------------------------------------------------------------------------------*/
import * as azdata from 'azdata';
import * as vscode from 'vscode';
import { MigrationWizardPage } from '../models/migrationWizardPage';
import { MigrationStateModel, StateChangeEvent } from '../models/stateMachine';
import { CreateMigrationControllerDialog } from '../dialog/createMigrationDialog/createMigrationControllerDialog';
import * as constants from '../models/strings';
import * as os from 'os';
import { WIZARD_INPUT_COMPONENT_WIDTH } from './wizardController';
import { createInformationRow, WIZARD_INPUT_COMPONENT_WIDTH } from './wizardController';
import { getMigrationController, getMigrationControllerAuthKeys, getMigrationControllerMonitoringData } from '../api/azure';
import { IconPathHelper } from '../constants/iconPathHelper';
export class IntergrationRuntimePage extends MigrationWizardPage {
private migrationControllerDropdown!: azdata.DropDownComponent;
private _connectionStatus!: azdata.InfoBoxComponent;
private _view!: azdata.ModelView;
private _form!: azdata.FormBuilder;
private _statusLoadingComponent!: azdata.LoadingComponent;
private _migrationDetailsContainer!: azdata.FlexContainer;
constructor(wizard: azdata.window.Wizard, migrationStateModel: MigrationStateModel) {
super(wizard, azdata.window.createWizardPage(constants.IR_PAGE_TITLE), migrationStateModel);
@@ -35,7 +38,10 @@ export class IntergrationRuntimePage extends MigrationWizardPage {
dialog.initialize();
});
this._connectionStatus = view.modelBuilder.infoBox().component();
this._migrationDetailsContainer = view.modelBuilder.flexContainer().withLayout({
flexFlow: 'column'
}).component();
this._statusLoadingComponent = view.modelBuilder.loadingComponent().withItem(this._migrationDetailsContainer).component();
this._form = view.modelBuilder.formContainer()
.withFormItems(
@@ -47,7 +53,7 @@ export class IntergrationRuntimePage extends MigrationWizardPage {
component: createNewController
},
{
component: this._connectionStatus
component: this._statusLoadingComponent
}
]
@@ -59,23 +65,30 @@ export class IntergrationRuntimePage extends MigrationWizardPage {
this.populateMigrationController();
this.wizard.registerNavigationValidator((pageChangeInfo) => {
if (pageChangeInfo.newPage < pageChangeInfo.lastPage) {
this.wizard.message = {
text: ''
};
return true;
}
const errors: string[] = [];
if (((<azdata.CategoryValue>this.migrationControllerDropdown.value).displayName === constants.CONTROLLER_NOT_FOUND)) {
errors.push(constants.CONTROLLER_NOT_SETUP_ERROR);
}
this.wizard.message = {
text: errors.join(os.EOL),
level: azdata.window.MessageLevel.Error
};
if (errors.length > 0) {
const state = this.migrationStateModel._migrationController.properties.integrationRuntimeState;
if (!this.migrationStateModel._migrationController) {
this.wizard.message = {
level: azdata.window.MessageLevel.Error,
text: constants.INVALID_CONTROLLER_ERROR
};
return false;
}
if (state !== 'Online') {
this.wizard.message = {
level: azdata.window.MessageLevel.Error,
text: constants.CONTROLLER_OFFLINE_ERROR
};
return false;
} else {
this.wizard.message = {
text: ''
};
}
return true;
});
}
@@ -113,6 +126,16 @@ export class IntergrationRuntimePage extends MigrationWizardPage {
width: WIZARD_INPUT_COMPONENT_WIDTH
}).component();
this.migrationControllerDropdown.onValueChanged(async (value) => {
if (value.selected) {
this.wizard.message = {
text: ''
};
this.migrationStateModel._migrationController = this.migrationStateModel.getMigrationController(value.index);
await this.loadControllerStatus();
}
});
const flexContainer = this._view.modelBuilder.flexContainer().withItems([
descriptionText,
noteText,
@@ -126,49 +149,278 @@ export class IntergrationRuntimePage extends MigrationWizardPage {
public async populateMigrationController(controllerStatus?: string): Promise<void> {
this.migrationControllerDropdown.loading = true;
let migrationContollerValues: azdata.CategoryValue[] = [];
// TODO: Replace with this code when APIs are deployed.
// try{
// this.migrationControllerDropdown.values = await this.migrationStateModel.getMigrationControllerValues(this.migrationStateModel._targetSubscription, this.migrationStateModel._targetManagedInstance);
// this.migrationStateModel.migrationController = this.migrationStateModel.getMigrationController(0);
// } catch (e) {
// } finally {
// this.migrationControllerDropdown.loading = false;
// }
if (this.migrationStateModel.migrationController) {
this._connectionStatus.updateProperties(<azdata.InfoBoxComponentProperties>{
text: constants.CONTROLLER_READY(this.migrationStateModel.migrationController!.name, this.migrationStateModel._nodeNames.join(', ')),
style: 'success'
});
this._form.addFormItem({
component: this._connectionStatus
});
migrationContollerValues = [
{
displayName: this.migrationStateModel.migrationController.name,
name: ''
}
];
try {
this.migrationControllerDropdown.values = await this.migrationStateModel.getMigrationControllerValues(this.migrationStateModel._targetSubscription, this.migrationStateModel._targetManagedInstance);
if (this.migrationStateModel._migrationController) {
this.migrationControllerDropdown.value = {
name: this.migrationStateModel._migrationController.id,
displayName: this.migrationStateModel._migrationController.name
};
} else {
this.migrationStateModel._migrationController = this.migrationStateModel.getMigrationController(0);
}
} catch (error) {
console.log(error);
} finally {
this.migrationControllerDropdown.loading = false;
}
else {
migrationContollerValues = [
{
displayName: constants.CONTROLLER_NOT_FOUND,
name: ''
}
];
this._form.removeFormItem({
component: this._connectionStatus
});
}
this.migrationControllerDropdown.values = migrationContollerValues;
this.migrationControllerDropdown.loading = false;
}
private async loadControllerStatus(): Promise<void> {
this._statusLoadingComponent.loading = true;
try {
this._migrationDetailsContainer.clearItems();
if (this.migrationStateModel._migrationController) {
const controller = await getMigrationController(
this.migrationStateModel._azureAccount,
this.migrationStateModel._targetSubscription,
this.migrationStateModel._migrationController.properties.resourceGroup,
this.migrationStateModel._migrationController.properties.location,
this.migrationStateModel._migrationController.name);
this.migrationStateModel._migrationController = controller;
const controllerMonitoringStatus = await getMigrationControllerMonitoringData(
this.migrationStateModel._azureAccount,
this.migrationStateModel._targetSubscription,
this.migrationStateModel._migrationController.properties.resourceGroup,
this.migrationStateModel._migrationController.properties.location,
this.migrationStateModel._migrationController!.name);
this.migrationStateModel._nodeNames = controllerMonitoringStatus.nodes.map((node) => {
return node.nodeName;
});
const migrationControllerAuthKeys = await getMigrationControllerAuthKeys(
this.migrationStateModel._azureAccount,
this.migrationStateModel._targetSubscription,
this.migrationStateModel._migrationController.properties.resourceGroup,
this.migrationStateModel._migrationController.properties.location,
this.migrationStateModel._migrationController!.name
);
const migrationControllerTitle = this._view.modelBuilder.text().withProps({
value: constants.CONTROLLER_DETAILS_HEADER(controller.name),
CSSStyles: {
'font-weight': 'bold'
}
}).component();
const connectionStatusLabel = this._view.modelBuilder.text().withProps({
value: constants.CONTROLLER_CONNECTION_STATUS,
CSSStyles: {
'font-weight': 'bold',
'width': '150px'
}
}).component();
const refreshStatus = this._view.modelBuilder.button().withProps({
label: constants.REFRESH,
secondary: true,
width: '50px'
}).component();
const connectionLabelContainer = this._view.modelBuilder.flexContainer().withLayout({
flexFlow: 'row',
alignItems: 'center'
}).withItems(
[
connectionStatusLabel,
refreshStatus
],
{
CSSStyles: { 'margin-right': '5px' }
}
).component();
const connectionStatus = this._view.modelBuilder.infoBox().component();
const connectionStatusLoader = this._view.modelBuilder.loadingComponent().withItem(connectionStatus).withProps({
loading: false
}).component();
refreshStatus.onDidClick(async (e) => {
connectionStatusLoader.loading = true;
const controller = await getMigrationController(
this.migrationStateModel._azureAccount,
this.migrationStateModel._targetSubscription,
this.migrationStateModel._migrationController.properties.resourceGroup,
this.migrationStateModel._migrationController.properties.location,
this.migrationStateModel._migrationController.name);
this.migrationStateModel._migrationController = controller;
const controllerMonitoringStatus = await getMigrationControllerMonitoringData(
this.migrationStateModel._azureAccount,
this.migrationStateModel._targetSubscription,
this.migrationStateModel._migrationController.properties.resourceGroup,
this.migrationStateModel._migrationController.properties.location,
this.migrationStateModel._migrationController!.name);
this.migrationStateModel._nodeNames = controllerMonitoringStatus.nodes.map((node) => {
return node.nodeName;
});
const state = controller.properties.integrationRuntimeState;
if (state === 'Online') {
connectionStatus.updateProperties(<azdata.InfoBoxComponentProperties>{
text: constants.CONTROLLER_READY(this.migrationStateModel._migrationController!.name, this.migrationStateModel._nodeNames.join(', ')),
style: 'success'
});
} else {
connectionStatus.updateProperties(<azdata.InfoBoxComponentProperties>{
text: constants.CONTROLLER_NOT_READY(this.migrationStateModel._migrationController!.name),
style: 'error'
});
}
connectionStatusLoader.loading = false;
});
if (controller) {
const state = controller.properties.integrationRuntimeState;
if (state === 'Online') {
connectionStatus.updateProperties(<azdata.InfoBoxComponentProperties>{
text: constants.CONTROLLER_READY(this.migrationStateModel._migrationController!.name, this.migrationStateModel._nodeNames.join(', ')),
style: 'success'
});
} else {
connectionStatus.updateProperties(<azdata.InfoBoxComponentProperties>{
text: constants.CONTROLLER_NOT_READY(this.migrationStateModel._migrationController!.name),
style: 'error'
});
}
}
const authenticationKeysLabel = this._view.modelBuilder.text().withProps({
value: constants.AUTHENTICATION_KEYS,
CSSStyles: {
'font-weight': 'bold'
}
}).component();
const migrationControllerAuthKeyTable = this._view.modelBuilder.declarativeTable().withProps({
columns: [
{
displayName: constants.NAME,
valueType: azdata.DeclarativeDataType.string,
width: '50px',
isReadOnly: true,
rowCssStyles: {
'text-align': 'center'
}
},
{
displayName: constants.AUTH_KEY_COLUMN_HEADER,
valueType: azdata.DeclarativeDataType.string,
width: '500px',
isReadOnly: true,
rowCssStyles: {
overflow: 'scroll'
}
},
{
displayName: '',
valueType: azdata.DeclarativeDataType.component,
width: '15px',
isReadOnly: true,
},
{
displayName: '',
valueType: azdata.DeclarativeDataType.component,
width: '15px',
isReadOnly: true,
}
],
CSSStyles: {
'margin-top': '5px'
}
}).component();
const copyKey1Button = this._view.modelBuilder.button().withProps({
iconPath: IconPathHelper.copy
}).component();
copyKey1Button.onDidClick((e) => {
vscode.env.clipboard.writeText(<string>migrationControllerAuthKeyTable.dataValues![0][1].value);
vscode.window.showInformationMessage(constants.CONTROLLER_KEY_COPIED_HELP);
});
const copyKey2Button = this._view.modelBuilder.button().withProps({
iconPath: IconPathHelper.copy
}).component();
copyKey2Button.onDidClick((e) => {
vscode.env.clipboard.writeText(<string>migrationControllerAuthKeyTable.dataValues![1][1].value);
vscode.window.showInformationMessage(constants.CONTROLLER_KEY_COPIED_HELP);
});
const refreshKey1Button = this._view.modelBuilder.button().withProps({
iconPath: IconPathHelper.refresh
}).component();
refreshKey1Button.onDidClick((e) => {//TODO: add refresh logic
});
const refreshKey2Button = this._view.modelBuilder.button().withProps({
iconPath: IconPathHelper.refresh
}).component();
refreshKey2Button.onDidClick((e) => {//TODO: add refresh logic
});
migrationControllerAuthKeyTable.updateProperties({
dataValues: [
[
{
value: constants.CONTROLLER_KEY1_LABEL
},
{
value: migrationControllerAuthKeys.authKey1
},
{
value: copyKey1Button
},
{
value: refreshKey1Button
}
],
[
{
value: constants.CONTROLLER_KEY2_LABEL
},
{
value: migrationControllerAuthKeys.authKey2
},
{
value: copyKey2Button
},
{
value: refreshKey2Button
}
]
]
});
this._migrationDetailsContainer.addItems(
[
migrationControllerTitle,
createInformationRow(this._view, constants.SUBSCRIPTION, this.migrationStateModel._targetSubscription.name),
createInformationRow(this._view, constants.RESOURCE_GROUP, controller.properties.resourceGroup),
createInformationRow(this._view, constants.LOCATION, controller.properties.location),
connectionLabelContainer,
connectionStatusLoader,
authenticationKeysLabel,
migrationControllerAuthKeyTable
]
);
}
} catch (error) {
console.log(error);
this._migrationDetailsContainer.clearItems();
} finally {
this._statusLoadingComponent.loading = false;
}
}
}

View File

@@ -7,6 +7,7 @@ import * as azdata from 'azdata';
import { MigrationWizardPage } from '../models/migrationWizardPage';
import { MigrationStateModel, NetworkContainerType, StateChangeEvent } from '../models/stateMachine';
import * as constants from '../models/strings';
import { createHeadingTextComponent, createInformationRow } from './wizardController';
export class SummaryPage extends MigrationWizardPage {
private _view!: azdata.ModelView;
@@ -35,22 +36,18 @@ export class SummaryPage extends MigrationWizardPage {
public async onPageEnter(): Promise<void> {
this._flexContainer.addItems(
[
this.createHeadingTextComponent(constants.AZURE_ACCOUNT_LINKED),
this.createHeadingTextComponent(this.migrationStateModel.azureAccount.displayInfo.displayName),
this.createHeadingTextComponent(constants.MIGRATION_TARGET),
this.createInformationRow(constants.TYPE, constants.SUMMARY_MI_TYPE),
this.createInformationRow(constants.SUBSCRIPTION, this.migrationStateModel._targetSubscription.name),
this.createInformationRow(constants.SUMMARY_MI_TYPE, this.migrationStateModel._targetManagedInstance.name),
this.createInformationRow(constants.SUMMARY_DATABASE_COUNT_LABEL, '1'),
this.createHeadingTextComponent(constants.DATABASE_BACKUP_PAGE_TITLE),
createHeadingTextComponent(this._view, constants.AZURE_ACCOUNT_LINKED),
createHeadingTextComponent(this._view, this.migrationStateModel._azureAccount.displayInfo.displayName),
createHeadingTextComponent(this._view, constants.MIGRATION_TARGET),
createInformationRow(this._view, constants.TYPE, constants.SUMMARY_MI_TYPE),
createInformationRow(this._view, constants.SUBSCRIPTION, this.migrationStateModel._targetSubscription.name),
createInformationRow(this._view, constants.SUMMARY_MI_TYPE, this.migrationStateModel._targetManagedInstance.name),
createInformationRow(this._view, constants.SUMMARY_DATABASE_COUNT_LABEL, '1'),
createHeadingTextComponent(this._view, constants.DATABASE_BACKUP_PAGE_TITLE),
this.createNetworkContainerRows(),
this.createHeadingTextComponent(constants.IR_PAGE_TITLE),
this.createInformationRow(constants.IR_PAGE_TITLE, this.migrationStateModel.migrationController?.name!),
this.createInformationRow(constants.SUMMARY_IR_NODE, this.migrationStateModel._nodeNames.join(', ')),
createHeadingTextComponent(this._view, constants.IR_PAGE_TITLE),
createInformationRow(this._view, constants.IR_PAGE_TITLE, this.migrationStateModel._migrationController?.name!),
createInformationRow(this._view, constants.SUMMARY_IR_NODE, this.migrationStateModel._nodeNames.join(', ')),
]
);
@@ -66,82 +63,39 @@ export class SummaryPage extends MigrationWizardPage {
protected async handleStateChange(e: StateChangeEvent): Promise<void> {
}
private createInformationRow(label: string, value: string): azdata.FlexContainer {
return this._view.modelBuilder.flexContainer()
.withLayout(
{
flexFlow: 'row',
alignItems: 'center',
})
.withItems(
[
this.creaetLabelTextComponent(label),
this.createTextCompononent(value)
],
{
CSSStyles: { 'margin-right': '5px' }
})
.component();
}
private createHeadingTextComponent(value: string): azdata.TextComponent {
const component = this.createTextCompononent(value);
component.updateCssStyles({
'font-size': '13px',
'font-weight': 'bold'
});
return component;
}
private creaetLabelTextComponent(value: string): azdata.TextComponent {
const component = this.createTextCompononent(value);
component.updateCssStyles({
'color': '#595959',
'width': '250px'
});
return component;
}
private createTextCompononent(value: string): azdata.TextComponent {
return this._view.modelBuilder.text().withProps({
value: value
}).component();
}
private createNetworkContainerRows(): azdata.FlexContainer {
const flexContainer = this._view.modelBuilder.flexContainer().withLayout({
flexFlow: 'column'
}).component();
switch (this.migrationStateModel.databaseBackup.networkContainerType) {
switch (this.migrationStateModel._databaseBackup.networkContainerType) {
case NetworkContainerType.NETWORK_SHARE:
flexContainer.addItems(
[
this.createInformationRow(constants.TYPE, constants.NETWORK_SHARE),
this.createInformationRow(constants.PATH, this.migrationStateModel.databaseBackup.networkShareLocation),
this.createInformationRow(constants.USER_ACCOUNT, this.migrationStateModel.databaseBackup.windowsUser),
this.createInformationRow(constants.SUMMARY_AZURE_STORAGE_SUBSCRIPTION, this.migrationStateModel.databaseBackup.subscription.name),
this.createInformationRow(constants.SUMMARY_AZURE_STORAGE, this.migrationStateModel.databaseBackup.storageAccount.name),
createInformationRow(this._view, constants.TYPE, constants.NETWORK_SHARE),
createInformationRow(this._view, constants.PATH, this.migrationStateModel._databaseBackup.networkShareLocation),
createInformationRow(this._view, constants.USER_ACCOUNT, this.migrationStateModel._databaseBackup.windowsUser),
createInformationRow(this._view, constants.SUMMARY_AZURE_STORAGE_SUBSCRIPTION, this.migrationStateModel._databaseBackup.subscription.name),
createInformationRow(this._view, constants.SUMMARY_AZURE_STORAGE, this.migrationStateModel._databaseBackup.storageAccount.name),
]
);
break;
case NetworkContainerType.FILE_SHARE:
flexContainer.addItems(
[
this.createInformationRow(constants.TYPE, constants.FILE_SHARE),
this.createInformationRow(constants.SUMMARY_AZURE_STORAGE_SUBSCRIPTION, this.migrationStateModel.databaseBackup.subscription.name),
this.createInformationRow(constants.SUMMARY_AZURE_STORAGE, this.migrationStateModel.databaseBackup.storageAccount.name),
this.createInformationRow(constants.FILE_SHARE, this.migrationStateModel.databaseBackup.fileShare.name),
createInformationRow(this._view, constants.TYPE, constants.FILE_SHARE),
createInformationRow(this._view, constants.SUMMARY_AZURE_STORAGE_SUBSCRIPTION, this.migrationStateModel._databaseBackup.subscription.name),
createInformationRow(this._view, constants.SUMMARY_AZURE_STORAGE, this.migrationStateModel._databaseBackup.storageAccount.name),
createInformationRow(this._view, constants.FILE_SHARE, this.migrationStateModel._databaseBackup.fileShare.name),
]
);
break;
case NetworkContainerType.BLOB_CONTAINER:
flexContainer.addItems(
[
this.createInformationRow(constants.TYPE, constants.BLOB_CONTAINER),
this.createInformationRow(constants.SUMMARY_AZURE_STORAGE_SUBSCRIPTION, this.migrationStateModel.databaseBackup.blobContainer.subscription.name),
this.createInformationRow(constants.SUMMARY_AZURE_STORAGE, this.migrationStateModel.databaseBackup.storageAccount.name),
this.createInformationRow(constants.BLOB_CONTAINER, this.migrationStateModel.databaseBackup.blobContainer.name),
createInformationRow(this._view, constants.TYPE, constants.BLOB_CONTAINER),
createInformationRow(this._view, constants.SUMMARY_AZURE_STORAGE_SUBSCRIPTION, this.migrationStateModel._databaseBackup.blobContainer.subscription.name),
createInformationRow(this._view, constants.SUMMARY_AZURE_STORAGE, this.migrationStateModel._databaseBackup.storageAccount.name),
createInformationRow(this._view, constants.BLOB_CONTAINER, this.migrationStateModel._databaseBackup.blobContainer.name),
]
);
}

View File

@@ -32,7 +32,8 @@ export class TempTargetSelectionPage extends MigrationWizardPage {
this._managedInstanceSubscriptionDropdown.onValueChanged((e) => {
if (e.selected) {
this.migrationStateModel._targetSubscription = this.migrationStateModel.getSubscription(e.index);
this.migrationStateModel._targetManagedInstances = undefined!;
this.migrationStateModel._targetManagedInstance = undefined!;
this.migrationStateModel._migrationController = undefined!;
this.populateManagedInstanceDropdown();
}
});
@@ -47,7 +48,7 @@ export class TempTargetSelectionPage extends MigrationWizardPage {
}).component();
this._managedInstanceDropdown.onValueChanged((e) => {
if (e.selected) {
this.migrationStateModel.migrationControllers = undefined!;
this.migrationStateModel._migrationControllers = undefined!;
this.migrationStateModel._targetManagedInstance = this.migrationStateModel.getManagedInstance(e.index);
}
});
@@ -77,35 +78,34 @@ export class TempTargetSelectionPage extends MigrationWizardPage {
this.populateSubscriptionDropdown();
}
public async onPageLeave(): Promise<void> {
console.log(this.migrationStateModel._targetSubscription);
console.log(this.migrationStateModel._targetManagedInstance);
}
protected async handleStateChange(e: StateChangeEvent): Promise<void> {
}
private async populateSubscriptionDropdown(): Promise<void> {
this._managedInstanceSubscriptionDropdown.loading = true;
this._managedInstanceDropdown.loading = true;
try {
this._managedInstanceSubscriptionDropdown.values = await this.migrationStateModel.getSubscriptionsDropdownValues();
this.migrationStateModel._targetSubscription = this.migrationStateModel.getSubscription(0);
} catch (e) {
this.migrationStateModel._targetManagedInstances = undefined!;
} finally {
this.populateManagedInstanceDropdown();
this._managedInstanceSubscriptionDropdown.loading = false;
this._managedInstanceDropdown.loading = false;
if (!this.migrationStateModel._targetSubscription) {
this._managedInstanceSubscriptionDropdown.loading = true;
this._managedInstanceDropdown.loading = true;
try {
this._managedInstanceSubscriptionDropdown.values = await this.migrationStateModel.getSubscriptionsDropdownValues();
} catch (e) {
console.log(e);
} finally {
this._managedInstanceSubscriptionDropdown.loading = false;
}
}
}
private async populateManagedInstanceDropdown(): Promise<void> {
this._managedInstanceDropdown.loading = true;
try {
this._managedInstanceDropdown.values = await this.migrationStateModel.getManagedInstanceValues(this.migrationStateModel._targetSubscription);
this.migrationStateModel._targetManagedInstance = this.migrationStateModel.getManagedInstance(0);
} finally {
this._managedInstanceDropdown.loading = false;
if (!this.migrationStateModel._targetManagedInstance) {
this._managedInstanceDropdown.loading = true;
try {
this._managedInstanceDropdown.values = await this.migrationStateModel.getManagedInstanceValues(this.migrationStateModel._targetSubscription);
} catch (e) {
console.log(e);
} finally {
this._managedInstanceDropdown.loading = false;
}
}
}
}

View File

@@ -6,7 +6,7 @@ import * as azdata from 'azdata';
import * as vscode from 'vscode';
import * as mssql from '../../../mssql';
import { MigrationStateModel } from '../models/stateMachine';
import { SourceConfigurationPage } from './sourceConfigurationPage';
// import { SourceConfigurationPage } from './sourceConfigurationPage';
import { WIZARD_TITLE } from '../models/strings';
import { MigrationWizardPage } from '../models/migrationWizardPage';
import { SKURecommendationPage } from './skuRecommendationPage';
@@ -36,7 +36,7 @@ export class WizardController {
const wizard = azdata.window.createWizard(WIZARD_TITLE, 'wide');
wizard.generateScriptButton.enabled = false;
wizard.generateScriptButton.hidden = true;
const sourceConfigurationPage = new SourceConfigurationPage(wizard, stateModel);
// const sourceConfigurationPage = new SourceConfigurationPage(wizard, stateModel);
const skuRecommendationPage = new SKURecommendationPage(wizard, stateModel);
// const subscriptionSelectionPage = new SubscriptionSelectionPage(wizard, stateModel);
const azureAccountsPage = new AccountsSelectionPage(wizard, stateModel);
@@ -49,7 +49,7 @@ export class WizardController {
// subscriptionSelectionPage,
azureAccountsPage,
tempTargetSelectionPage,
sourceConfigurationPage,
// sourceConfigurationPage,
skuRecommendationPage,
databaseBackupPage,
integrationRuntimePage,
@@ -88,3 +88,45 @@ export class WizardController {
});
}
}
export function createInformationRow(view: azdata.ModelView, label: string, value: string): azdata.FlexContainer {
return view.modelBuilder.flexContainer()
.withLayout(
{
flexFlow: 'row',
alignItems: 'center',
})
.withItems(
[
creaetLabelTextComponent(view, label),
createTextCompononent(view, value)
],
{
CSSStyles: { 'margin-right': '5px' }
})
.component();
}
export function createHeadingTextComponent(view: azdata.ModelView, value: string): azdata.TextComponent {
const component = createTextCompononent(view, value);
component.updateCssStyles({
'font-size': '13px',
'font-weight': 'bold'
});
return component;
}
export function creaetLabelTextComponent(view: azdata.ModelView, value: string): azdata.TextComponent {
const component = createTextCompononent(view, value);
component.updateCssStyles({
'width': '250px'
});
return component;
}
export function createTextCompononent(view: azdata.ModelView, value: string): azdata.TextComponent {
return view.modelBuilder.text().withProps({
value: value
}).component();
}