mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-02-16 10:58:30 -05:00
Adding migration status and cutover to extension (#14482)
This commit is contained in:
@@ -8,11 +8,10 @@ import * as path from 'path';
|
||||
import { MigrationWizardPage } from '../models/migrationWizardPage';
|
||||
import { MigrationStateModel, StateChangeEvent } from '../models/stateMachine';
|
||||
import { Product, ProductLookupTable } from '../models/product';
|
||||
import { Disposable } from 'vscode';
|
||||
import { AssessmentResultsDialog } from '../dialog/assessmentResults/assessmentResultsDialog';
|
||||
import { getAvailableManagedInstanceProducts, getSubscriptions, SqlManagedInstance, Subscription } from '../api/azure';
|
||||
import * as constants from '../models/strings';
|
||||
import { azureResource } from 'azureResource';
|
||||
import * as constants from '../constants/strings';
|
||||
import * as vscode from 'vscode';
|
||||
import { EOL } from 'os';
|
||||
|
||||
// import { SqlMigrationService } from '../../../../extensions/mssql/src/sqlMigration/sqlMigrationService';
|
||||
|
||||
@@ -32,11 +31,11 @@ export class SKURecommendationPage extends MigrationWizardPage {
|
||||
private _azureSubscriptionText: azdata.FormComponent<azdata.TextComponent> | undefined;
|
||||
private _managedInstanceSubscriptionDropdown!: azdata.DropDownComponent;
|
||||
private _managedInstanceDropdown!: azdata.DropDownComponent;
|
||||
private _subscriptionDropdownValues: azdata.CategoryValue[] = [];
|
||||
private _subscriptionMap: Map<string, Subscription> = new Map();
|
||||
private _view: azdata.ModelView | undefined;
|
||||
private _rbg!: azdata.RadioCardGroupComponent;
|
||||
|
||||
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
|
||||
this._chooseTargetComponent = this.createChooseTargetComponent(view);
|
||||
@@ -47,12 +46,24 @@ export class SKURecommendationPage extends MigrationWizardPage {
|
||||
}).component();
|
||||
this._managedInstanceSubscriptionDropdown = view.modelBuilder.dropDown().component();
|
||||
this._managedInstanceSubscriptionDropdown.onValueChanged((e) => {
|
||||
this.populateManagedInstanceDropdown();
|
||||
if (e.selected) {
|
||||
this.migrationStateModel._targetSubscription = this.migrationStateModel.getSubscription(e.index);
|
||||
this.migrationStateModel._targetManagedInstance = undefined!;
|
||||
this.migrationStateModel._migrationController = undefined!;
|
||||
this.populateManagedInstanceDropdown();
|
||||
}
|
||||
});
|
||||
const managedInstanceDropdownLabel = view.modelBuilder.text().withProps({
|
||||
value: constants.MANAGED_INSTANCE
|
||||
}).component();
|
||||
|
||||
this._managedInstanceDropdown = view.modelBuilder.dropDown().component();
|
||||
this._managedInstanceDropdown.onValueChanged((e) => {
|
||||
if (e.selected) {
|
||||
this.migrationStateModel._migrationControllers = undefined!;
|
||||
this.migrationStateModel._targetManagedInstance = this.migrationStateModel.getManagedInstance(e.index);
|
||||
}
|
||||
});
|
||||
|
||||
const targetContainer = view.modelBuilder.flexContainer().withItems(
|
||||
[
|
||||
@@ -137,18 +148,23 @@ export class SKURecommendationPage extends MigrationWizardPage {
|
||||
private constructTargets(): void {
|
||||
const products: Product[] = Object.values(ProductLookupTable);
|
||||
|
||||
const rbg = this._view!.modelBuilder.radioCardGroup().withProperties<azdata.RadioCardGroupComponentProperties>({
|
||||
this._rbg = this._view!.modelBuilder.radioCardGroup().withProperties<azdata.RadioCardGroupComponentProperties>({
|
||||
cards: [],
|
||||
cardWidth: '600px',
|
||||
cardHeight: '60px',
|
||||
orientation: azdata.Orientation.Vertical,
|
||||
iconHeight: '30px',
|
||||
iconWidth: '30px'
|
||||
});
|
||||
}).component();
|
||||
|
||||
products.forEach((product) => {
|
||||
const imagePath = path.resolve(this.migrationStateModel.getExtensionPath(), 'media', product.icon ?? 'ads.svg');
|
||||
|
||||
let dbCount = 0;
|
||||
if (product.type === 'AzureSQLVM') {
|
||||
dbCount = 0;
|
||||
} else {
|
||||
dbCount = this.migrationStateModel._migrationDbs.length;
|
||||
}
|
||||
const descriptions: azdata.RadioCardDescription[] = [
|
||||
{
|
||||
textValue: product.name,
|
||||
@@ -164,7 +180,7 @@ export class SKURecommendationPage extends MigrationWizardPage {
|
||||
}
|
||||
},
|
||||
{
|
||||
textValue: '9 databases will be migrated',
|
||||
textValue: `${dbCount} databases will be migrated`,
|
||||
linkDisplayValue: 'View/Change',
|
||||
displayLinkCodicon: true,
|
||||
linkCodiconStyles: {
|
||||
@@ -174,22 +190,31 @@ export class SKURecommendationPage extends MigrationWizardPage {
|
||||
}
|
||||
];
|
||||
|
||||
rbg.component().cards.push({
|
||||
id: product.name,
|
||||
this._rbg.cards.push({
|
||||
id: product.type,
|
||||
icon: imagePath,
|
||||
descriptions
|
||||
});
|
||||
});
|
||||
|
||||
rbg.component().onLinkClick(async (value) => {
|
||||
this._rbg.onLinkClick(async (value) => {
|
||||
|
||||
//check which card is being selected, and open correct dialog based on link
|
||||
console.log(value);
|
||||
let dialog = new AssessmentResultsDialog('ownerUri', this.migrationStateModel, 'Assessment Dialog');
|
||||
let dialog = new AssessmentResultsDialog('ownerUri', this.migrationStateModel, 'Assessment Dialog', this);
|
||||
await dialog.openDialog();
|
||||
});
|
||||
|
||||
this._chooseTargetComponent?.component.addItem(rbg.component());
|
||||
this._rbg.onSelectionChanged((value) => {
|
||||
if (value.cardId === 'AzureSQLVM') {
|
||||
vscode.window.showInformationMessage('Feature coming soon');
|
||||
this._rbg.selectedCardId = 'AzureSQLMI';
|
||||
}
|
||||
});
|
||||
|
||||
this._rbg.selectedCardId = 'AzureSQLMI';
|
||||
|
||||
this._chooseTargetComponent?.component.addItem(this._rbg);
|
||||
}
|
||||
|
||||
private createAzureSubscriptionText(view: azdata.ModelView): azdata.FormComponent<azdata.TextComponent> {
|
||||
@@ -205,85 +230,78 @@ export class SKURecommendationPage extends MigrationWizardPage {
|
||||
}
|
||||
|
||||
private async populateSubscriptionDropdown(): Promise<void> {
|
||||
this._managedInstanceSubscriptionDropdown.loading = true;
|
||||
this._managedInstanceDropdown.loading = true;
|
||||
let subscriptions: azureResource.AzureResourceSubscription[] = [];
|
||||
try {
|
||||
subscriptions = await getSubscriptions(this.migrationStateModel._azureAccount);
|
||||
subscriptions.forEach((subscription) => {
|
||||
this._subscriptionMap.set(subscription.id, subscription);
|
||||
this._subscriptionDropdownValues.push({
|
||||
name: subscription.id,
|
||||
displayName: subscription.name + ' - ' + subscription.id,
|
||||
});
|
||||
});
|
||||
|
||||
if (!this._subscriptionDropdownValues || this._subscriptionDropdownValues.length === 0) {
|
||||
this._subscriptionDropdownValues = [
|
||||
{
|
||||
displayName: constants.NO_SUBSCRIPTIONS_FOUND,
|
||||
name: ''
|
||||
}
|
||||
];
|
||||
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;
|
||||
}
|
||||
|
||||
this._managedInstanceSubscriptionDropdown.values = this._subscriptionDropdownValues;
|
||||
} catch (error) {
|
||||
this.setEmptyDropdownPlaceHolder(this._managedInstanceSubscriptionDropdown, constants.NO_SUBSCRIPTIONS_FOUND);
|
||||
this._managedInstanceDropdown.loading = false;
|
||||
}
|
||||
this.populateManagedInstanceDropdown();
|
||||
this._managedInstanceSubscriptionDropdown.loading = false;
|
||||
}
|
||||
|
||||
private async populateManagedInstanceDropdown(): Promise<void> {
|
||||
this._managedInstanceDropdown.loading = true;
|
||||
let mis: SqlManagedInstance[] = [];
|
||||
let miValues: azdata.CategoryValue[] = [];
|
||||
try {
|
||||
const subscriptionId = (<azdata.CategoryValue>this._managedInstanceSubscriptionDropdown.value).name;
|
||||
|
||||
mis = await getAvailableManagedInstanceProducts(this.migrationStateModel._azureAccount, this._subscriptionMap.get(subscriptionId)!);
|
||||
mis.forEach((mi) => {
|
||||
miValues.push({
|
||||
name: mi.name,
|
||||
displayName: mi.name
|
||||
});
|
||||
});
|
||||
|
||||
if (!miValues || miValues.length === 0) {
|
||||
miValues = [
|
||||
{
|
||||
displayName: constants.NO_MANAGED_INSTANCE_FOUND,
|
||||
name: ''
|
||||
}
|
||||
];
|
||||
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;
|
||||
}
|
||||
|
||||
this._managedInstanceDropdown.values = miValues;
|
||||
} catch (error) {
|
||||
this.setEmptyDropdownPlaceHolder(this._managedInstanceDropdown, constants.NO_MANAGED_INSTANCE_FOUND);
|
||||
}
|
||||
|
||||
this._managedInstanceDropdown.loading = false;
|
||||
}
|
||||
|
||||
private setEmptyDropdownPlaceHolder(dropDown: azdata.DropDownComponent, placeholder: string): void {
|
||||
dropDown.values = [{
|
||||
displayName: placeholder,
|
||||
name: ''
|
||||
}];
|
||||
}
|
||||
|
||||
private eventListener: Disposable | undefined;
|
||||
private eventListener: vscode.Disposable | undefined;
|
||||
public async onPageEnter(): Promise<void> {
|
||||
this.eventListener = this.migrationStateModel.stateChangeEvent(async (e) => this.onStateChangeEvent(e));
|
||||
this.populateSubscriptionDropdown();
|
||||
this.constructDetails();
|
||||
|
||||
this.wizard.registerNavigationValidator((pageChangeInfo) => {
|
||||
const errors: string[] = [];
|
||||
this.wizard.message = {
|
||||
text: '',
|
||||
level: azdata.window.MessageLevel.Error
|
||||
};
|
||||
if (pageChangeInfo.newPage < pageChangeInfo.lastPage) {
|
||||
return true;
|
||||
}
|
||||
if (this.migrationStateModel._migrationDbs.length === 0) {
|
||||
errors.push('Please select databases to migrate');
|
||||
|
||||
}
|
||||
if ((<azdata.CategoryValue>this._managedInstanceSubscriptionDropdown.value).displayName === constants.NO_SUBSCRIPTIONS_FOUND) {
|
||||
errors.push(constants.INVALID_SUBSCRIPTION_ERROR);
|
||||
}
|
||||
if ((<azdata.CategoryValue>this._managedInstanceDropdown.value).displayName === constants.NO_MANAGED_INSTANCE_FOUND) {
|
||||
errors.push(constants.INVALID_STORAGE_ACCOUNT_ERROR);
|
||||
}
|
||||
|
||||
if (errors.length > 0) {
|
||||
this.wizard.message = {
|
||||
text: errors.join(EOL),
|
||||
level: azdata.window.MessageLevel.Error
|
||||
};
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
public async onPageLeave(): Promise<void> {
|
||||
this.eventListener?.dispose();
|
||||
this.wizard.message = {
|
||||
text: '',
|
||||
level: azdata.window.MessageLevel.Error
|
||||
};
|
||||
this.wizard.registerNavigationValidator((pageChangeInfo) => {
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
protected async handleStateChange(e: StateChangeEvent): Promise<void> {
|
||||
@@ -292,4 +310,16 @@ export class SKURecommendationPage extends MigrationWizardPage {
|
||||
}
|
||||
}
|
||||
|
||||
public refreshDatabaseCount(count: number): 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.updateProperties({
|
||||
cards: this._rbg.cards
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user