mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-02-16 18:46:40 -05:00
sql db deployments into main (WIP) (#12767)
* added my resource-deployment * changed notebook message * Add more advanced properties for spark job submission dialog (#12732) * Add more advanced properties for spark job submission dialog * Add queue * Revert "Add more advanced properties for spark job submission dialog (#12732)" This reverts commit e6a7e86ddbe70b39660098a8ebd9ded2a1c5530c. * Changes made for simplification * changed error messages * tags added * tags removed due to redundancy * Update package.json * Update resourceTypePickerDialog.ts * changes based on feedback * activaterealtimevalidation removed Co-authored-by: Charles Gagnon <chgagnon@microsoft.com>
This commit is contained in:
@@ -0,0 +1,211 @@
|
|||||||
|
{
|
||||||
|
"metadata": {
|
||||||
|
"kernelspec": {
|
||||||
|
"name": "python3",
|
||||||
|
"display_name": "Python 3"
|
||||||
|
},
|
||||||
|
"language_info": {
|
||||||
|
"name": "python",
|
||||||
|
"version": "3.6.6",
|
||||||
|
"mimetype": "text/x-python",
|
||||||
|
"codemirror_mode": {
|
||||||
|
"name": "ipython",
|
||||||
|
"version": 3
|
||||||
|
},
|
||||||
|
"pygments_lexer": "ipython3",
|
||||||
|
"nbconvert_exporter": "python",
|
||||||
|
"file_extension": ".py"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"nbformat_minor": 2,
|
||||||
|
"nbformat": 4,
|
||||||
|
"cells": [
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"source": [
|
||||||
|
"Create Azure SQL Database\n",
|
||||||
|
"============================================\n",
|
||||||
|
"\n",
|
||||||
|
"Steps of this procedure include:\n",
|
||||||
|
"1. Set variables and set up Notebook\n",
|
||||||
|
"1. Connect to Azure account and subscription\n",
|
||||||
|
"1. Provision firewall rules to allow local access\n",
|
||||||
|
"1. Create SQL database resource"
|
||||||
|
],
|
||||||
|
"metadata": {
|
||||||
|
"azdata_cell_guid": "6af59d69-ade7-480a-b33e-52a86fe5bfd3"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"source": [
|
||||||
|
"## Set variables\r\n",
|
||||||
|
"These variables are set based on your inputs in the deployment wizard. You can make changes to these variables but be aware of possible validation errors caused by your changes.\r\n",
|
||||||
|
"\r\n",
|
||||||
|
"\r\n",
|
||||||
|
"\r\n",
|
||||||
|
"\r\n",
|
||||||
|
""
|
||||||
|
],
|
||||||
|
"metadata": {
|
||||||
|
"azdata_cell_guid": "b57c46c8-4a34-49af-9b62-aa5688a02002"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"source": [
|
||||||
|
"## Notebook Setup "
|
||||||
|
],
|
||||||
|
"metadata": {
|
||||||
|
"azdata_cell_guid": "19ebf0fd-7010-4cd6-8bcd-d2f63dc75cfb"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"source": [
|
||||||
|
"import sys, os, json, time, string, random, subprocess\r\n",
|
||||||
|
"def run_command(command, json_decode = True, printOutput = True):\n",
|
||||||
|
" print(command)\n",
|
||||||
|
" process = subprocess.Popen(command.split(), stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True)\n",
|
||||||
|
" output, error = process.communicate()\n",
|
||||||
|
" if process.returncode != 0: \n",
|
||||||
|
" print(\"Process failed %d \\n%s\" % (process.returncode, error.decode(\"utf-8\")))\n",
|
||||||
|
" raise Exception()\n",
|
||||||
|
" if output:\n",
|
||||||
|
" output = output.decode(\"utf-8\")\n",
|
||||||
|
" if printOutput:\n",
|
||||||
|
" print(output)\n",
|
||||||
|
" try:\n",
|
||||||
|
" return json.loads(output)\n",
|
||||||
|
" except:\n",
|
||||||
|
" return output\r\n",
|
||||||
|
],
|
||||||
|
"metadata": {
|
||||||
|
"azdata_cell_guid": "c320ffe2-c488-4bd8-9886-c7deeae02996",
|
||||||
|
"tags": []
|
||||||
|
},
|
||||||
|
"outputs": [],
|
||||||
|
"execution_count": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"source": [
|
||||||
|
"## Connecting to your Azure account\r\n",
|
||||||
|
""
|
||||||
|
],
|
||||||
|
"metadata": {
|
||||||
|
"azdata_cell_guid": "e34334a7-0d55-4c18-8c0a-1c4a673629cd"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"source": [
|
||||||
|
"subscriptions = run_command('az account list', printOutput = False)\r\n",
|
||||||
|
"if azure_sqldb_subscription not in (subscription[\"id\"] for subscription in subscriptions):\r\n",
|
||||||
|
" run_command('az login')"
|
||||||
|
],
|
||||||
|
"metadata": {
|
||||||
|
"azdata_cell_guid": "96800b54-48a8-463b-886c-3d0e96f29765"
|
||||||
|
},
|
||||||
|
"outputs": [],
|
||||||
|
"execution_count": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"source": [
|
||||||
|
"## Setting your Azure subscription\r\n",
|
||||||
|
""
|
||||||
|
],
|
||||||
|
"metadata": {
|
||||||
|
"azdata_cell_guid": "ed6b781d-ce7e-4b51-a7ec-1eeeb2032c73"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"source": [
|
||||||
|
"run_command(\r\n",
|
||||||
|
" 'az account set '\r\n",
|
||||||
|
" '--subscription {0}'\r\n",
|
||||||
|
" .format(\r\n",
|
||||||
|
" azure_sqldb_subscription));"
|
||||||
|
],
|
||||||
|
"metadata": {
|
||||||
|
"azdata_cell_guid": "17b57956-98cf-44de-9ab5-348469ddabf4"
|
||||||
|
},
|
||||||
|
"outputs": [],
|
||||||
|
"execution_count": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"source": [
|
||||||
|
"## Create a server firewall rule\r\n",
|
||||||
|
"\r\n",
|
||||||
|
"This firewall rule will allow you to access your server and database within IP range immediately after it is created."
|
||||||
|
],
|
||||||
|
"metadata": {
|
||||||
|
"azdata_cell_guid": "ba895abf-3176-48b5-9e49-a060b3f74370"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"source": [
|
||||||
|
"create_firewall_rule_result = run_command(\r\n",
|
||||||
|
" 'az sql server firewall-rule create '\r\n",
|
||||||
|
" '--start-ip-address {0} '\r\n",
|
||||||
|
" '--end-ip-address {1} '\r\n",
|
||||||
|
" '--server {2} '\r\n",
|
||||||
|
" '--name {3} '\r\n",
|
||||||
|
" '--resource-group {4} '\r\n",
|
||||||
|
" .format(\r\n",
|
||||||
|
" azure_sqldb_ip_start, \r\n",
|
||||||
|
" azure_sqldb_ip_end, \r\n",
|
||||||
|
" azure_sqldb_server_name, \r\n",
|
||||||
|
" azure_sqldb_firewall_name, \r\n",
|
||||||
|
" azure_sqldb_resource_group_name));"
|
||||||
|
],
|
||||||
|
"metadata": {
|
||||||
|
"azdata_cell_guid": "ceae5670-292f-4c45-9c10-4ac85baf2d07"
|
||||||
|
},
|
||||||
|
"outputs": [],
|
||||||
|
"execution_count": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"source": [
|
||||||
|
"## Create Azure SQL Database\r\n",
|
||||||
|
"\r\n",
|
||||||
|
"The database will be created based on all the settings previously specified. [Learn more](https://docs.microsoft.com/en-us/cli/azure/sql/db?view=azure-cli-latest#az_sql_db_create) about additonal options for creating the database."
|
||||||
|
],
|
||||||
|
"metadata": {
|
||||||
|
"azdata_cell_guid": "b460ca8f-65a7-4d6c-94b7-6d7dd9655fad"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"source": [
|
||||||
|
"create_database_result = run_command(\r\n",
|
||||||
|
" 'az sql db create '\r\n",
|
||||||
|
" '--server {0} '\r\n",
|
||||||
|
" '--name {1} '\r\n",
|
||||||
|
" '--edition GeneralPurpose '\r\n",
|
||||||
|
" '--compute-model Serverless '\r\n",
|
||||||
|
" '--family Gen5 '\r\n",
|
||||||
|
" '--resource-group {2} '\r\n",
|
||||||
|
" '--min-capacity 0.5 '\r\n",
|
||||||
|
" '--max-size 32GB '\r\n",
|
||||||
|
" '--capacity 1 '\r\n",
|
||||||
|
" '--collation {3} '\r\n",
|
||||||
|
" .format(\r\n",
|
||||||
|
" azure_sqldb_server_name, \r\n",
|
||||||
|
" azure_sqldb_database_name, \r\n",
|
||||||
|
" azure_sqldb_resource_group_name, \r\n",
|
||||||
|
" azure_sqldb_collation));"
|
||||||
|
],
|
||||||
|
"metadata": {
|
||||||
|
"azdata_cell_guid": "dc3b2f6f-83ac-4a4d-9d81-2f534e90913e"
|
||||||
|
},
|
||||||
|
"outputs": [],
|
||||||
|
"execution_count": null
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -405,7 +405,20 @@
|
|||||||
"dark": "./images/azure-sql-db.svg"
|
"dark": "./images/azure-sql-db.svg"
|
||||||
},
|
},
|
||||||
"tags": ["SQL Server", "Cloud"],
|
"tags": ["SQL Server", "Cloud"],
|
||||||
"okButtonText": "%azure-sqldb-ok-button-text%",
|
"okButtonText": [
|
||||||
|
{
|
||||||
|
"value": "%azure-sqldb-notebook-ok-button-text%",
|
||||||
|
"when": "resource-type=single-database"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"value": "%azure-sqldb-portal-ok-button-text%",
|
||||||
|
"when": "resource-type=elastic-pool"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"value": "%azure-sqldb-portal-ok-button-text%",
|
||||||
|
"when": "resource-type=database-server"
|
||||||
|
}
|
||||||
|
],
|
||||||
"options": [
|
"options": [
|
||||||
{
|
{
|
||||||
"name": "resource-type",
|
"name": "resource-type",
|
||||||
@@ -428,8 +441,14 @@
|
|||||||
],
|
],
|
||||||
"providers": [
|
"providers": [
|
||||||
{
|
{
|
||||||
"webPageUrl": "https://portal.azure.com/#create/Microsoft.SQLDatabase",
|
"azureSQLDBWizard":{
|
||||||
"requiredTools": [],
|
"notebook": "./notebooks/azuredb/create-sqldb.ipynb"
|
||||||
|
},
|
||||||
|
"requiredTools": [
|
||||||
|
{
|
||||||
|
"name": "azure-cli"
|
||||||
|
}
|
||||||
|
],
|
||||||
"when": "resource-type=single-database"
|
"when": "resource-type=single-database"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -70,9 +70,10 @@
|
|||||||
"azure-sqlvm-password-label": "Password",
|
"azure-sqlvm-password-label": "Password",
|
||||||
"azure-sqlvm-password-confirm-label": "Confirm password",
|
"azure-sqlvm-password-confirm-label": "Confirm password",
|
||||||
"azure-sqlvm-vm-summary-page-label": "Summary",
|
"azure-sqlvm-vm-summary-page-label": "Summary",
|
||||||
"azure-sqldb-display-name": "Azure SQL Database",
|
"azure-sqldb-display-name": "SQL Database on Azure Server",
|
||||||
"azure-sqldb-description": "Select a resource type and then you will be taken to the Azure portal to create the Azure resource.",
|
"azure-sqldb-description": "Create SQL Databases on Azure. Best for new applications or existing on-premises applications.",
|
||||||
"azure-sqldb-ok-button-text": "Create in Azure portal",
|
"azure-sqldb-portal-ok-button-text": "Create in Azure portal",
|
||||||
|
"azure-sqldb-notebook-ok-button-text": "Script to Notebook",
|
||||||
"resource-type-display-name": "Resource Type",
|
"resource-type-display-name": "Resource Type",
|
||||||
"sql-azure-single-database-display-name": "Single Database",
|
"sql-azure-single-database-display-name": "Single Database",
|
||||||
"sql-azure-elastic-pool-display-name": "Elastic Pool",
|
"sql-azure-elastic-pool-display-name": "Elastic Pool",
|
||||||
|
|||||||
@@ -19,7 +19,8 @@ export interface ResourceType {
|
|||||||
providers: DeploymentProvider[];
|
providers: DeploymentProvider[];
|
||||||
agreement?: AgreementInfo;
|
agreement?: AgreementInfo;
|
||||||
displayIndex?: number;
|
displayIndex?: number;
|
||||||
okButtonText?: string;
|
okButtonText?: OkButtonTextValue[];
|
||||||
|
getOkButtonText(selectedOptions: { option: string, value: string }[]): string | undefined;
|
||||||
getProvider(selectedOptions: { option: string, value: string }[]): DeploymentProvider | undefined;
|
getProvider(selectedOptions: { option: string, value: string }[]): DeploymentProvider | undefined;
|
||||||
tags?: string[];
|
tags?: string[];
|
||||||
}
|
}
|
||||||
@@ -40,6 +41,11 @@ export interface ResourceTypeOptionValue {
|
|||||||
displayName: string;
|
displayName: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface OkButtonTextValue {
|
||||||
|
value: string;
|
||||||
|
when: string;
|
||||||
|
}
|
||||||
|
|
||||||
export interface DialogDeploymentProvider extends DeploymentProviderBase {
|
export interface DialogDeploymentProvider extends DeploymentProviderBase {
|
||||||
dialog: DialogInfo;
|
dialog: DialogInfo;
|
||||||
}
|
}
|
||||||
@@ -72,6 +78,10 @@ export interface AzureSQLVMDeploymentProvider extends DeploymentProviderBase {
|
|||||||
azureSQLVMWizard: AzureSQLVMWizardInfo;
|
azureSQLVMWizard: AzureSQLVMWizardInfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface AzureSQLDBDeploymentProvider extends DeploymentProviderBase {
|
||||||
|
azureSQLDBWizard: AzureSQLDBWizardInfo;
|
||||||
|
}
|
||||||
|
|
||||||
export function instanceOfDialogDeploymentProvider(obj: any): obj is DialogDeploymentProvider {
|
export function instanceOfDialogDeploymentProvider(obj: any): obj is DialogDeploymentProvider {
|
||||||
return obj && 'dialog' in obj;
|
return obj && 'dialog' in obj;
|
||||||
}
|
}
|
||||||
@@ -104,12 +114,16 @@ export function instanceOfAzureSQLVMDeploymentProvider(obj: any): obj is AzureSQ
|
|||||||
return obj && 'azureSQLVMWizard' in obj;
|
return obj && 'azureSQLVMWizard' in obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function instanceOfAzureSQLDBDeploymentProvider(obj: any): obj is AzureSQLDBDeploymentProvider {
|
||||||
|
return obj && 'azureSQLDBWizard' in obj;
|
||||||
|
}
|
||||||
|
|
||||||
export interface DeploymentProviderBase {
|
export interface DeploymentProviderBase {
|
||||||
requiredTools: ToolRequirementInfo[];
|
requiredTools: ToolRequirementInfo[];
|
||||||
when: string;
|
when: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export type DeploymentProvider = DialogDeploymentProvider | BdcWizardDeploymentProvider | NotebookWizardDeploymentProvider | NotebookDeploymentProvider | WebPageDeploymentProvider | DownloadDeploymentProvider | CommandDeploymentProvider | AzureSQLVMDeploymentProvider;
|
export type DeploymentProvider = DialogDeploymentProvider | BdcWizardDeploymentProvider | NotebookWizardDeploymentProvider | NotebookDeploymentProvider | WebPageDeploymentProvider | DownloadDeploymentProvider | CommandDeploymentProvider | AzureSQLVMDeploymentProvider | AzureSQLDBDeploymentProvider;
|
||||||
|
|
||||||
export interface BdcWizardInfo {
|
export interface BdcWizardInfo {
|
||||||
notebook: string | NotebookPathInfo;
|
notebook: string | NotebookPathInfo;
|
||||||
@@ -182,6 +196,10 @@ export interface AzureSQLVMWizardInfo {
|
|||||||
notebook: string | NotebookPathInfo;
|
notebook: string | NotebookPathInfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface AzureSQLDBWizardInfo {
|
||||||
|
notebook: string | NotebookPathInfo;
|
||||||
|
}
|
||||||
|
|
||||||
export type DialogInfo = NotebookBasedDialogInfo | CommandBasedDialogInfo;
|
export type DialogInfo = NotebookBasedDialogInfo | CommandBasedDialogInfo;
|
||||||
|
|
||||||
export function instanceOfNotebookBasedDialogInfo(obj: any): obj is NotebookBasedDialogInfo {
|
export function instanceOfNotebookBasedDialogInfo(obj: any): obj is NotebookBasedDialogInfo {
|
||||||
|
|||||||
@@ -10,8 +10,9 @@ import * as os from 'os';
|
|||||||
import * as path from 'path';
|
import * as path from 'path';
|
||||||
import * as vscode from 'vscode';
|
import * as vscode from 'vscode';
|
||||||
import * as nls from 'vscode-nls';
|
import * as nls from 'vscode-nls';
|
||||||
import { DeploymentProvider, instanceOfAzureSQLVMDeploymentProvider, instanceOfCommandDeploymentProvider, instanceOfDialogDeploymentProvider, instanceOfDownloadDeploymentProvider, instanceOfNotebookBasedDialogInfo, instanceOfNotebookDeploymentProvider, instanceOfNotebookWizardDeploymentProvider, instanceOfWebPageDeploymentProvider, instanceOfWizardDeploymentProvider, NotebookInfo, NotebookPathInfo, ResourceType, ResourceTypeOption } from '../interfaces';
|
import { DeploymentProvider, instanceOfAzureSQLVMDeploymentProvider, instanceOfAzureSQLDBDeploymentProvider, instanceOfCommandDeploymentProvider, instanceOfDialogDeploymentProvider, instanceOfDownloadDeploymentProvider, instanceOfNotebookBasedDialogInfo, instanceOfNotebookDeploymentProvider, instanceOfNotebookWizardDeploymentProvider, instanceOfWebPageDeploymentProvider, instanceOfWizardDeploymentProvider, NotebookInfo, NotebookPathInfo, ResourceType, ResourceTypeOption } from '../interfaces';
|
||||||
import { DeployAzureSQLVMWizard } from '../ui/deployAzureSQLVMWizard/deployAzureSQLVMWizard';
|
import { DeployAzureSQLVMWizard } from '../ui/deployAzureSQLVMWizard/deployAzureSQLVMWizard';
|
||||||
|
import { DeployAzureSQLDBWizard } from '../ui/deployAzureSQLDBWizard/deployAzureSQLDBWizard';
|
||||||
import { DeployClusterWizard } from '../ui/deployClusterWizard/deployClusterWizard';
|
import { DeployClusterWizard } from '../ui/deployClusterWizard/deployClusterWizard';
|
||||||
import { DeploymentInputDialog } from '../ui/deploymentInputDialog';
|
import { DeploymentInputDialog } from '../ui/deploymentInputDialog';
|
||||||
import { NotebookWizard } from '../ui/notebookWizard/notebookWizard';
|
import { NotebookWizard } from '../ui/notebookWizard/notebookWizard';
|
||||||
@@ -20,6 +21,7 @@ import { KubeService } from './kubeService';
|
|||||||
import { INotebookService } from './notebookService';
|
import { INotebookService } from './notebookService';
|
||||||
import { IPlatformService } from './platformService';
|
import { IPlatformService } from './platformService';
|
||||||
import { IToolsService } from './toolsService';
|
import { IToolsService } from './toolsService';
|
||||||
|
import * as loc from './../localizedConstants';
|
||||||
|
|
||||||
const localize = nls.loadMessageBundle();
|
const localize = nls.loadMessageBundle();
|
||||||
|
|
||||||
@@ -46,6 +48,7 @@ export class ResourceTypeService implements IResourceTypeService {
|
|||||||
extensionResourceTypes.forEach((resourceType: ResourceType) => {
|
extensionResourceTypes.forEach((resourceType: ResourceType) => {
|
||||||
this.updatePathProperties(resourceType, extension.extensionPath);
|
this.updatePathProperties(resourceType, extension.extensionPath);
|
||||||
resourceType.getProvider = (selectedOptions) => { return this.getProvider(resourceType, selectedOptions); };
|
resourceType.getProvider = (selectedOptions) => { return this.getProvider(resourceType, selectedOptions); };
|
||||||
|
resourceType.getOkButtonText = (selectedOptions) => { return this.getOkButtonText(resourceType, selectedOptions); };
|
||||||
this._resourceTypes.push(resourceType);
|
this._resourceTypes.push(resourceType);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -78,6 +81,9 @@ export class ResourceTypeService implements IResourceTypeService {
|
|||||||
else if ('azureSQLVMWizard' in provider) {
|
else if ('azureSQLVMWizard' in provider) {
|
||||||
this.updateNotebookPath(provider.azureSQLVMWizard, extensionPath);
|
this.updateNotebookPath(provider.azureSQLVMWizard, extensionPath);
|
||||||
}
|
}
|
||||||
|
else if ('azureSQLDBWizard' in provider) {
|
||||||
|
this.updateNotebookPath(provider.azureSQLDBWizard, extensionPath);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -187,7 +193,8 @@ export class ResourceTypeService implements IResourceTypeService {
|
|||||||
&& !instanceOfDownloadDeploymentProvider(provider)
|
&& !instanceOfDownloadDeploymentProvider(provider)
|
||||||
&& !instanceOfWebPageDeploymentProvider(provider)
|
&& !instanceOfWebPageDeploymentProvider(provider)
|
||||||
&& !instanceOfCommandDeploymentProvider(provider)
|
&& !instanceOfCommandDeploymentProvider(provider)
|
||||||
&& !instanceOfAzureSQLVMDeploymentProvider(provider)) {
|
&& !instanceOfAzureSQLVMDeploymentProvider(provider)
|
||||||
|
&& !instanceOfAzureSQLDBDeploymentProvider(provider)) {
|
||||||
errorMessages.push(`No deployment method defined for the provider, ${providerPositionInfo}`);
|
errorMessages.push(`No deployment method defined for the provider, ${providerPositionInfo}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -245,6 +252,21 @@ export class ResourceTypeService implements IResourceTypeService {
|
|||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the ok button text based on the selected options
|
||||||
|
*/
|
||||||
|
private getOkButtonText(resourceType: ResourceType, selectedOptions: { option: string, value: string }[]): string | undefined {
|
||||||
|
if (resourceType.okButtonText && selectedOptions.length === 1) {
|
||||||
|
const optionGiven = `${selectedOptions[0].option}=${selectedOptions[0].value}`;
|
||||||
|
for (const possibleOption of resourceType.okButtonText) {
|
||||||
|
if (possibleOption.when === optionGiven || possibleOption.when === undefined || possibleOption.when.toString().toLowerCase() === 'true') {
|
||||||
|
return possibleOption.value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return loc.select;
|
||||||
|
}
|
||||||
|
|
||||||
public startDeployment(provider: DeploymentProvider): void {
|
public startDeployment(provider: DeploymentProvider): void {
|
||||||
const self = this;
|
const self = this;
|
||||||
if (instanceOfWizardDeploymentProvider(provider)) {
|
if (instanceOfWizardDeploymentProvider(provider)) {
|
||||||
@@ -283,6 +305,9 @@ export class ResourceTypeService implements IResourceTypeService {
|
|||||||
} else if (instanceOfAzureSQLVMDeploymentProvider(provider)) {
|
} else if (instanceOfAzureSQLVMDeploymentProvider(provider)) {
|
||||||
const wizard = new DeployAzureSQLVMWizard(provider.azureSQLVMWizard, this.notebookService, this.toolsService);
|
const wizard = new DeployAzureSQLVMWizard(provider.azureSQLVMWizard, this.notebookService, this.toolsService);
|
||||||
wizard.open();
|
wizard.open();
|
||||||
|
} else if (instanceOfAzureSQLDBDeploymentProvider(provider)) {
|
||||||
|
const wizard = new DeployAzureSQLDBWizard(provider.azureSQLDBWizard, this.notebookService, this.toolsService);
|
||||||
|
wizard.open();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,45 @@
|
|||||||
|
/*---------------------------------------------------------------------------------------------
|
||||||
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||||
|
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||||
|
*--------------------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
import * as nls from 'vscode-nls';
|
||||||
|
const localize = nls.loadMessageBundle();
|
||||||
|
|
||||||
|
export const standardWidth: string = '480px';
|
||||||
|
|
||||||
|
// Deploy Azure SQL DB wizard constants
|
||||||
|
export const WizardTitle = localize('deployAzureSQLDB.NewSQLDBTitle', "Deploy Azure SQL DB");
|
||||||
|
export const WizardDoneButtonLabel = localize('deployAzureSQLDB.ScriptToNotebook', "Script to Notebook");
|
||||||
|
export const MissingRequiredInformationErrorMessage = localize('deployAzureSQLDB.MissingRequiredInfoError', "Please fill out the required fields marked with red asterisks.");
|
||||||
|
|
||||||
|
// Azure settings page constants
|
||||||
|
export const AzureSettingsPageTitle = localize('deployAzureSQLDB.AzureSettingsPageTitle', "Azure SQL Database - Azure Account Settings");
|
||||||
|
export const AzureSettingsSummaryPageTitle = localize('deployAzureSQLDB.AzureSettingsSummaryPageTitle', "Azure Account Settings");
|
||||||
|
export const AzureAccountDropdownLabel = localize('deployAzureSQLDB.AzureAccountDropdownLabel', "Azure Account");
|
||||||
|
export const AzureAccountSubscriptionDropdownLabel = localize('deployAzureSQLDB.AzureSubscriptionDropdownLabel', "Subscription");
|
||||||
|
export const AzureAccountDatabaseServersDropdownLabel = localize('deployAzureSQLDB.AzureDatabaseServersDropdownLabel', "Server");
|
||||||
|
export const AzureAccountResourceGroupDropdownLabel = localize('deployAzureSQLDB.ResourceGroup', "Resource Group");
|
||||||
|
//@todo alma1 9/8/20 Region label used for upcoming server creation feature.
|
||||||
|
//export const AzureAccountRegionDropdownLabel = localize('deployAzureSQLDB.AzureRegionDropdownLabel', "Region (for Public IP Address)");
|
||||||
|
|
||||||
|
//Azure settings Database hardware properties. //@todo alma1 9/8/20 labels used for upcoming database hardware creation feature.
|
||||||
|
// export const DatabaseHardwareInfoLabel = localize('deployAzureSQLDB.DatabaseHardwareInfo', "SQLDB Hardware Settings");
|
||||||
|
// export const DatabaseManagedInstanceDropdownLabel = localize('deployAzureSQLDB.DatabaseManagedInstanceDropdownLabel', "SQLDB Version");
|
||||||
|
// export const DatabaseSupportedEditionsDropdownLabel = localize('deployAzureSQLDB.DatabaseSupportedEditionsDropdownLabel', "Edition Type");
|
||||||
|
// export const DatabaseSupportedFamilyDropdownLabel = localize('deployAzureSQLDB.DatabaseSupportedFamilyDropdownLabel', "Family Type");
|
||||||
|
// export const DatabaseVCoreNumberDropdownLabel = localize('deployAzureSQLDB.DatabaseVCoreNumberDropdownLabel', "Number of Vcores");
|
||||||
|
// export const DatabaseMaxMemoryTextLabel = localize('deployAzureSQLDB.DatabaseMaxMemoryTextLabel', "Maximum Data Storage Capacity in GB, can go up to 1TB (1024 GB).");
|
||||||
|
// export const DatabaseMaxMemorySummaryTextLabel = localize('deployAzureSQLDB.DatabaseMaxMemorySummaryTextLabel', "Maximum Data Storage Capacity in GB");
|
||||||
|
|
||||||
|
// Database settings page constants
|
||||||
|
export const DatabaseSettingsPageTitle = localize('deployAzureSQLDB.DatabaseSettingsPageTitle', "Database settings");
|
||||||
|
export const FirewallRuleNameLabel = localize('deployAzureSQLDB.FirewallRuleNameLabel', "Firewall rule name");
|
||||||
|
export const DatabaseNameLabel = localize('deployAzureSQLDB.DatabaseNameLabel', "SQL database name");
|
||||||
|
export const CollationNameLabel = localize('deployAzureSQLDB.CollationNameLabel', "Database collation");
|
||||||
|
export const CollationNameSummaryLabel = localize('deployAzureSQLDB.CollationNameSummaryLabel', "Collation for database");
|
||||||
|
export const IpAddressInfoLabel = localize('deployAzureSQLDB.IpAddressInfoLabel', "Enter IP Addresses in IPv4 format.");
|
||||||
|
export const StartIpAddressLabel = localize('deployAzureSQLDB.StartIpAddressLabel', "Min IP Address in firewall Ip Range");
|
||||||
|
export const EndIpAddressLabel = localize('deployAzureSQLDB.EndIpAddressLabel', "Max IP Address in firewall IP Range");
|
||||||
|
export const StartIpAddressShortLabel = localize('deployAzureSQLDB.StartIpAddressShortLabel', "Min IP Address");
|
||||||
|
export const EndIpAddressShortLabel = localize('deployAzureSQLDB.EndIpAddressShortLabel', "Max IP Address");
|
||||||
@@ -0,0 +1,175 @@
|
|||||||
|
/*---------------------------------------------------------------------------------------------
|
||||||
|
* 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 vscode from 'vscode';
|
||||||
|
import * as constants from './constants';
|
||||||
|
import { INotebookService } from '../../services/notebookService';
|
||||||
|
import { IToolsService } from '../../services/toolsService';
|
||||||
|
import { WizardBase } from '../wizardBase';
|
||||||
|
import { WizardPageBase } from '../wizardPageBase';
|
||||||
|
import { DeployAzureSQLDBWizardModel } from './deployAzureSQLDBWizardModel';
|
||||||
|
import { AzureSQLDBWizardInfo } from '../../interfaces';
|
||||||
|
import { AzureSettingsPage } from './pages/azureSettingsPage';
|
||||||
|
import { DatabaseSettingsPage } from './pages/databaseSettingsPage';
|
||||||
|
import axios, { AxiosRequestConfig } from 'axios';
|
||||||
|
import { AzureSQLDBSummaryPage } from './pages/summaryPage';
|
||||||
|
import { EOL } from 'os';
|
||||||
|
|
||||||
|
export class DeployAzureSQLDBWizard extends WizardBase<DeployAzureSQLDBWizard, WizardPageBase<DeployAzureSQLDBWizard>, DeployAzureSQLDBWizardModel> {
|
||||||
|
|
||||||
|
constructor(private wizardInfo: AzureSQLDBWizardInfo, private _notebookService: INotebookService, private _toolsService: IToolsService) {
|
||||||
|
super(
|
||||||
|
constants.WizardTitle,
|
||||||
|
'DeployAzureSqlDBWizard',
|
||||||
|
new DeployAzureSQLDBWizardModel(),
|
||||||
|
_toolsService
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
private cache: Map<string, any> = new Map();
|
||||||
|
|
||||||
|
protected initialize(): void {
|
||||||
|
this.setPages(this.getPages());
|
||||||
|
this.wizardObject.generateScriptButton.hidden = true;
|
||||||
|
this.wizardObject.doneButton.label = constants.WizardDoneButtonLabel;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public get notebookService(): INotebookService {
|
||||||
|
return this._notebookService;
|
||||||
|
}
|
||||||
|
|
||||||
|
public get toolService(): IToolsService {
|
||||||
|
return this._toolsService;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected async onOk(): Promise<void> {
|
||||||
|
await this.scriptToNotebook();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected onCancel(): void {
|
||||||
|
}
|
||||||
|
|
||||||
|
private getPages(): WizardPageBase<DeployAzureSQLDBWizard>[] {
|
||||||
|
const pages: WizardPageBase<DeployAzureSQLDBWizard>[] = [];
|
||||||
|
pages.push(new AzureSettingsPage(this));
|
||||||
|
pages.push(new DatabaseSettingsPage(this));
|
||||||
|
pages.push(new AzureSQLDBSummaryPage(this));
|
||||||
|
return pages;
|
||||||
|
}
|
||||||
|
|
||||||
|
private async scriptToNotebook(): Promise<void> {
|
||||||
|
const variableValueStatements = this.model.getCodeCellContentForNotebook();
|
||||||
|
const insertionPosition = 2; // Cell number 2 is the position where the python variable setting statements need to be inserted in this.wizardInfo.notebook.
|
||||||
|
try {
|
||||||
|
await this.notebookService.openNotebookWithEdits(this.wizardInfo.notebook, variableValueStatements, insertionPosition);
|
||||||
|
} catch (error) {
|
||||||
|
vscode.window.showErrorMessage(error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public async getRequest(url: string, useCache = false): Promise<any> {
|
||||||
|
if (useCache) {
|
||||||
|
if (this.cache.has(url)) {
|
||||||
|
return this.cache.get(url);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let token = this.model.securityToken.token;
|
||||||
|
const config: AxiosRequestConfig = {
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
'Authorization': `Bearer ${token}`
|
||||||
|
},
|
||||||
|
validateStatus: () => true // Never throw
|
||||||
|
};
|
||||||
|
const response = await axios.get(url, config);
|
||||||
|
if (response.status !== 200) {
|
||||||
|
let errorMessage: string[] = [];
|
||||||
|
errorMessage.push(response.status.toString());
|
||||||
|
errorMessage.push(response.statusText);
|
||||||
|
if (response.data && response.data.error) {
|
||||||
|
errorMessage.push(`${response.data.error.code} : ${response.data.error.message}`);
|
||||||
|
}
|
||||||
|
vscode.window.showErrorMessage(errorMessage.join(EOL));
|
||||||
|
}
|
||||||
|
if (useCache) {
|
||||||
|
this.cache.set(url, response);
|
||||||
|
}
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
|
||||||
|
public createFormRowComponent(view: azdata.ModelView, title: string, description: string, component: azdata.Component, required: boolean): azdata.FlexContainer {
|
||||||
|
|
||||||
|
component.updateProperties({
|
||||||
|
required: required,
|
||||||
|
width: '480px'
|
||||||
|
});
|
||||||
|
|
||||||
|
const labelText = view.modelBuilder.text()
|
||||||
|
.withProperties<azdata.TextComponentProperties>(
|
||||||
|
{
|
||||||
|
value: title,
|
||||||
|
width: '250px',
|
||||||
|
description: description,
|
||||||
|
requiredIndicator: required,
|
||||||
|
})
|
||||||
|
.component();
|
||||||
|
|
||||||
|
labelText.updateCssStyles({
|
||||||
|
'font-weight': '400',
|
||||||
|
'font-size': '13px',
|
||||||
|
});
|
||||||
|
|
||||||
|
const flexContainer = view.modelBuilder.flexContainer()
|
||||||
|
.withLayout(
|
||||||
|
{
|
||||||
|
flexFlow: 'row',
|
||||||
|
alignItems: 'center',
|
||||||
|
})
|
||||||
|
.withItems(
|
||||||
|
[labelText, component],
|
||||||
|
{
|
||||||
|
CSSStyles: { 'margin-right': '5px' }
|
||||||
|
})
|
||||||
|
.component();
|
||||||
|
return flexContainer;
|
||||||
|
}
|
||||||
|
|
||||||
|
public changeComponentDisplay(component: azdata.Component, display: ('none' | 'block')) {
|
||||||
|
component.updateProperties({
|
||||||
|
required: display === 'block'
|
||||||
|
});
|
||||||
|
component.updateCssStyles({
|
||||||
|
display: display
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public changeRowDisplay(container: azdata.FlexContainer, display: ('none' | 'block')) {
|
||||||
|
container.items.map((component) => {
|
||||||
|
component.updateProperties({
|
||||||
|
required: (display === 'block'),
|
||||||
|
});
|
||||||
|
component.updateCssStyles({
|
||||||
|
display: display,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public addDropdownValues(component: azdata.DropDownComponent, values: azdata.CategoryValue[], width?: number) {
|
||||||
|
component.updateProperties({
|
||||||
|
values: values,
|
||||||
|
width: '480px'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public showErrorMessage(message: string) {
|
||||||
|
this.wizardObject.message = {
|
||||||
|
text: message,
|
||||||
|
level: azdata.window.MessageLevel.Error
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,56 @@
|
|||||||
|
/*---------------------------------------------------------------------------------------------
|
||||||
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||||
|
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||||
|
*--------------------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
import { EOL } from 'os';
|
||||||
|
import * as azdata from 'azdata';
|
||||||
|
import { Model } from '../model';
|
||||||
|
|
||||||
|
export class DeployAzureSQLDBWizardModel extends Model {
|
||||||
|
public azureAccount!: azdata.Account;
|
||||||
|
public securityToken!: any;
|
||||||
|
public azureSubscription!: string;
|
||||||
|
public azureSubscriptionDisplayName!: string;
|
||||||
|
public azureResouceGroup!: string;
|
||||||
|
public azureServerName!: string;
|
||||||
|
public azureRegion!: string;
|
||||||
|
|
||||||
|
// public databaseEdition!: string; //@todo alma1 10/7/2020 used for upcoming database hardware creation feature
|
||||||
|
// public databaseFamily!: string;
|
||||||
|
// public vCoreNumber!: number;
|
||||||
|
// public storageInGB!: string;
|
||||||
|
|
||||||
|
public databaseName!: string;
|
||||||
|
//public newServer!: 'True' | 'False'; //@todo alma1 9/8/2020 used for upcoming server creation feature.
|
||||||
|
public startIpAddress!: string;
|
||||||
|
public endIpAddress!: string;
|
||||||
|
public firewallRuleName!: string;
|
||||||
|
public databaseCollation!: string;
|
||||||
|
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
|
public getCodeCellContentForNotebook(): string[] {
|
||||||
|
const statements: string[] = [];
|
||||||
|
|
||||||
|
statements.push(`azure_sqldb_subscription = '${this.azureSubscription}'`);
|
||||||
|
statements.push(`azure_sqldb_resource_group_name = '${this.azureResouceGroup}'`);
|
||||||
|
statements.push(`azure_sqldb_server_name = '${this.azureServerName}'`);
|
||||||
|
//statements.push(`azure_sqldb_database_edition = '${this.databaseEdition}'`); //@todo alma1 10/7/2020 used for upcoming datbase hardware creation feature.
|
||||||
|
statements.push(`azure_sqldb_database_name = '${this.databaseName}'`);
|
||||||
|
//statements.push(`azure_sqldb_location = '${this.azureRegion}'`); //@todo alma1 9/10/2020 used for upcoming server creation feature.
|
||||||
|
statements.push(`azure_sqldb_ip_start = '${this.startIpAddress}'`);
|
||||||
|
statements.push(`azure_sqldb_ip_end = '${this.endIpAddress}'`);
|
||||||
|
statements.push(`azure_sqldb_firewall_name = '${this.firewallRuleName}'`);
|
||||||
|
statements.push(`azure_sqldb_collation = '${this.databaseCollation}'`);
|
||||||
|
// statements.push(`azure_sqldb_family = '${this.databaseFamily}'`); //@todo alma1 10/7/2020 used for upcoming datbase hardware creation feature.
|
||||||
|
// statements.push(`azure_sqldb_vcore = '${this.vCoreNumber}'`);
|
||||||
|
// statements.push(`azure_sqldb_maxmemory = '${this.storageInGB}'`);
|
||||||
|
//statements.push(`azure_sqldb_new_server = '${this.newServer}'`); //@todo alma1 9/8/2020 used for upcoming server creation feature.
|
||||||
|
|
||||||
|
return statements.map(line => line.concat(EOL));
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,765 @@
|
|||||||
|
/*---------------------------------------------------------------------------------------------
|
||||||
|
* 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 { EOL } from 'os';
|
||||||
|
import * as constants from '../constants';
|
||||||
|
import { DeployAzureSQLDBWizard } from '../deployAzureSQLDBWizard';
|
||||||
|
import { apiService } from '../../../services/apiService';
|
||||||
|
import { azureResource } from 'azureResource';
|
||||||
|
import * as vscode from 'vscode';
|
||||||
|
import { BasePage } from './basePage';
|
||||||
|
import * as nls from 'vscode-nls';
|
||||||
|
const localize = nls.loadMessageBundle();
|
||||||
|
|
||||||
|
export class AzureSettingsPage extends BasePage {
|
||||||
|
// <- 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 //@todo alma1 9/9/2020 Used for upcoming server creation feature.
|
||||||
|
// private _resourceGroupDropdown!: azdata.DropDownComponent;
|
||||||
|
|
||||||
|
//dropdown for SQL servers <- subscription dropdown
|
||||||
|
private _serverGroupDropdown!: azdata.DropDownComponent;
|
||||||
|
|
||||||
|
// //dropdown for azure regions <- subscription dropdown //@todo alma1 9/8/2020 Region dropdown used for upcoming server creation feature.
|
||||||
|
// private _azureRegionsDropdown!: azdata.DropDownComponent;
|
||||||
|
|
||||||
|
// //information text about hardware settings. //@todo alma1 9/8/2020 components below are used for upcoming database hardware creation feature.
|
||||||
|
// private _dbHardwareInfoText!: azdata.TextComponent;
|
||||||
|
|
||||||
|
// //dropdown for Managed Instance Versions <- server dropdown.
|
||||||
|
// private _dbManagedInstanceDropdown!: azdata.DropDownComponent;
|
||||||
|
|
||||||
|
// //dropdown for Supported Editions <- Managed Instance dropdown.
|
||||||
|
// private _dbSupportedEditionsDropdown!: azdata.DropDownComponent;
|
||||||
|
|
||||||
|
// //dropdown for Supported Family <- Supported Editions dropdown.
|
||||||
|
// private _dbSupportedFamilyDropdown!: azdata.DropDownComponent;
|
||||||
|
|
||||||
|
// //dropdown for VCore <= Supported Family dropdown.
|
||||||
|
// private _dbVCoreDropdown!: azdata.DropDownComponent;
|
||||||
|
|
||||||
|
|
||||||
|
// //input box for maximum memory size, supports between 1 and 1024 GB (1 TB)
|
||||||
|
// private _dbMemoryTextBox!: azdata.InputBoxComponent;
|
||||||
|
|
||||||
|
private _form!: azdata.FormContainer;
|
||||||
|
|
||||||
|
private _accountsMap!: Map<string, azdata.Account>;
|
||||||
|
private _subscriptionsMap!: Map<string, azureResource.AzureResourceSubscription>;
|
||||||
|
constructor(wizard: DeployAzureSQLDBWizard) {
|
||||||
|
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), //@todo alma1 9/8/2020 used for upcoming server creation feature.
|
||||||
|
this.createServerDropdown(view),
|
||||||
|
//this.createAzureRegionsDropdown(view) //@todo alma1 9/8/2020 used for upcoming server creation feature.
|
||||||
|
// this.createDatabaseHardwareSettingsText(view), //@todo alma1 9/8/2020 used for upcoming database hardware creation feature.
|
||||||
|
// this.createManagedInstanceDropdown(view),
|
||||||
|
// this.createSupportedEditionsDropdown(view),
|
||||||
|
// this.createSupportedFamilyDropdown(view),
|
||||||
|
// this.createVCoreDropdown(view),
|
||||||
|
// this.createMaxMemoryText(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)
|
||||||
|
},
|
||||||
|
// { //@todo alma1 9/9/2020 Used for upcoming server creation feature.
|
||||||
|
// component: this.wizard.createFormRowComponent(view, constants.AzureAccountResourceGroupDropdownLabel, '', this._resourceGroupDropdown, true)
|
||||||
|
// },
|
||||||
|
{
|
||||||
|
component: this.wizard.createFormRowComponent(view, constants.AzureAccountDatabaseServersDropdownLabel, '', this._serverGroupDropdown, true)
|
||||||
|
},
|
||||||
|
// { //@todo alma1 9/8/2020 Used for upcoming server creation feature.
|
||||||
|
// component: this.wizard.createFormRowComponent(view, constants.AzureAccountRegionDropdownLabel, '', this._azureRegionsDropdown, true)
|
||||||
|
// }
|
||||||
|
// { //@todo alma1 9/8/2020 Used for upcoming database hardware creation feature.
|
||||||
|
// component: this._dbHardwareInfoText
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// component: this.wizard.createFormRowComponent(view, constants.DatabaseManagedInstanceDropdownLabel, '', this._dbManagedInstanceDropdown, true)
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// component: this.wizard.createFormRowComponent(view, constants.DatabaseSupportedEditionsDropdownLabel, '', this._dbSupportedEditionsDropdown, true)
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// component: this.wizard.createFormRowComponent(view, constants.DatabaseSupportedFamilyDropdownLabel, '', this._dbSupportedFamilyDropdown, true)
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// component: this.wizard.createFormRowComponent(view, constants.DatabaseVCoreNumberDropdownLabel, '', this._dbVCoreDropdown, true)
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// component: this.wizard.createFormRowComponent(view, constants.DatabaseMaxMemoryTextLabel, '', this._dbMemoryTextBox, true)
|
||||||
|
// }
|
||||||
|
],
|
||||||
|
{
|
||||||
|
horizontal: false,
|
||||||
|
componentWidth: '100%'
|
||||||
|
})
|
||||||
|
.withLayout({ width: '100%' })
|
||||||
|
.component();
|
||||||
|
return view.initializeModel(this._form);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public async onEnter(): Promise<void> {
|
||||||
|
this.wizard.wizardObject.registerNavigationValidator(async (pcInfo) => {
|
||||||
|
if (pcInfo.newPage < pcInfo.lastPage) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
let errorMessage = await this.validate();
|
||||||
|
|
||||||
|
if (errorMessage !== '') {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
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(localize('deployAzureSQLDB.azureSignInError', "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().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
|
||||||
|
);
|
||||||
|
|
||||||
|
await this.populateServerGroupDropdown();
|
||||||
|
//@todo alma1 9/8/2020 used for upcoming server creation feature.
|
||||||
|
//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.populateServerGroupDropdown();
|
||||||
|
//@todo alma1 9/8/2020 used for upcoming server creation feature.
|
||||||
|
//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.populateServerGroupDropdown();
|
||||||
|
//@todo alma1 9/8/2020 used for upcoming server creation feature.
|
||||||
|
//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.populateServerGroupDropdown();
|
||||||
|
//@todo alma1 9/8/2020 used for upcoming server creation feature.
|
||||||
|
//await this.populateResourceGroupDropdown();
|
||||||
|
//await this.populateAzureRegionsDropdown();
|
||||||
|
}
|
||||||
|
|
||||||
|
private async createServerDropdown(view: azdata.ModelView) {
|
||||||
|
this._serverGroupDropdown = view.modelBuilder.dropDown().withProperties({
|
||||||
|
required: true,
|
||||||
|
}).component();
|
||||||
|
this._serverGroupDropdown.onValueChanged(async (value) => {
|
||||||
|
if (value.selected === ((this._serverGroupDropdown.value as azdata.CategoryValue).displayName)) {
|
||||||
|
this.wizard.model.azureServerName = value.selected;
|
||||||
|
this.wizard.model.azureResouceGroup = (this._serverGroupDropdown.value as azdata.CategoryValue).name.replace(RegExp('^(.*?)/resourceGroups/'), '').replace(RegExp('/providers/.*'), '');
|
||||||
|
this.wizard.model.azureRegion = (this._serverGroupDropdown.value as azdata.CategoryValue).name.replace(RegExp('^(.*?)/location/'), '');
|
||||||
|
//this.populateManagedInstanceDropdown(); //@todo alma1 9/8/2020 functions below are used for upcoming database hardware creation feature.
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private async populateServerGroupDropdown() {
|
||||||
|
this._serverGroupDropdown.loading = true;
|
||||||
|
let currentSubscriptionValue = this._azureSubscriptionsDropdown.value as azdata.CategoryValue;
|
||||||
|
if (currentSubscriptionValue === undefined || currentSubscriptionValue.displayName === '') {
|
||||||
|
this._serverGroupDropdown.updateProperties({
|
||||||
|
values: []
|
||||||
|
});
|
||||||
|
this._serverGroupDropdown.loading = false;
|
||||||
|
// await this.populateManagedInstanceDropdown(); //@todo alma1 9/8/2020 functions below are used for upcoming database hardware creation feature.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let url = `https://management.azure.com/subscriptions/${this.wizard.model.azureSubscription}/providers/Microsoft.Sql/servers?api-version=2019-06-01-preview`;
|
||||||
|
let response = await this.wizard.getRequest(url);
|
||||||
|
if (response.data.value.length === 0) {
|
||||||
|
this._serverGroupDropdown.updateProperties({
|
||||||
|
values: [
|
||||||
|
{
|
||||||
|
displayName: localize('deployAzureSQLDB.NoServerLabel', "No servers found"),
|
||||||
|
name: ''
|
||||||
|
}
|
||||||
|
],
|
||||||
|
});
|
||||||
|
this._serverGroupDropdown.loading = false;
|
||||||
|
// await this.populateManagedInstanceDropdown(); //@todo alma1 9/8/2020 functions below are used for upcoming database hardware creation feature.
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
response.data.value.sort((a: azdata.CategoryValue, b: azdata.CategoryValue) => (a!.name > b!.name) ? 1 : -1);
|
||||||
|
}
|
||||||
|
this.wizard.addDropdownValues(
|
||||||
|
this._serverGroupDropdown,
|
||||||
|
response.data.value.map((value: any) => {
|
||||||
|
return {
|
||||||
|
displayName: value.name,
|
||||||
|
// remove location from this line and others when region population is enabled again.
|
||||||
|
name: value.id + '/location/' + value.location,
|
||||||
|
};
|
||||||
|
})
|
||||||
|
);
|
||||||
|
if (this._serverGroupDropdown.value) {
|
||||||
|
this.wizard.model.azureServerName = (this._serverGroupDropdown.value as azdata.CategoryValue).displayName;
|
||||||
|
this.wizard.model.azureResouceGroup = (this._serverGroupDropdown.value as azdata.CategoryValue).name.replace(RegExp('^(.*?)/resourceGroups/'), '').replace(RegExp('/providers/.*'), '');
|
||||||
|
this.wizard.model.azureRegion = (this._serverGroupDropdown.value as azdata.CategoryValue).name.replace(RegExp('^(.*?)/location/'), '');
|
||||||
|
}
|
||||||
|
this._serverGroupDropdown.loading = false;
|
||||||
|
// await this.populateManagedInstanceDropdown(); //@todo alma1 9/8/2020 functions below are used for upcoming database hardware creation feature.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
//@todo alma1 9/8/2020 functions below are used for upcoming server creation feature.
|
||||||
|
|
||||||
|
// 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;
|
||||||
|
// this.populateServerGroupDropdown();
|
||||||
|
// });
|
||||||
|
// }
|
||||||
|
|
||||||
|
// 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;
|
||||||
|
// await this.populateServerGroupDropdown();
|
||||||
|
// 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: []
|
||||||
|
// });
|
||||||
|
// await this.populateServerGroupDropdown();
|
||||||
|
// 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;
|
||||||
|
// await this.populateServerGroupDropdown();
|
||||||
|
// }
|
||||||
|
|
||||||
|
// 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, true);
|
||||||
|
// 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;
|
||||||
|
// }
|
||||||
|
|
||||||
|
//@todo alma1 9/8/2020 functions below are used for upcoming database hardware creation feature.
|
||||||
|
|
||||||
|
// private createDatabaseHardwareSettingsText(view: azdata.ModelView) {
|
||||||
|
// this._dbHardwareInfoText = view.modelBuilder.text()
|
||||||
|
// .withProperties({
|
||||||
|
// value: constants.DatabaseHardwareInfoLabel
|
||||||
|
// }).component();
|
||||||
|
// }
|
||||||
|
|
||||||
|
// private async createManagedInstanceDropdown(view: azdata.ModelView) {
|
||||||
|
// this._dbManagedInstanceDropdown = view.modelBuilder.dropDown().withProperties({
|
||||||
|
// required: true,
|
||||||
|
// }).component();
|
||||||
|
// this._dbManagedInstanceDropdown.onValueChanged(async (value) => {
|
||||||
|
// this.populateSupportedEditionsDropdown();
|
||||||
|
// });
|
||||||
|
// }
|
||||||
|
|
||||||
|
// private async populateManagedInstanceDropdown() {
|
||||||
|
// this._dbManagedInstanceDropdown.loading = true;
|
||||||
|
// let currentSubscriptionValue = this._azureSubscriptionsDropdown.value as azdata.CategoryValue;
|
||||||
|
// if (!currentSubscriptionValue || currentSubscriptionValue.displayName === '') {
|
||||||
|
// this._dbManagedInstanceDropdown.updateProperties({
|
||||||
|
// values: []
|
||||||
|
// });
|
||||||
|
// this._dbManagedInstanceDropdown.loading = false;
|
||||||
|
// await this.populateSupportedEditionsDropdown();
|
||||||
|
// return;
|
||||||
|
// }
|
||||||
|
// let currentServerValue = this._serverGroupDropdown.value as azdata.CategoryValue;
|
||||||
|
|
||||||
|
// if (currentServerValue.name === '') {
|
||||||
|
// this._dbManagedInstanceDropdown.updateProperties({
|
||||||
|
// values: [
|
||||||
|
// {
|
||||||
|
// displayName: localize('deployAzureSQLDB.NoServerLabel', "No servers found"),
|
||||||
|
// name: '',
|
||||||
|
// supportedEditions: undefined
|
||||||
|
// }
|
||||||
|
// ]
|
||||||
|
// });
|
||||||
|
// this._dbManagedInstanceDropdown.loading = false;
|
||||||
|
// await this.populateSupportedEditionsDropdown();
|
||||||
|
// return;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// let url = `https://management.azure.com/subscriptions/${this.wizard.model.azureSubscription}/providers/Microsoft.Sql/locations/${this.wizard.model.azureRegion}/capabilities?api-version=2017-10-01-preview`;
|
||||||
|
// let response = await this.wizard.getRequest(url);
|
||||||
|
|
||||||
|
// if (response.data.supportedManagedInstanceVersions.length === 0) {
|
||||||
|
// this._dbManagedInstanceDropdown.updateProperties({
|
||||||
|
// values: [
|
||||||
|
// {
|
||||||
|
// displayName: localize('deployAzureSQLDB.NoHardwareConfigLabel', "No database hardware configuration found"),
|
||||||
|
// name: '',
|
||||||
|
// supportedEditions: undefined
|
||||||
|
// }
|
||||||
|
// ],
|
||||||
|
// });
|
||||||
|
// this._dbManagedInstanceDropdown.loading = false;
|
||||||
|
// await this.populateSupportedEditionsDropdown();
|
||||||
|
// return;
|
||||||
|
// } else {
|
||||||
|
// response.data.supportedManagedInstanceVersions.sort((a: any, b: any) => (a!.name > b!.name) ? 1 : -1);
|
||||||
|
// }
|
||||||
|
// this.wizard.addDropdownValues(
|
||||||
|
// this._dbManagedInstanceDropdown,
|
||||||
|
// response.data.supportedManagedInstanceVersions.map((value: any) => {
|
||||||
|
// return {
|
||||||
|
// displayName: value.name,
|
||||||
|
// name: value.name,
|
||||||
|
// supportedEditions: value.supportedEditions
|
||||||
|
// };
|
||||||
|
// })
|
||||||
|
// );
|
||||||
|
// // if (this._serverGroupDropdown.value) {
|
||||||
|
// // this.wizard.model.azureServerName = (this._serverGroupDropdown.value as azdata.CategoryValue).displayName;
|
||||||
|
// // this.wizard.model.azureResouceGroup = (this._serverGroupDropdown.value as azdata.CategoryValue).name.replace(RegExp('^(.*?)/resourceGroups/'), '').replace(RegExp('/providers/.*'), '');
|
||||||
|
// // this.wizard.model.azureRegion = (this._serverGroupDropdown.value as azdata.CategoryValue).name.replace(RegExp('^(.*?)/location/'), '');
|
||||||
|
// // }
|
||||||
|
// this._dbManagedInstanceDropdown.loading = false;
|
||||||
|
// await this.populateSupportedEditionsDropdown();
|
||||||
|
// return;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// private async createSupportedEditionsDropdown(view: azdata.ModelView) {
|
||||||
|
// this._dbSupportedEditionsDropdown = view.modelBuilder.dropDown().withProperties({
|
||||||
|
// required: true,
|
||||||
|
// }).component();
|
||||||
|
// this._dbSupportedEditionsDropdown.onValueChanged(async (value) => {
|
||||||
|
// this.wizard.model.databaseEdition = value.selected;
|
||||||
|
// this.populateSupportedFamilyDropdown();
|
||||||
|
// });
|
||||||
|
// }
|
||||||
|
|
||||||
|
// private async populateSupportedEditionsDropdown() {
|
||||||
|
// this._dbSupportedEditionsDropdown.loading = true;
|
||||||
|
// if (!this._dbManagedInstanceDropdown.values || this._dbManagedInstanceDropdown.values!.length === 0) {
|
||||||
|
// this._dbSupportedEditionsDropdown.updateProperties({
|
||||||
|
// values: []
|
||||||
|
// });
|
||||||
|
// this._dbSupportedEditionsDropdown.loading = false;
|
||||||
|
// await this.populateSupportedFamilyDropdown();
|
||||||
|
// return;
|
||||||
|
// }
|
||||||
|
// let currentManagedInstanceValue = this._dbManagedInstanceDropdown.value as any;
|
||||||
|
// if (!currentManagedInstanceValue.supportedEditions) {
|
||||||
|
// this._dbSupportedEditionsDropdown.updateProperties({
|
||||||
|
// values: [
|
||||||
|
// {
|
||||||
|
// displayName: localize('deployAzureSQLDB.NoManagedInstanceLabel', "Managed instance not selected"),
|
||||||
|
// name: ''
|
||||||
|
// }
|
||||||
|
// ]
|
||||||
|
// });
|
||||||
|
// this._dbSupportedEditionsDropdown.loading = false;
|
||||||
|
// await this.populateSupportedFamilyDropdown();
|
||||||
|
// return;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// if (currentManagedInstanceValue.supportedEditions.length === 0) {
|
||||||
|
// this._dbSupportedEditionsDropdown.updateProperties({
|
||||||
|
// values: [
|
||||||
|
// {
|
||||||
|
// displayName: localize('deployAzureSQLDB.NoSupportedEditionsLabel', "No supported editions found"),
|
||||||
|
// name: ''
|
||||||
|
// }
|
||||||
|
// ],
|
||||||
|
// });
|
||||||
|
// this._dbSupportedEditionsDropdown.loading = false;
|
||||||
|
// await this.populateSupportedFamilyDropdown();
|
||||||
|
// return;
|
||||||
|
// } else {
|
||||||
|
// currentManagedInstanceValue.supportedEditions.sort((a: any, b: any) => (a!.name > b!.name) ? 1 : -1);
|
||||||
|
// }
|
||||||
|
// this.wizard.addDropdownValues(
|
||||||
|
// this._dbSupportedEditionsDropdown,
|
||||||
|
// currentManagedInstanceValue.supportedEditions.map((value: any) => {
|
||||||
|
// return {
|
||||||
|
// displayName: value.name,
|
||||||
|
// name: value.supportedFamilies
|
||||||
|
// };
|
||||||
|
// })
|
||||||
|
// );
|
||||||
|
// if (this._dbSupportedEditionsDropdown.value) {
|
||||||
|
// this.wizard.model.databaseEdition = (this._dbSupportedEditionsDropdown.value as azdata.CategoryValue).displayName;
|
||||||
|
// }
|
||||||
|
// this._dbSupportedEditionsDropdown.loading = false;
|
||||||
|
// await this.populateSupportedFamilyDropdown();
|
||||||
|
// return;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// private async createSupportedFamilyDropdown(view: azdata.ModelView) {
|
||||||
|
// this._dbSupportedFamilyDropdown = view.modelBuilder.dropDown().withProperties({
|
||||||
|
// required: true,
|
||||||
|
// }).component();
|
||||||
|
// this._dbSupportedFamilyDropdown.onValueChanged(async (value) => {
|
||||||
|
// this.wizard.model.databaseFamily = value.selected;
|
||||||
|
// this.populateVCoreDropdown();
|
||||||
|
// });
|
||||||
|
// }
|
||||||
|
|
||||||
|
// private async populateSupportedFamilyDropdown() {
|
||||||
|
// this._dbSupportedFamilyDropdown.loading = true;
|
||||||
|
// if (!this._dbSupportedEditionsDropdown.values || this._dbSupportedEditionsDropdown.values!.length === 0) {
|
||||||
|
// this._dbSupportedFamilyDropdown.updateProperties({
|
||||||
|
// values: []
|
||||||
|
// });
|
||||||
|
// this._dbSupportedFamilyDropdown.loading = false;
|
||||||
|
// await this.populateVCoreDropdown();
|
||||||
|
// return;
|
||||||
|
// }
|
||||||
|
// let currentSupportedEditionValue = this._dbSupportedEditionsDropdown.value as any;
|
||||||
|
// if (!currentSupportedEditionValue.name) {
|
||||||
|
// this._dbSupportedFamilyDropdown.updateProperties({
|
||||||
|
// values: [
|
||||||
|
// {
|
||||||
|
// displayName: localize('deployAzureSQLDB.NoSupportedEditionLabel', "Supported Edition not selected"),
|
||||||
|
// name: ''
|
||||||
|
// }
|
||||||
|
// ]
|
||||||
|
// });
|
||||||
|
// this._dbSupportedFamilyDropdown.loading = false;
|
||||||
|
// await this.populateVCoreDropdown();
|
||||||
|
// return;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// if (currentSupportedEditionValue.name.length === 0) {
|
||||||
|
// this._dbSupportedFamilyDropdown.updateProperties({
|
||||||
|
// values: [
|
||||||
|
// {
|
||||||
|
// displayName: localize('deployAzureSQLDB.NoSupportedFamiliesLabel', "No database family types found."),
|
||||||
|
// name: ''
|
||||||
|
// }
|
||||||
|
// ],
|
||||||
|
// });
|
||||||
|
// this._dbSupportedFamilyDropdown.loading = false;
|
||||||
|
// await this.populateVCoreDropdown();
|
||||||
|
// return;
|
||||||
|
// } else {
|
||||||
|
// currentSupportedEditionValue.name.sort((a: any, b: any) => (a!.name > b!.name) ? 1 : -1);
|
||||||
|
// }
|
||||||
|
// this.wizard.addDropdownValues(
|
||||||
|
// this._dbSupportedFamilyDropdown,
|
||||||
|
// currentSupportedEditionValue.name.map((value: any) => {
|
||||||
|
// return {
|
||||||
|
// displayName: value.name,
|
||||||
|
// name: value
|
||||||
|
// };
|
||||||
|
// })
|
||||||
|
// );
|
||||||
|
// if (this._dbSupportedFamilyDropdown.value) {
|
||||||
|
// this.wizard.model.databaseFamily = (this._dbSupportedFamilyDropdown.value as any).displayName;
|
||||||
|
// }
|
||||||
|
// this._dbSupportedFamilyDropdown.loading = false;
|
||||||
|
// await this.populateVCoreDropdown();
|
||||||
|
// return;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// private async createVCoreDropdown(view: azdata.ModelView) {
|
||||||
|
// this._dbVCoreDropdown = view.modelBuilder.dropDown().withProperties({
|
||||||
|
// required: true,
|
||||||
|
// }).component();
|
||||||
|
// this._dbVCoreDropdown.onValueChanged(async (value) => {
|
||||||
|
// this.wizard.model.vCoreNumber = value.selected;
|
||||||
|
// });
|
||||||
|
// }
|
||||||
|
|
||||||
|
// private async populateVCoreDropdown() {
|
||||||
|
// this._dbVCoreDropdown.loading = true;
|
||||||
|
// if (!this._dbSupportedFamilyDropdown.values || this._dbSupportedFamilyDropdown.values!.length === 0) {
|
||||||
|
// this._dbVCoreDropdown.updateProperties({
|
||||||
|
// values: []
|
||||||
|
// });
|
||||||
|
// this._dbVCoreDropdown.loading = false;
|
||||||
|
// return;
|
||||||
|
// }
|
||||||
|
// let currentSupportedFamilyValue = this._dbSupportedFamilyDropdown.value as any;
|
||||||
|
// if (!currentSupportedFamilyValue.name && !currentSupportedFamilyValue.name.supportedVcoresValues) {
|
||||||
|
// this._dbVCoreDropdown.updateProperties({
|
||||||
|
// values: [
|
||||||
|
// {
|
||||||
|
// displayName: localize('deployAzureSQLDB.NoSupportedFamilyLabel', "Supported Family not selected"),
|
||||||
|
// name: ''
|
||||||
|
// }
|
||||||
|
// ]
|
||||||
|
// });
|
||||||
|
// this._dbVCoreDropdown.loading = false;
|
||||||
|
// return;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// if (currentSupportedFamilyValue.name.supportedVcoresValues === 0) {
|
||||||
|
// this._dbVCoreDropdown.updateProperties({
|
||||||
|
// values: [
|
||||||
|
// {
|
||||||
|
// displayName: localize('deployAzureSQLDB.NoSupportedVCoreValuesLabel', "No VCore values found."),
|
||||||
|
// name: ''
|
||||||
|
// }
|
||||||
|
// ],
|
||||||
|
// });
|
||||||
|
// this._dbVCoreDropdown.loading = false;
|
||||||
|
// return;
|
||||||
|
// } else {
|
||||||
|
// currentSupportedFamilyValue.name.supportedVcoresValues.sort((a: any, b: any) => (a!.value > b!.value) ? 1 : -1);
|
||||||
|
// }
|
||||||
|
|
||||||
|
// this.wizard.addDropdownValues(
|
||||||
|
// this._dbVCoreDropdown,
|
||||||
|
// currentSupportedFamilyValue.name.supportedVcoresValues.map((value: any) => {
|
||||||
|
// return {
|
||||||
|
// displayName: String(value.value),
|
||||||
|
// name: value.status
|
||||||
|
// };
|
||||||
|
// })
|
||||||
|
// );
|
||||||
|
// for (let i = 0; i < this._dbVCoreDropdown.values!.length; i++) {
|
||||||
|
// let value = this._dbVCoreDropdown.values![i] as azdata.CategoryValue;
|
||||||
|
// if (value.name === 'Default') {
|
||||||
|
// this._dbVCoreDropdown.value = this._dbVCoreDropdown.values![i];
|
||||||
|
// break;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// if (this._dbVCoreDropdown.value) {
|
||||||
|
// this.wizard.model.vCoreNumber = Number((this._dbVCoreDropdown.value as any).displayName);
|
||||||
|
// }
|
||||||
|
// this._dbVCoreDropdown.loading = false;
|
||||||
|
// return;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// private createMaxMemoryText(view: azdata.ModelView) {
|
||||||
|
// this._dbMemoryTextBox = view.modelBuilder.inputBox().withProperties(<azdata.InputBoxProperties>{
|
||||||
|
// inputType: 'number',
|
||||||
|
// max: 1024,
|
||||||
|
// min: 1,
|
||||||
|
// value: '32',
|
||||||
|
// required: true
|
||||||
|
// }).component();
|
||||||
|
|
||||||
|
// this._dbMemoryTextBox.onTextChanged((value) => {
|
||||||
|
// this.wizard.model.storageInGB = value + 'GB';
|
||||||
|
// });
|
||||||
|
// }
|
||||||
|
|
||||||
|
|
||||||
|
protected async validate(): Promise<string> {
|
||||||
|
let errorMessages = [];
|
||||||
|
let serverName = (this._serverGroupDropdown.value as azdata.CategoryValue).name;
|
||||||
|
if (serverName === '') {
|
||||||
|
errorMessages.push(localize('deployAzureSQLDB.NoServerError', "No servers found in current subscription.\nSelect a different subscription containing at least one server"));
|
||||||
|
}
|
||||||
|
// let supportedEditionName = (this._dbSupportedEditionsDropdown.value as azdata.CategoryValue).name;
|
||||||
|
// if (supportedEditionName === '') {
|
||||||
|
// errorMessages.push(localize('deployAzureSQLDB.SupportedEditionError', "No Supported DB Edition found in current server.\nSelect a different server"));
|
||||||
|
// }
|
||||||
|
// let familyName = (this._dbSupportedFamilyDropdown.value as azdata.CategoryValue).name;
|
||||||
|
// if (familyName === '') {
|
||||||
|
// errorMessages.push(localize('deployAzureSQLDB.SupportedFamiliesError', "No Supported Family found in current DB edition.\nSelect a different edition"));
|
||||||
|
// }
|
||||||
|
|
||||||
|
this.wizard.showErrorMessage(errorMessages.join(EOL));
|
||||||
|
return errorMessages.join(EOL);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
/*---------------------------------------------------------------------------------------------
|
||||||
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||||
|
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||||
|
*--------------------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
import { WizardPageBase } from '../../wizardPageBase';
|
||||||
|
import { DeployAzureSQLDBWizard } from '../deployAzureSQLDBWizard';
|
||||||
|
|
||||||
|
export abstract class BasePage extends WizardPageBase<DeployAzureSQLDBWizard> {
|
||||||
|
public abstract initialize(): void;
|
||||||
|
}
|
||||||
@@ -0,0 +1,237 @@
|
|||||||
|
/*---------------------------------------------------------------------------------------------
|
||||||
|
* 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 { EOL } from 'os';
|
||||||
|
import { DeployAzureSQLDBWizard } from '../deployAzureSQLDBWizard';
|
||||||
|
import * as constants from '../constants';
|
||||||
|
import { BasePage } from './basePage';
|
||||||
|
import * as nls from 'vscode-nls';
|
||||||
|
const localize = nls.loadMessageBundle();
|
||||||
|
|
||||||
|
export class DatabaseSettingsPage extends BasePage {
|
||||||
|
|
||||||
|
private _startIpAddressTextRow!: azdata.FlexContainer;
|
||||||
|
private _startIpAddressTextbox!: azdata.InputBoxComponent;
|
||||||
|
private _endIpAddressTextRow!: azdata.FlexContainer;
|
||||||
|
private _endIpAddressTextbox!: azdata.InputBoxComponent;
|
||||||
|
private _firewallRuleNameTextbox!: azdata.InputBoxComponent;
|
||||||
|
private _firewallRuleNameTextRow!: azdata.FlexContainer;
|
||||||
|
private _databaseNameTextbox!: azdata.InputBoxComponent;
|
||||||
|
private _databaseNameTextRow!: azdata.FlexContainer;
|
||||||
|
private _collationTextbox!: azdata.InputBoxComponent;
|
||||||
|
private _collationTextRow!: azdata.FlexContainer;
|
||||||
|
private _IpInfoText!: azdata.TextComponent;
|
||||||
|
|
||||||
|
private _form!: azdata.FormContainer;
|
||||||
|
|
||||||
|
constructor(wizard: DeployAzureSQLDBWizard) {
|
||||||
|
super(
|
||||||
|
constants.DatabaseSettingsPageTitle,
|
||||||
|
'',
|
||||||
|
wizard
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async initialize() {
|
||||||
|
this.pageObject.registerContent(async (view: azdata.ModelView) => {
|
||||||
|
await Promise.all([
|
||||||
|
this.createIpAddressText(view),
|
||||||
|
this.createFirewallNameText(view),
|
||||||
|
this.createDatabaseNameText(view),
|
||||||
|
this.createCollationText(view)
|
||||||
|
]);
|
||||||
|
this._form = view.modelBuilder.formContainer()
|
||||||
|
.withFormItems(
|
||||||
|
[
|
||||||
|
{
|
||||||
|
component: this._databaseNameTextRow
|
||||||
|
},
|
||||||
|
{
|
||||||
|
component: this._collationTextRow
|
||||||
|
},
|
||||||
|
{
|
||||||
|
component: this._firewallRuleNameTextRow
|
||||||
|
},
|
||||||
|
{
|
||||||
|
component: this._startIpAddressTextRow
|
||||||
|
},
|
||||||
|
{
|
||||||
|
component: this._endIpAddressTextRow
|
||||||
|
},
|
||||||
|
{
|
||||||
|
component: this._IpInfoText
|
||||||
|
}
|
||||||
|
],
|
||||||
|
{
|
||||||
|
horizontal: false,
|
||||||
|
componentWidth: '100%'
|
||||||
|
})
|
||||||
|
.withLayout({ width: '100%' })
|
||||||
|
.component();
|
||||||
|
|
||||||
|
return view.initializeModel(this._form);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public async onEnter(): Promise<void> {
|
||||||
|
this.wizard.wizardObject.registerNavigationValidator(async (pcInfo) => {
|
||||||
|
if (pcInfo.newPage < pcInfo.lastPage) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
let errorMessage = await this.validate();
|
||||||
|
|
||||||
|
if (errorMessage !== '') {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public async onLeave(): Promise<void> {
|
||||||
|
this.wizard.wizardObject.registerNavigationValidator((pcInfo) => {
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private createIpAddressText(view: azdata.ModelView) {
|
||||||
|
|
||||||
|
this._IpInfoText = view.modelBuilder.text()
|
||||||
|
.withProperties({
|
||||||
|
value: constants.IpAddressInfoLabel
|
||||||
|
}).component();
|
||||||
|
|
||||||
|
//Start IP Address Section:
|
||||||
|
|
||||||
|
this._startIpAddressTextbox = view.modelBuilder.inputBox().withProperties(<azdata.InputBoxProperties>{
|
||||||
|
inputType: 'text'
|
||||||
|
}).component();
|
||||||
|
|
||||||
|
this._startIpAddressTextbox.onTextChanged((value) => {
|
||||||
|
this.wizard.model.startIpAddress = value;
|
||||||
|
});
|
||||||
|
|
||||||
|
this._startIpAddressTextRow = this.wizard.createFormRowComponent(view, constants.StartIpAddressLabel, '', this._startIpAddressTextbox, true);
|
||||||
|
|
||||||
|
//End IP Address Section:
|
||||||
|
|
||||||
|
this._endIpAddressTextbox = view.modelBuilder.inputBox().withProperties(<azdata.InputBoxProperties>{
|
||||||
|
inputType: 'text'
|
||||||
|
}).component();
|
||||||
|
|
||||||
|
this._endIpAddressTextbox.onTextChanged((value) => {
|
||||||
|
this.wizard.model.endIpAddress = value;
|
||||||
|
});
|
||||||
|
|
||||||
|
this._endIpAddressTextRow = this.wizard.createFormRowComponent(view, constants.EndIpAddressLabel, '', this._endIpAddressTextbox, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
private createFirewallNameText(view: azdata.ModelView) {
|
||||||
|
|
||||||
|
this._firewallRuleNameTextbox = view.modelBuilder.inputBox().component();
|
||||||
|
|
||||||
|
this._firewallRuleNameTextRow = this.wizard.createFormRowComponent(view, constants.FirewallRuleNameLabel, '', this._firewallRuleNameTextbox, true);
|
||||||
|
|
||||||
|
this._firewallRuleNameTextbox.onTextChanged((value) => {
|
||||||
|
this.wizard.model.firewallRuleName = value;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private createDatabaseNameText(view: azdata.ModelView) {
|
||||||
|
|
||||||
|
this._databaseNameTextbox = view.modelBuilder.inputBox().component();
|
||||||
|
|
||||||
|
this._databaseNameTextRow = this.wizard.createFormRowComponent(view, constants.DatabaseNameLabel, '', this._databaseNameTextbox, true);
|
||||||
|
|
||||||
|
this._databaseNameTextbox.onTextChanged((value) => {
|
||||||
|
this.wizard.model.databaseName = value;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private createCollationText(view: azdata.ModelView) {
|
||||||
|
this._collationTextbox = view.modelBuilder.inputBox().withProperties(<azdata.InputBoxProperties>{
|
||||||
|
inputType: 'text',
|
||||||
|
value: 'SQL_Latin1_General_CP1_CI_AS'
|
||||||
|
}).component();
|
||||||
|
|
||||||
|
this._collationTextbox.onTextChanged((value) => {
|
||||||
|
this.wizard.model.databaseCollation = value;
|
||||||
|
});
|
||||||
|
|
||||||
|
this._collationTextRow = this.wizard.createFormRowComponent(view, constants.CollationNameLabel, '', this._collationTextbox, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
protected async validate(): Promise<string> {
|
||||||
|
let errorMessages = [];
|
||||||
|
let ipRegex = /(^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$)/;
|
||||||
|
let startipvalue = this._startIpAddressTextbox.value!;
|
||||||
|
let endipvalue = this._endIpAddressTextbox.value!;
|
||||||
|
let firewallname = this._firewallRuleNameTextbox.value!;
|
||||||
|
let databasename = this._databaseNameTextbox.value!;
|
||||||
|
let collationname = this._collationTextbox.value!;
|
||||||
|
|
||||||
|
if (!(ipRegex.test(startipvalue))) {
|
||||||
|
errorMessages.push(localize('deployAzureSQLDB.DBMinIpInvalidError', "Min Ip address is invalid"));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(ipRegex.test(endipvalue))) {
|
||||||
|
errorMessages.push(localize('deployAzureSQLDB.DBMaxIpInvalidError', "Max Ip address is invalid"));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (/^\d+$/.test(firewallname)) {
|
||||||
|
errorMessages.push(localize('deployAzureSQLDB.DBFirewallOnlyNumericNameError', "Firewall name cannot contain only numbers."));
|
||||||
|
}
|
||||||
|
if (firewallname.length < 1 || firewallname.length > 100) {
|
||||||
|
errorMessages.push(localize('deployAzureSQLDB.DBFirewallLengthError', "Firewall name must be between 1 and 100 characters long."));
|
||||||
|
}
|
||||||
|
if (/[\\\/"\'\[\]:\|<>\+=;,\?\*@\&,]/g.test(firewallname)) {
|
||||||
|
errorMessages.push(localize('deployAzureSQLDB.DBFirewallSpecialCharError', "Firewall name cannot contain special characters \/\"\"[]:|<>+=;,?*@&, ."));
|
||||||
|
}
|
||||||
|
if (/[A-Z]/g.test(firewallname)) {
|
||||||
|
errorMessages.push(localize('deployAzureSQLDB.DBFirewallUpperCaseError', "Upper case letters are not allowed for firealll name"));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (/^\d+$/.test(databasename)) {
|
||||||
|
errorMessages.push(localize('deployAzureSQLDB.DBNameOnlyNumericNameError', "Database name cannot contain only numbers."));
|
||||||
|
}
|
||||||
|
if (databasename.length < 1 || databasename.length > 100) {
|
||||||
|
errorMessages.push(localize('deployAzureSQLDB.DBNameLengthError', "Database name must be between 1 and 100 characters long."));
|
||||||
|
}
|
||||||
|
if (/[\\\/"\'\[\]:\|<>\+=;,\?\*@\&,]/g.test(databasename)) {
|
||||||
|
errorMessages.push(localize('deployAzureSQLDB.DBNameSpecialCharError', "Database name cannot contain special characters \/\"\"[]:|<>+=;,?*@&, ."));
|
||||||
|
}
|
||||||
|
if (await this.databaseNameExists(databasename)) {
|
||||||
|
errorMessages.push(localize('deployAzureSQLDB.DBNameExistsError', "Database name must be unique in the current server."));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (/^\d+$/.test(collationname)) {
|
||||||
|
errorMessages.push(localize('deployAzureSQLDB.DBCollationOnlyNumericNameError', "Collation name cannot contain only numbers."));
|
||||||
|
}
|
||||||
|
if (collationname.length < 1 || collationname.length > 100) {
|
||||||
|
errorMessages.push(localize('deployAzureSQLDB.DBCollationLengthError', "Collation name must be between 1 and 100 characters long."));
|
||||||
|
}
|
||||||
|
if (/[\\\/"\'\[\]:\|<>\+=;,\?\*@\&,]/g.test(collationname)) {
|
||||||
|
errorMessages.push(localize('deployAzureSQLDB.DBCollationSpecialCharError', "Collation name cannot contain special characters \/\"\"[]:|<>+=;,?*@&, ."));
|
||||||
|
}
|
||||||
|
|
||||||
|
this.wizard.showErrorMessage(errorMessages.join(EOL));
|
||||||
|
return errorMessages.join(EOL);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected async databaseNameExists(dbName: string): Promise<boolean> {
|
||||||
|
const url = `https://management.azure.com` +
|
||||||
|
`/subscriptions/${this.wizard.model.azureSubscription}` +
|
||||||
|
`/resourceGroups/${this.wizard.model.azureResouceGroup}` +
|
||||||
|
`/providers/Microsoft.Sql` +
|
||||||
|
`/servers/${this.wizard.model.azureServerName}` +
|
||||||
|
`/databases?api-version=2017-10-01-preview`;
|
||||||
|
|
||||||
|
let response = await this.wizard.getRequest(url, true);
|
||||||
|
|
||||||
|
let nameArray = response.data.value.map((v: any) => { return v.name; });
|
||||||
|
return (nameArray.includes(dbName));
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,225 @@
|
|||||||
|
/*---------------------------------------------------------------------------------------------
|
||||||
|
* 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 { WizardPageBase } from '../../wizardPageBase';
|
||||||
|
import { DeployAzureSQLDBWizard } from '../deployAzureSQLDBWizard';
|
||||||
|
import * as constants from '../constants';
|
||||||
|
import { SectionInfo, LabelPosition, FontWeight, FieldType } from '../../../interfaces';
|
||||||
|
import { createSection } from '../../modelViewUtils';
|
||||||
|
|
||||||
|
export class AzureSQLDBSummaryPage extends WizardPageBase<DeployAzureSQLDBWizard> {
|
||||||
|
|
||||||
|
private formItems: azdata.FormComponent[] = [];
|
||||||
|
private _form!: azdata.FormBuilder;
|
||||||
|
private _view!: azdata.ModelView;
|
||||||
|
|
||||||
|
constructor(wizard: DeployAzureSQLDBWizard) {
|
||||||
|
super(
|
||||||
|
'Summary',
|
||||||
|
'',
|
||||||
|
wizard
|
||||||
|
);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public async initialize() {
|
||||||
|
this.pageObject.registerContent(async (view: azdata.ModelView) => {
|
||||||
|
this._view = view;
|
||||||
|
this._form = view.modelBuilder.formContainer();
|
||||||
|
return view.initializeModel(this._form!.withLayout({ width: '100%' }).component());
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public async onEnter(): Promise<void> {
|
||||||
|
|
||||||
|
this.formItems.forEach(item => {
|
||||||
|
this._form.removeFormItem(item);
|
||||||
|
});
|
||||||
|
|
||||||
|
this.formItems = [];
|
||||||
|
|
||||||
|
let model = this.wizard.model;
|
||||||
|
|
||||||
|
const labelWidth = '150px';
|
||||||
|
const inputWidth = '400px';
|
||||||
|
const fieldHeight = '20px';
|
||||||
|
|
||||||
|
const auzreSettingSection: SectionInfo = {
|
||||||
|
labelPosition: LabelPosition.Left,
|
||||||
|
labelWidth: labelWidth,
|
||||||
|
inputWidth: inputWidth,
|
||||||
|
fieldHeight: fieldHeight,
|
||||||
|
spaceBetweenFields: '0',
|
||||||
|
title: constants.AzureSettingsSummaryPageTitle,
|
||||||
|
fields: [
|
||||||
|
{
|
||||||
|
type: FieldType.ReadonlyText,
|
||||||
|
label: constants.AzureAccountDropdownLabel,
|
||||||
|
defaultValue: model.azureAccount.displayInfo.displayName,
|
||||||
|
labelCSSStyles: { fontWeight: FontWeight.Bold }
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: FieldType.ReadonlyText,
|
||||||
|
label: constants.AzureAccountSubscriptionDropdownLabel,
|
||||||
|
defaultValue: model.azureSubscriptionDisplayName,
|
||||||
|
labelCSSStyles: { fontWeight: FontWeight.Bold }
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: FieldType.ReadonlyText,
|
||||||
|
label: constants.AzureAccountResourceGroupDropdownLabel,
|
||||||
|
defaultValue: model.azureResouceGroup,
|
||||||
|
labelCSSStyles: { fontWeight: FontWeight.Bold }
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: FieldType.ReadonlyText,
|
||||||
|
label: constants.AzureAccountDatabaseServersDropdownLabel,
|
||||||
|
defaultValue: model.azureServerName,
|
||||||
|
labelCSSStyles: { fontWeight: FontWeight.Bold }
|
||||||
|
}
|
||||||
|
]
|
||||||
|
};
|
||||||
|
|
||||||
|
// const databaseHardwareSettingSection: SectionInfo = { //@todo alma1 9/8/2020 section used for upcoming database hardware creation feature.
|
||||||
|
// labelPosition: LabelPosition.Left,
|
||||||
|
// labelWidth: labelWidth,
|
||||||
|
// inputWidth: inputWidth,
|
||||||
|
// fieldHeight: fieldHeight,
|
||||||
|
// spaceBetweenFields: '0',
|
||||||
|
// title: constants.DatabaseHardwareInfoLabel,
|
||||||
|
// fields: [
|
||||||
|
// {
|
||||||
|
// type: FieldType.ReadonlyText,
|
||||||
|
// label: constants.DatabaseSupportedEditionsDropdownLabel,
|
||||||
|
// defaultValue: model.databaseEdition,
|
||||||
|
// labelCSSStyles: { fontWeight: FontWeight.Bold }
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// type: FieldType.ReadonlyText,
|
||||||
|
// label: constants.DatabaseSupportedFamilyDropdownLabel,
|
||||||
|
// defaultValue: model.databaseFamily,
|
||||||
|
// labelCSSStyles: { fontWeight: FontWeight.Bold }
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// type: FieldType.ReadonlyText,
|
||||||
|
// label: constants.DatabaseVCoreNumberDropdownLabel,
|
||||||
|
// defaultValue: String(model.vCoreNumber),
|
||||||
|
// labelCSSStyles: { fontWeight: FontWeight.Bold }
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// type: FieldType.ReadonlyText,
|
||||||
|
// label: constants.DatabaseMaxMemorySummaryTextLabel,
|
||||||
|
// defaultValue: model.storageInGB,
|
||||||
|
// labelCSSStyles: { fontWeight: FontWeight.Bold }
|
||||||
|
// }
|
||||||
|
// ]
|
||||||
|
// };
|
||||||
|
|
||||||
|
const databaseSettingSection: SectionInfo = {
|
||||||
|
labelPosition: LabelPosition.Left,
|
||||||
|
labelWidth: labelWidth,
|
||||||
|
inputWidth: inputWidth,
|
||||||
|
fieldHeight: fieldHeight,
|
||||||
|
title: constants.DatabaseSettingsPageTitle,
|
||||||
|
fields: [
|
||||||
|
{
|
||||||
|
type: FieldType.ReadonlyText,
|
||||||
|
label: constants.DatabaseNameLabel,
|
||||||
|
defaultValue: model.databaseName,
|
||||||
|
labelCSSStyles: { fontWeight: FontWeight.Bold }
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: FieldType.ReadonlyText,
|
||||||
|
label: constants.CollationNameSummaryLabel,
|
||||||
|
defaultValue: model.databaseCollation,
|
||||||
|
labelCSSStyles: { fontWeight: FontWeight.Bold }
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: FieldType.ReadonlyText,
|
||||||
|
label: constants.FirewallRuleNameLabel,
|
||||||
|
defaultValue: model.firewallRuleName,
|
||||||
|
labelCSSStyles: { fontWeight: FontWeight.Bold }
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: FieldType.ReadonlyText,
|
||||||
|
label: constants.StartIpAddressShortLabel,
|
||||||
|
defaultValue: model.startIpAddress,
|
||||||
|
labelCSSStyles: { fontWeight: FontWeight.Bold }
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: FieldType.ReadonlyText,
|
||||||
|
label: constants.EndIpAddressShortLabel,
|
||||||
|
defaultValue: model.endIpAddress,
|
||||||
|
labelCSSStyles: { fontWeight: FontWeight.Bold }
|
||||||
|
}
|
||||||
|
]
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
const createSectionFunc = async (sectionInfo: SectionInfo): Promise<azdata.FormComponent> => {
|
||||||
|
return {
|
||||||
|
title: '',
|
||||||
|
component: await createSection({
|
||||||
|
container: this.wizard.wizardObject,
|
||||||
|
inputComponents: {},
|
||||||
|
sectionInfo: sectionInfo,
|
||||||
|
view: this._view,
|
||||||
|
onNewDisposableCreated: () => { },
|
||||||
|
onNewInputComponentCreated: () => { },
|
||||||
|
onNewValidatorCreated: () => { },
|
||||||
|
toolsService: this.wizard.toolsService
|
||||||
|
})
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
const azureSection = await createSectionFunc(auzreSettingSection);
|
||||||
|
//const databaseHardwareSection = await createSectionFunc(databaseHardwareSettingSection); //@todo alma1 9/8/2020 used for upcoming database hardware creation feature.
|
||||||
|
const databaseSection = await createSectionFunc(databaseSettingSection);
|
||||||
|
|
||||||
|
this.formItems.push(azureSection, /*databaseHardwareSection,*/ databaseSection);
|
||||||
|
this._form.addFormItems(this.formItems);
|
||||||
|
|
||||||
|
this.wizard.wizardObject.registerNavigationValidator((pcInfo) => {
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public async onLeave(): Promise<void> {
|
||||||
|
this.wizard.wizardObject.registerNavigationValidator((pcInfo) => {
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public createSummaryRow(view: azdata.ModelView, title: string, textComponent: azdata.TextComponent): azdata.FlexContainer {
|
||||||
|
|
||||||
|
const labelText = view.modelBuilder.text()
|
||||||
|
.withProperties<azdata.TextComponentProperties>(
|
||||||
|
{
|
||||||
|
value: title,
|
||||||
|
width: '250px',
|
||||||
|
})
|
||||||
|
.component();
|
||||||
|
|
||||||
|
labelText.updateCssStyles({
|
||||||
|
'font-weight': '400',
|
||||||
|
'font-size': '13px',
|
||||||
|
});
|
||||||
|
|
||||||
|
const flexContainer = view.modelBuilder.flexContainer()
|
||||||
|
.withLayout(
|
||||||
|
{
|
||||||
|
flexFlow: 'row',
|
||||||
|
alignItems: 'center',
|
||||||
|
})
|
||||||
|
.withItems(
|
||||||
|
[labelText, textComponent],
|
||||||
|
{
|
||||||
|
CSSStyles: { 'margin-right': '5px' }
|
||||||
|
})
|
||||||
|
.component();
|
||||||
|
|
||||||
|
return flexContainer;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -274,9 +274,6 @@ export class ResourceTypePickerDialog extends DialogBase {
|
|||||||
private selectResourceType(resourceType: ResourceType): void {
|
private selectResourceType(resourceType: ResourceType): void {
|
||||||
this._currentResourceTypeDisposables.forEach(disposable => disposable.dispose());
|
this._currentResourceTypeDisposables.forEach(disposable => disposable.dispose());
|
||||||
this._selectedResourceType = resourceType;
|
this._selectedResourceType = resourceType;
|
||||||
//handle special case when resource type has different OK button.
|
|
||||||
this._dialogObject.okButton.label = this._selectedResourceType.okButtonText || loc.select;
|
|
||||||
|
|
||||||
this._agreementCheckboxChecked = false;
|
this._agreementCheckboxChecked = false;
|
||||||
this._agreementContainer.clearItems();
|
this._agreementContainer.clearItems();
|
||||||
if (resourceType.agreement) {
|
if (resourceType.agreement) {
|
||||||
@@ -299,15 +296,26 @@ export class ResourceTypePickerDialog extends DialogBase {
|
|||||||
ariaLabel: option.displayName
|
ariaLabel: option.displayName
|
||||||
}).component();
|
}).component();
|
||||||
|
|
||||||
this._currentResourceTypeDisposables.push(optionSelectBox.onValueChanged(() => { this.updateToolsDisplayTable(); }));
|
this._currentResourceTypeDisposables.push(optionSelectBox.onValueChanged(() => {
|
||||||
|
this.updateOkButtonText();
|
||||||
|
this.updateToolsDisplayTable();
|
||||||
|
}));
|
||||||
|
|
||||||
this._optionDropDownMap.set(option.name, optionSelectBox);
|
this._optionDropDownMap.set(option.name, optionSelectBox);
|
||||||
const row = this._view.modelBuilder.flexContainer().withItems([optionLabel, optionSelectBox], { flex: '0 0 auto', CSSStyles: { 'margin-right': '20px' } }).withLayout({ flexFlow: 'row', alignItems: 'center' }).component();
|
const row = this._view.modelBuilder.flexContainer().withItems([optionLabel, optionSelectBox], { flex: '0 0 auto', CSSStyles: { 'margin-right': '20px' } }).withLayout({ flexFlow: 'row', alignItems: 'center' }).component();
|
||||||
this._optionsContainer.addItem(row);
|
this._optionsContainer.addItem(row);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
this.updateOkButtonText();
|
||||||
this.updateToolsDisplayTable();
|
this.updateToolsDisplayTable();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private updateOkButtonText(): void {
|
||||||
|
//handle special case when resource type has different OK button.
|
||||||
|
let text = this.getCurrentOkText();
|
||||||
|
this._dialogObject.okButton.label = text || loc.select;
|
||||||
|
}
|
||||||
|
|
||||||
private updateToolsDisplayTable(): void {
|
private updateToolsDisplayTable(): void {
|
||||||
this.toolRefreshTimestamp = new Date().getTime();
|
this.toolRefreshTimestamp = new Date().getTime();
|
||||||
const currentRefreshTimestamp = this.toolRefreshTimestamp;
|
const currentRefreshTimestamp = this.toolRefreshTimestamp;
|
||||||
@@ -482,6 +490,17 @@ export class ResourceTypePickerDialog extends DialogBase {
|
|||||||
return this._selectedResourceType.getProvider(options)!;
|
return this._selectedResourceType.getProvider(options)!;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private getCurrentOkText(): string {
|
||||||
|
const options: { option: string, value: string }[] = [];
|
||||||
|
|
||||||
|
this._optionDropDownMap.forEach((selectBox, option) => {
|
||||||
|
let selectedValue: azdata.CategoryValue = selectBox.value as azdata.CategoryValue;
|
||||||
|
options.push({ option: option, value: selectedValue.name });
|
||||||
|
});
|
||||||
|
|
||||||
|
return this._selectedResourceType.getOkButtonText(options)!;
|
||||||
|
}
|
||||||
|
|
||||||
protected async onComplete(): Promise<void> {
|
protected async onComplete(): Promise<void> {
|
||||||
this.toolsService.toolsForCurrentProvider = this._tools;
|
this.toolsService.toolsForCurrentProvider = this._tools;
|
||||||
this.resourceTypeService.startDeployment(this.getCurrentProvider());
|
this.resourceTypeService.startDeployment(this.getCurrentProvider());
|
||||||
|
|||||||
Reference in New Issue
Block a user