mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-02-09 01:32:34 -05:00
SQL VM deployments (#12144)
* Added sql vm deployment option * Added more fields for sql vm deployments * created basic sqlvm deployment. Mostly hardcoded * added string to package.nls * added poc deployments for sql vm * Made some changes in the notebook that was mentioned in PR * Added scaffolding for azure sql vm wizard. * code cleanups * added some async logic * added loading component * fixed loader code * completed page2 of wizard * added some more required fields. * added some more fields * added network settings page * added sql server settings page * added azure signin support and sql server settings page * added some helper methods in wizard code * added some fixes * fixed azure and vm setting page added validation in azure setting page * added changes for the notebook variable * validations and other bug fixes * commenting sql storage optimization dropdown * cleanedup wizard base page * reversing vm image list to display newer images first * cleaning model code * added validations for network setting * Completed summary page fixed the code poisition some additional field validations * fixed networking page * - fixed an error with vm size model variable - removed byol images because it was not working with az sql vm - Fixed vm size display names in dropdown * added double quotes to some localized strings * added some space inside strings * -Added live validations -Restyled network component -Added required to regions -Some bug fixes * -redesigned summary page -localized some strings * Fixed summary page section titles * -Fixed validations on sql server settings page -Fixed some fields on Summary Page * corrected onleave validation using array for error messages using Promises.all * Fixed bug on network settings dropdowns when user does not have existing resource to populate them * Change resource deployment display name Added Ninar's iteration of the notebook Changed RDP check box label Surfacing API errors to user Filtering regions based on Azure VM regions and user's subscription region Made form validation async Displaying new checkbox on network page when dropdowns empty Fixed a small bug in SQL auth form validation Made summary single item per row and fixed the gaps in spacing Fixed validations in vm page Checking if vm name already exists on azure * Fixed sql vm eula Fixed sql vm description Added hyperlink for more info on vm sizes * Replaced loading component with dropdown loaders. * localized string Fixed a bug in network settings page * Added additonal filtering * added reverse to image images * Fixing some merge related issues
This commit is contained in:
@@ -0,0 +1,302 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* 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 constants from '../constants';
|
||||
import { WizardPageBase } from '../../wizardPageBase';
|
||||
import { DeployAzureSQLVMWizard } from '../deployAzureSQLVMWizard';
|
||||
import { apiService } from '../../../services/apiService';
|
||||
import { azureResource } from 'azureResource';
|
||||
import * as vscode from 'vscode';
|
||||
|
||||
export class AzureSettingsPage extends WizardPageBase<DeployAzureSQLVMWizard> {
|
||||
// <- means depends on
|
||||
//dropdown for azure accounts
|
||||
private _azureAccountsDropdown!: azdata.DropDownComponent;
|
||||
private signInButton!: azdata.ButtonComponent;
|
||||
private refreshButton!: azdata.ButtonComponent;
|
||||
|
||||
private buttonFlexContainer!: azdata.FlexContainer;
|
||||
|
||||
//dropdown for subscription accounts <- azure account dropdown
|
||||
private _azureSubscriptionsDropdown!: azdata.DropDownComponent;
|
||||
|
||||
//dropdown for resource groups <- subscription dropdown
|
||||
private _resourceGroupDropdown!: azdata.DropDownComponent;
|
||||
|
||||
//dropdown for azure regions <- subscription dropdown
|
||||
private _azureRegionsDropdown!: azdata.DropDownComponent;
|
||||
|
||||
private _form!: azdata.FormContainer;
|
||||
|
||||
private _accountsMap!: Map<string, azdata.Account>;
|
||||
private _subscriptionsMap!: Map<string, azureResource.AzureResourceSubscription>;
|
||||
constructor(wizard: DeployAzureSQLVMWizard) {
|
||||
super(
|
||||
constants.AzureSettingsPageTitle,
|
||||
'',
|
||||
wizard
|
||||
);
|
||||
this._accountsMap = new Map();
|
||||
this._subscriptionsMap = new Map();
|
||||
}
|
||||
|
||||
public async initialize() {
|
||||
this.pageObject.registerContent(async (view: azdata.ModelView) => {
|
||||
|
||||
await Promise.all([
|
||||
this.createAzureAccountsDropdown(view),
|
||||
this.createAzureSubscriptionsDropdown(view),
|
||||
this.createResourceDropdown(view),
|
||||
this.createAzureRegionsDropdown(view)
|
||||
]);
|
||||
this.populateAzureAccountsDropdown();
|
||||
|
||||
this._form = view.modelBuilder.formContainer()
|
||||
.withFormItems(
|
||||
[
|
||||
{
|
||||
component: this.wizard.createFormRowComponent(view, constants.AzureAccountDropdownLabel, '', this._azureAccountsDropdown, true)
|
||||
},
|
||||
{
|
||||
component: this.buttonFlexContainer
|
||||
},
|
||||
{
|
||||
component: this.wizard.createFormRowComponent(view, constants.AzureAccountSubscriptionDropdownLabel, '', this._azureSubscriptionsDropdown, true)
|
||||
},
|
||||
{
|
||||
component: this.wizard.createFormRowComponent(view, constants.AzureAccountResourceGroupDropdownLabel, '', this._resourceGroupDropdown, true)
|
||||
},
|
||||
{
|
||||
component: this.wizard.createFormRowComponent(view, constants.AzureAccountRegionDropdownLabel, '', this._azureRegionsDropdown, true)
|
||||
}
|
||||
],
|
||||
{
|
||||
horizontal: false,
|
||||
componentWidth: '100%'
|
||||
})
|
||||
.withLayout({ width: '100%' })
|
||||
.component();
|
||||
return view.initializeModel(this._form);
|
||||
});
|
||||
}
|
||||
|
||||
public async onEnter(): Promise<void> {
|
||||
this.wizard.wizardObject.registerNavigationValidator((pcInfo) => {
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
public async onLeave(): Promise<void> {
|
||||
this.wizard.wizardObject.registerNavigationValidator((pcInfo) => {
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
private async createAzureAccountsDropdown(view: azdata.ModelView) {
|
||||
|
||||
this._azureAccountsDropdown = view.modelBuilder.dropDown().withProperties({}).component();
|
||||
|
||||
this._azureAccountsDropdown.onValueChanged(async (value) => {
|
||||
this.wizard.model.azureAccount = this._accountsMap.get(value.selected)!;
|
||||
this.populateAzureSubscriptionsDropdown();
|
||||
});
|
||||
|
||||
this.signInButton = view.modelBuilder.button().withProperties<azdata.ButtonProperties>({
|
||||
label: 'Sign In',
|
||||
width: '100px'
|
||||
}).component();
|
||||
this.refreshButton = view.modelBuilder.button().withProperties<azdata.ButtonProperties>({
|
||||
label: 'Refresh',
|
||||
width: '100px'
|
||||
}).component();
|
||||
|
||||
this.signInButton.onDidClick(async (event) => {
|
||||
await vscode.commands.executeCommand('workbench.actions.modal.linkedAccount');
|
||||
await this.populateAzureAccountsDropdown();
|
||||
});
|
||||
this.refreshButton.onDidClick(async (event) => {
|
||||
await this.populateAzureAccountsDropdown();
|
||||
});
|
||||
this.buttonFlexContainer = view.modelBuilder.flexContainer().withLayout({
|
||||
flexFlow: 'row'
|
||||
}).withItems([this.signInButton, this.refreshButton], { CSSStyles: { 'margin-right': '5px', } }).component();
|
||||
|
||||
}
|
||||
|
||||
private async populateAzureAccountsDropdown() {
|
||||
this._azureAccountsDropdown.loading = true;
|
||||
let accounts = await azdata.accounts.getAllAccounts();
|
||||
|
||||
if (accounts.length === 0) {
|
||||
this.wizard.showErrorMessage('Sign in to an Azure account first');
|
||||
return;
|
||||
} else {
|
||||
this.wizard.showErrorMessage('');
|
||||
}
|
||||
|
||||
this.wizard.addDropdownValues(
|
||||
this._azureAccountsDropdown,
|
||||
accounts.map((account): azdata.CategoryValue => {
|
||||
let accountCategoryValue = {
|
||||
displayName: account.displayInfo.displayName,
|
||||
name: account.displayInfo.displayName
|
||||
};
|
||||
this._accountsMap.set(accountCategoryValue.displayName, account);
|
||||
return accountCategoryValue;
|
||||
}),
|
||||
);
|
||||
|
||||
this.wizard.model.azureAccount = accounts[0];
|
||||
this._azureAccountsDropdown.loading = false;
|
||||
|
||||
await this.populateAzureSubscriptionsDropdown();
|
||||
}
|
||||
|
||||
private async createAzureSubscriptionsDropdown(view: azdata.ModelView) {
|
||||
this._azureSubscriptionsDropdown = view.modelBuilder.dropDown().withProperties({}).component();
|
||||
|
||||
this._azureSubscriptionsDropdown.onValueChanged(async (value) => {
|
||||
|
||||
let currentSubscriptionValue = this._azureSubscriptionsDropdown.value as azdata.CategoryValue;
|
||||
this.wizard.model.azureSubscription = currentSubscriptionValue.name;
|
||||
this.wizard.model.azureSubscriptionDisplayName = currentSubscriptionValue.displayName;
|
||||
|
||||
this.wizard.model.securityToken = await azdata.accounts.getAccountSecurityToken(
|
||||
this.wizard.model.azureAccount,
|
||||
this._subscriptionsMap.get(currentSubscriptionValue.name)?.tenant!,
|
||||
azdata.AzureResource.ResourceManagement
|
||||
);
|
||||
|
||||
this.populateResourceGroupDropdown();
|
||||
this.populateAzureRegionsDropdown();
|
||||
});
|
||||
}
|
||||
|
||||
private async populateAzureSubscriptionsDropdown() {
|
||||
this._azureSubscriptionsDropdown.loading = true;
|
||||
let subService = await apiService.azurecoreApi;
|
||||
let currentAccountDropdownValue = (this._azureAccountsDropdown.value as azdata.CategoryValue);
|
||||
if (currentAccountDropdownValue === undefined) {
|
||||
this._azureSubscriptionsDropdown.loading = false;
|
||||
await this.populateResourceGroupDropdown();
|
||||
await this.populateAzureRegionsDropdown();
|
||||
return;
|
||||
}
|
||||
let currentAccount = this._accountsMap.get(currentAccountDropdownValue.name);
|
||||
let subscriptions = (await subService.getSubscriptions(currentAccount, true)).subscriptions;
|
||||
if (subscriptions === undefined || subscriptions.length === 0) {
|
||||
this._azureSubscriptionsDropdown.updateProperties({
|
||||
values: []
|
||||
});
|
||||
this._azureSubscriptionsDropdown.loading = false;
|
||||
await this.populateResourceGroupDropdown();
|
||||
await this.populateAzureRegionsDropdown();
|
||||
return;
|
||||
}
|
||||
subscriptions.sort((a: any, b: any) => a.name.toLocaleLowerCase().localeCompare(b.name.toLocaleLowerCase()));
|
||||
|
||||
this.wizard.addDropdownValues(
|
||||
this._azureSubscriptionsDropdown,
|
||||
subscriptions.map((subscription: any): azdata.CategoryValue => {
|
||||
let subscriptionCategoryValue = {
|
||||
displayName: subscription.name + ' - ' + subscription.id,
|
||||
name: subscription.id
|
||||
};
|
||||
this._subscriptionsMap.set(subscriptionCategoryValue.name, subscription);
|
||||
return subscriptionCategoryValue;
|
||||
})
|
||||
);
|
||||
|
||||
this.wizard.model.azureSubscription = (this._azureSubscriptionsDropdown.value as azdata.CategoryValue).name;
|
||||
this.wizard.model.azureSubscriptionDisplayName = (this._azureSubscriptionsDropdown.value as azdata.CategoryValue).displayName;
|
||||
|
||||
this.wizard.model.securityToken = await azdata.accounts.getAccountSecurityToken(
|
||||
this.wizard.model.azureAccount,
|
||||
this._subscriptionsMap.get((this._azureSubscriptionsDropdown.value as azdata.CategoryValue).name)?.tenant!,
|
||||
azdata.AzureResource.ResourceManagement
|
||||
);
|
||||
this._azureSubscriptionsDropdown.loading = false;
|
||||
await this.populateResourceGroupDropdown();
|
||||
await this.populateAzureRegionsDropdown();
|
||||
}
|
||||
|
||||
private async createResourceDropdown(view: azdata.ModelView) {
|
||||
this._resourceGroupDropdown = view.modelBuilder.dropDown().withProperties({
|
||||
required: true
|
||||
}).component();
|
||||
this._resourceGroupDropdown.onValueChanged(async (value) => {
|
||||
this.wizard.model.azureResouceGroup = value.selected;
|
||||
});
|
||||
}
|
||||
|
||||
private async populateResourceGroupDropdown() {
|
||||
this._resourceGroupDropdown.loading = true;
|
||||
let subService = await apiService.azurecoreApi;
|
||||
let currentSubscriptionValue = this._azureSubscriptionsDropdown.value as azdata.CategoryValue;
|
||||
if (currentSubscriptionValue === undefined || currentSubscriptionValue.displayName === '') {
|
||||
|
||||
this._resourceGroupDropdown.updateProperties({
|
||||
values: []
|
||||
});
|
||||
this._resourceGroupDropdown.loading = false;
|
||||
return;
|
||||
}
|
||||
let currentSubscription = this._subscriptionsMap.get(currentSubscriptionValue.name);
|
||||
let resourceGroups = (await subService.getResourceGroups(this.wizard.model.azureAccount, currentSubscription, true)).resourceGroups;
|
||||
if (resourceGroups === undefined || resourceGroups.length === 0) {
|
||||
this._resourceGroupDropdown.loading = false;
|
||||
this._resourceGroupDropdown.updateProperties({
|
||||
values: []
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
resourceGroups.sort((a: any, b: any) => a.name.toLocaleLowerCase().localeCompare(b.name.toLocaleLowerCase()));
|
||||
this._resourceGroupDropdown.updateProperties({
|
||||
values: resourceGroups.map((resourceGroup: any) => {
|
||||
return {
|
||||
displayName: resourceGroup.name,
|
||||
name: resourceGroup.name
|
||||
};
|
||||
})
|
||||
});
|
||||
this.wizard.model.azureResouceGroup = (this._resourceGroupDropdown.value as azdata.CategoryValue).name;
|
||||
this._resourceGroupDropdown.loading = false;
|
||||
}
|
||||
|
||||
private async createAzureRegionsDropdown(view: azdata.ModelView) {
|
||||
this._azureRegionsDropdown = view.modelBuilder.dropDown().withProperties({
|
||||
required: true
|
||||
}).component();
|
||||
|
||||
this._azureRegionsDropdown.onValueChanged((value) => {
|
||||
this.wizard.model.azureRegion = (this._azureRegionsDropdown.value as azdata.CategoryValue).name;
|
||||
});
|
||||
}
|
||||
|
||||
private async populateAzureRegionsDropdown() {
|
||||
this._azureRegionsDropdown.loading = true;
|
||||
|
||||
let supportedRegions = 'eastus, eastus2, westus, centralus, northcentralus, southcentralus, northeurope, westeurope, eastasia, southeastasia, japaneast, japanwest, australiaeast, australiasoutheast, australiacentral, brazilsouth, southindia, centralindia, westindia, canadacentral, canadaeast, westus2, westcentralus, uksouth, ukwest, koreacentral, koreasouth, francecentral, southafricanorth, uaenorth, switzerlandnorth, germanywestcentral, norwayeast';
|
||||
let supportedRegionsArray = supportedRegions.split(', ');
|
||||
let url = `https://management.azure.com/subscriptions/${this.wizard.model.azureSubscription}/locations?api-version=2020-01-01`;
|
||||
const response = await this.wizard.getRequest(url, false);
|
||||
response.data.value = response.data.value.sort((a: any, b: any) => (a.displayName > b.displayName) ? 1 : -1);
|
||||
this.wizard.addDropdownValues(
|
||||
this._azureRegionsDropdown,
|
||||
response.data.value.filter((value: any) => {
|
||||
return supportedRegionsArray.includes(value.name);
|
||||
}).map((value: any) => {
|
||||
return {
|
||||
displayName: value.displayName,
|
||||
name: value.name
|
||||
};
|
||||
})
|
||||
);
|
||||
this.wizard.model.azureRegion = (this._azureRegionsDropdown.value as azdata.CategoryValue).name;
|
||||
this._azureRegionsDropdown.loading = false;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user