mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-02-17 02:51:36 -05:00
Adding Azure AD tenant dropdown in migration wizard (#14637)
* Added dropdown to select azure tenant in accounts page * Added dropdown label for tenant dropdown * Moving deepcopy to utils Exporting tenant type from azurecore * Removing unnecessary stylings * removing unnecessary async
This commit is contained in:
23
extensions/sql-migration/src/api/utils.ts
Normal file
23
extensions/sql-migration/src/api/utils.ts
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
/*---------------------------------------------------------------------------------------------
|
||||||
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||||
|
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||||
|
*--------------------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
export function deepClone<T>(obj: T): T {
|
||||||
|
if (!obj || typeof obj !== 'object') {
|
||||||
|
return obj;
|
||||||
|
}
|
||||||
|
if (obj instanceof RegExp) {
|
||||||
|
// See https://github.com/Microsoft/TypeScript/issues/10990
|
||||||
|
return obj as any;
|
||||||
|
}
|
||||||
|
const result: any = Array.isArray(obj) ? [] : {};
|
||||||
|
Object.keys(<any>obj).forEach((key: string) => {
|
||||||
|
if ((<any>obj)[key] && typeof (<any>obj)[key] === 'object') {
|
||||||
|
result[key] = deepClone((<any>obj)[key]);
|
||||||
|
} else {
|
||||||
|
result[key] = (<any>obj)[key];
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return result;
|
||||||
|
}
|
||||||
@@ -46,6 +46,7 @@ export const ACCOUNT_LINK_BUTTON_LABEL = localize('sql.migration.wizard.account.
|
|||||||
export function accountLinkedMessage(count: number): string {
|
export function accountLinkedMessage(count: number): string {
|
||||||
return count === 1 ? localize('sql.migration.wizard.account.count.single.message', '{0} account linked', count) : localize('sql.migration.wizard.account.count.multiple.message', '{0} accounts linked', count);
|
return count === 1 ? localize('sql.migration.wizard.account.count.single.message', '{0} account linked', count) : localize('sql.migration.wizard.account.count.multiple.message', '{0} accounts linked', count);
|
||||||
}
|
}
|
||||||
|
export const AZURE_TENANT = localize('sql.migration.azure.tenant', "Azure AD tenant");
|
||||||
|
|
||||||
|
|
||||||
// database backup page
|
// database backup page
|
||||||
|
|||||||
@@ -5,6 +5,7 @@
|
|||||||
|
|
||||||
import * as azdata from 'azdata';
|
import * as azdata from 'azdata';
|
||||||
import { azureResource } from 'azureResource';
|
import { azureResource } from 'azureResource';
|
||||||
|
import * as azurecore from 'azurecore';
|
||||||
import * as vscode from 'vscode';
|
import * as vscode from 'vscode';
|
||||||
import * as mssql from '../../../mssql';
|
import * as mssql from '../../../mssql';
|
||||||
import { getAvailableManagedInstanceProducts, getAvailableStorageAccounts, getBlobContainers, getFileShares, getMigrationControllers, getSubscriptions, SqlMigrationController, SqlManagedInstance, startDatabaseMigration, StartDatabaseMigrationRequest, StorageAccount, getAvailableSqlVMs, SqlVMServer } from '../api/azure';
|
import { getAvailableManagedInstanceProducts, getAvailableStorageAccounts, getBlobContainers, getFileShares, getMigrationControllers, getSubscriptions, SqlMigrationController, SqlManagedInstance, startDatabaseMigration, StartDatabaseMigrationRequest, StorageAccount, getAvailableSqlVMs, SqlVMServer } from '../api/azure';
|
||||||
@@ -79,6 +80,7 @@ export interface StateChangeEvent {
|
|||||||
export class MigrationStateModel implements Model, vscode.Disposable {
|
export class MigrationStateModel implements Model, vscode.Disposable {
|
||||||
public _azureAccounts!: azdata.Account[];
|
public _azureAccounts!: azdata.Account[];
|
||||||
public _azureAccount!: azdata.Account;
|
public _azureAccount!: azdata.Account;
|
||||||
|
public _accountTenants!: azurecore.Tenant[];
|
||||||
|
|
||||||
public _subscriptions!: azureResource.AzureResourceSubscription[];
|
public _subscriptions!: azureResource.AzureResourceSubscription[];
|
||||||
|
|
||||||
@@ -197,6 +199,19 @@ export class MigrationStateModel implements Model, vscode.Disposable {
|
|||||||
return this._azureAccounts[index];
|
return this._azureAccounts[index];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public getTenantValues(): azdata.CategoryValue[] {
|
||||||
|
return this._accountTenants.map(tenant => {
|
||||||
|
return {
|
||||||
|
displayName: tenant.displayName,
|
||||||
|
name: tenant.id
|
||||||
|
};
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public getTenant(index: number): azurecore.Tenant {
|
||||||
|
return this._accountTenants[index];
|
||||||
|
}
|
||||||
|
|
||||||
public async getSubscriptionsDropdownValues(): Promise<azdata.CategoryValue[]> {
|
public async getSubscriptionsDropdownValues(): Promise<azdata.CategoryValue[]> {
|
||||||
let subscriptionsValues: azdata.CategoryValue[] = [];
|
let subscriptionsValues: azdata.CategoryValue[] = [];
|
||||||
try {
|
try {
|
||||||
|
|||||||
@@ -9,9 +9,12 @@ import { MigrationWizardPage } from '../models/migrationWizardPage';
|
|||||||
import { MigrationStateModel, StateChangeEvent } from '../models/stateMachine';
|
import { MigrationStateModel, StateChangeEvent } from '../models/stateMachine';
|
||||||
import * as constants from '../constants/strings';
|
import * as constants from '../constants/strings';
|
||||||
import { WIZARD_INPUT_COMPONENT_WIDTH } from './wizardController';
|
import { WIZARD_INPUT_COMPONENT_WIDTH } from './wizardController';
|
||||||
|
import { deepClone } from '../api/utils';
|
||||||
|
|
||||||
export class AccountsSelectionPage extends MigrationWizardPage {
|
export class AccountsSelectionPage extends MigrationWizardPage {
|
||||||
private _azureAccountsDropdown!: azdata.DropDownComponent;
|
private _azureAccountsDropdown!: azdata.DropDownComponent;
|
||||||
|
private _accountTenantDropdown!: azdata.DropDownComponent;
|
||||||
|
private _accountTenantFlexContainer!: azdata.FlexContainer;
|
||||||
|
|
||||||
constructor(wizard: azdata.window.Wizard, migrationStateModel: MigrationStateModel) {
|
constructor(wizard: azdata.window.Wizard, migrationStateModel: MigrationStateModel) {
|
||||||
super(wizard, azdata.window.createWizardPage(constants.ACCOUNTS_SELECTION_PAGE_TITLE), migrationStateModel);
|
super(wizard, azdata.window.createWizardPage(constants.ACCOUNTS_SELECTION_PAGE_TITLE), migrationStateModel);
|
||||||
@@ -22,7 +25,8 @@ export class AccountsSelectionPage extends MigrationWizardPage {
|
|||||||
const form = view.modelBuilder.formContainer()
|
const form = view.modelBuilder.formContainer()
|
||||||
.withFormItems(
|
.withFormItems(
|
||||||
[
|
[
|
||||||
await this.createAzureAccountsDropdown(view)
|
await this.createAzureAccountsDropdown(view),
|
||||||
|
await this.createAzureTenantContainer(view),
|
||||||
]
|
]
|
||||||
);
|
);
|
||||||
await view.initializeModel(form.component());
|
await view.initializeModel(form.component());
|
||||||
@@ -48,10 +52,24 @@ export class AccountsSelectionPage extends MigrationWizardPage {
|
|||||||
|
|
||||||
this._azureAccountsDropdown.onValueChanged(async (value) => {
|
this._azureAccountsDropdown.onValueChanged(async (value) => {
|
||||||
if (value.selected) {
|
if (value.selected) {
|
||||||
this.migrationStateModel._azureAccount = this.migrationStateModel.getAccount(value.index);
|
const selectedAzureAccount = this.migrationStateModel.getAccount(value.index);
|
||||||
|
// Making a clone of the account object to preserve the original tenants
|
||||||
|
this.migrationStateModel._azureAccount = deepClone(selectedAzureAccount);
|
||||||
|
if (this.migrationStateModel._azureAccount.properties.tenants.length > 1) {
|
||||||
|
this.migrationStateModel._accountTenants = selectedAzureAccount.properties.tenants;
|
||||||
|
this._accountTenantDropdown.values = await this.migrationStateModel.getTenantValues();
|
||||||
|
this._accountTenantFlexContainer.updateCssStyles({
|
||||||
|
'display': 'inline'
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
this._accountTenantFlexContainer.updateCssStyles({
|
||||||
|
'display': 'none'
|
||||||
|
});
|
||||||
|
}
|
||||||
this.migrationStateModel._subscriptions = undefined!;
|
this.migrationStateModel._subscriptions = undefined!;
|
||||||
this.migrationStateModel._targetSubscription = undefined!;
|
this.migrationStateModel._targetSubscription = undefined!;
|
||||||
this.migrationStateModel._databaseBackup.subscription = undefined!;
|
this.migrationStateModel._databaseBackup.subscription = undefined!;
|
||||||
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -71,7 +89,7 @@ export class AccountsSelectionPage extends MigrationWizardPage {
|
|||||||
.withLayout({
|
.withLayout({
|
||||||
flexFlow: 'column'
|
flexFlow: 'column'
|
||||||
})
|
})
|
||||||
.withItems([this._azureAccountsDropdown, linkAccountButton], { CSSStyles: { 'margin': '2px', } })
|
.withItems([this._azureAccountsDropdown, linkAccountButton])
|
||||||
.component();
|
.component();
|
||||||
|
|
||||||
return {
|
return {
|
||||||
@@ -80,6 +98,50 @@ export class AccountsSelectionPage extends MigrationWizardPage {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private createAzureTenantContainer(view: azdata.ModelView): azdata.FormComponent {
|
||||||
|
|
||||||
|
const azureTenantDropdownLabel = view.modelBuilder.text().withProps({
|
||||||
|
value: constants.AZURE_TENANT,
|
||||||
|
CSSStyles: {
|
||||||
|
'margin': '0px'
|
||||||
|
}
|
||||||
|
}).component();
|
||||||
|
|
||||||
|
this._accountTenantDropdown = view.modelBuilder.dropDown().withProps({
|
||||||
|
width: WIZARD_INPUT_COMPONENT_WIDTH
|
||||||
|
}).component();
|
||||||
|
|
||||||
|
this._accountTenantDropdown.onValueChanged(value => {
|
||||||
|
/**
|
||||||
|
* Replacing all the tenants in azure account with the tenant user has selected.
|
||||||
|
* All azure requests will only run on this tenant from now on
|
||||||
|
*/
|
||||||
|
if (value.selected) {
|
||||||
|
this.migrationStateModel._azureAccount.properties.tenants = [this.migrationStateModel.getTenant(value.index)];
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
this._accountTenantFlexContainer = view.modelBuilder.flexContainer()
|
||||||
|
.withLayout({
|
||||||
|
flexFlow: 'column'
|
||||||
|
})
|
||||||
|
.withItems([
|
||||||
|
azureTenantDropdownLabel,
|
||||||
|
this._accountTenantDropdown
|
||||||
|
])
|
||||||
|
.withProps({
|
||||||
|
CSSStyles: {
|
||||||
|
'display': 'none'
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.component();
|
||||||
|
|
||||||
|
return {
|
||||||
|
title: '',
|
||||||
|
component: this._accountTenantFlexContainer
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
private async populateAzureAccountsDropdown(): Promise<void> {
|
private async populateAzureAccountsDropdown(): Promise<void> {
|
||||||
this._azureAccountsDropdown.loading = true;
|
this._azureAccountsDropdown.loading = true;
|
||||||
try {
|
try {
|
||||||
|
|||||||
Reference in New Issue
Block a user