From 147ee53e3533e536a85bc4bf36af52f11bdcc35f Mon Sep 17 00:00:00 2001 From: Charles Gagnon Date: Wed, 9 Dec 2020 16:28:43 -0800 Subject: [PATCH] Revert "Added Accounts and Database Backup Page to Migration wizard (#13548)" (#13742) This reverts commit e1690055712c48fb860fdcc1350c72f07440f186. --- extensions/azurecore/package.json | 1 - .../src/azureResource/azure-resource.d.ts | 9 +- .../azurecore/src/azureResource/utils.ts | 204 +---- extensions/azurecore/src/azurecore.d.ts | 20 +- extensions/azurecore/src/extension.ts | 42 +- .../azurecore/src/localizedConstants.ts | 7 - extensions/azurecore/yarn.lock | 97 +-- extensions/machine-learning/src/test/stubs.ts | 25 +- extensions/sql-migration/src/api/azure.ts | 45 +- .../src/models/migrationWizardPage.ts | 2 +- .../sql-migration/src/models/stateMachine.ts | 59 -- .../sql-migration/src/models/strings.ts | 51 -- .../src/wizard/accountsSelectionPage.ts | 106 --- .../src/wizard/databaseBackupPage.ts | 702 ------------------ .../src/wizard/wizardController.ts | 7 +- 15 files changed, 23 insertions(+), 1354 deletions(-) delete mode 100644 extensions/sql-migration/src/wizard/accountsSelectionPage.ts delete mode 100644 extensions/sql-migration/src/wizard/databaseBackupPage.ts diff --git a/extensions/azurecore/package.json b/extensions/azurecore/package.json index cba12a8907..cd1711d7b3 100644 --- a/extensions/azurecore/package.json +++ b/extensions/azurecore/package.json @@ -321,7 +321,6 @@ }, "dependencies": { "@azure/arm-resourcegraph": "^2.0.0", - "@azure/arm-storage": "^15.1.0", "@azure/arm-subscriptions": "1.0.0", "axios": "^0.19.2", "qs": "^6.9.1", diff --git a/extensions/azurecore/src/azureResource/azure-resource.d.ts b/extensions/azurecore/src/azureResource/azure-resource.d.ts index 83db7c6e42..2c0d41d8d2 100644 --- a/extensions/azurecore/src/azureResource/azure-resource.d.ts +++ b/extensions/azurecore/src/azureResource/azure-resource.d.ts @@ -6,7 +6,6 @@ declare module 'azureResource' { import { TreeDataProvider } from 'vscode'; import { DataProvider, Account, TreeItem } from 'azdata'; - import { FileShareItem, ListContainerItem } from '@azure/arm-storage/esm/models'; export namespace azureResource { export const enum AzureResourceType { @@ -19,8 +18,7 @@ declare module 'azureResource' { kustoClusters = 'microsoft.kusto/clusters', azureArcPostgresServer = 'microsoft.azuredata/postgresinstances', postgresServer = 'microsoft.dbforpostgresql/servers', - azureArcService = 'microsoft.azuredata/datacontrollers', - storageAccount = 'microsoft.storage/storageaccounts', + azureArcService = 'microsoft.azuredata/datacontrollers' } export interface IAzureResourceProvider extends DataProvider { @@ -77,10 +75,7 @@ declare module 'azureResource' { fullName: string; defaultDatabaseName: string; } - export interface BlobContainer extends ListContainerItem { - } - export interface FileShare extends FileShareItem { - } + } } diff --git a/extensions/azurecore/src/azureResource/utils.ts b/extensions/azurecore/src/azureResource/utils.ts index 5e323071b3..0f31689055 100644 --- a/extensions/azurecore/src/azureResource/utils.ts +++ b/extensions/azurecore/src/azureResource/utils.ts @@ -5,18 +5,14 @@ import { ResourceGraphClient } from '@azure/arm-resourcegraph'; import { TokenCredentials } from '@azure/ms-rest-js'; -import axios, { AxiosRequestConfig } from 'axios'; import * as azdata from 'azdata'; -import { HttpGetRequestResult, GetResourceGroupsResult, GetSubscriptionsResult, ResourceQueryResult, GetBlobContainersResult, GetFileSharesResult } from 'azurecore'; +import { GetResourceGroupsResult, GetSubscriptionsResult, ResourceQueryResult } from 'azurecore'; import { azureResource } from 'azureResource'; -import { EOL } from 'os'; import * as nls from 'vscode-nls'; import { AppContext } from '../appContext'; -import { invalidAzureAccount, invalidTenant, unableToFetchTokenError } from '../localizedConstants'; import { AzureResourceServiceNames } from './constants'; import { IAzureResourceSubscriptionFilterService, IAzureResourceSubscriptionService } from './interfaces'; import { AzureResourceGroupService } from './providers/resourceGroup/resourceGroupService'; -import { StorageManagementClient } from '@azure/arm-storage'; const localize = nls.loadMessageBundle(); @@ -110,7 +106,7 @@ export function equals(one: any, other: any): boolean { export async function getResourceGroups(appContext: AppContext, account?: azdata.Account, subscription?: azureResource.AzureResourceSubscription, ignoreErrors: boolean = false): Promise { const result: GetResourceGroupsResult = { resourceGroups: [], errors: [] }; if (!account?.properties?.tenants || !Array.isArray(account.properties.tenants) || !subscription) { - const error = new Error(invalidAzureAccount); + const error = new Error(localize('azure.accounts.getResourceGroups.invalidParamsError', "Invalid account or subscription")); if (!ignoreErrors) { throw error; } @@ -150,7 +146,7 @@ export async function runResourceQuery> { const result: ResourceQueryResult = { resources: [], errors: [] }; if (!account?.properties?.tenants || !Array.isArray(account.properties.tenants)) { - const error = new Error(invalidAzureAccount); + const error = new Error(localize('azure.accounts.runResourceQuery.errors.invalidAccount', "Invalid account")); if (!ignoreErrors) { throw error; } @@ -161,7 +157,7 @@ export async function runResourceQuery { if (!subscription.tenant) { - const error = new Error(invalidTenant); + const error = new Error(localize('azure.accounts.runResourceQuery.errors.noTenantSpecifiedForSubscription', "Invalid tenant for subscription")); if (!ignoreErrors) { throw error; } @@ -192,7 +188,7 @@ export async function runResourceQuery { const result: GetSubscriptionsResult = { subscriptions: [], errors: [] }; if (!account?.properties?.tenants || !Array.isArray(account.properties.tenants)) { - const error = new Error(invalidAzureAccount); + const error = new Error(localize('azure.accounts.getSubscriptions.invalidParamsError', "Invalid account")); if (!ignoreErrors) { throw error; } @@ -265,7 +261,7 @@ export async function getSubscriptions(appContext: AppContext, account?: azdata. export async function getSelectedSubscriptions(appContext: AppContext, account?: azdata.Account, ignoreErrors: boolean = false): Promise { const result: GetSubscriptionsResult = { subscriptions: [], errors: [] }; if (!account?.properties?.tenants || !Array.isArray(account.properties.tenants)) { - const error = new Error(invalidAzureAccount); + const error = new Error(localize('azure.accounts.getSelectedSubscriptions.invalidParamsError', "Invalid account")); if (!ignoreErrors) { throw error; } @@ -288,189 +284,3 @@ export async function getSelectedSubscriptions(appContext: AppContext, account?: } return result; } - -/** - * makes a GET request to Azure REST apis. Currently, it only supports GET ARM queries. - */ -export async function makeHttpGetRequest(account: azdata.Account, subscription: azureResource.AzureResourceSubscription, ignoreErrors: boolean = false, url: string): Promise { - const result: HttpGetRequestResult = { response: {}, errors: [] }; - - if (!account?.properties?.tenants || !Array.isArray(account.properties.tenants)) { - const error = new Error(invalidAzureAccount); - if (!ignoreErrors) { - throw error; - } - result.errors.push(error); - } - - if (!subscription.tenant) { - const error = new Error(invalidTenant); - if (!ignoreErrors) { - throw error; - } - result.errors.push(error); - } - if (result.errors.length > 0) { - return result; - } - - let securityToken: { token: string, tokenType?: string }; - try { - securityToken = await azdata.accounts.getAccountSecurityToken( - account, - subscription.tenant!, - azdata.AzureResource.ResourceManagement - ); - } catch (err) { - console.error(err); - const error = new Error(unableToFetchTokenError(subscription.tenant)); - if (!ignoreErrors) { - throw error; - } - result.errors.push(error); - } - if (result.errors.length > 0) { - return result; - } - - const config: AxiosRequestConfig = { - headers: { - 'Content-Type': 'application/json', - 'Authorization': `Bearer ${securityToken.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}`); - } - const error = new Error(errorMessage.join(EOL)); - if (!ignoreErrors) { - throw error; - } - result.errors.push(error); - } - - result.response = response; - - return result; -} - -export async function getBlobContainers(account: azdata.Account, subscription: azureResource.AzureResourceSubscription, storageAccounts: azureResource.AzureGraphResource, ignoreErrors: boolean): Promise { - let result: GetBlobContainersResult = { blobContainer: undefined, errors: [] }; - - if (!account?.properties?.tenants || !Array.isArray(account.properties.tenants)) { - const error = new Error(invalidAzureAccount); - if (!ignoreErrors) { - throw error; - } - result.errors.push(error); - } - - if (!subscription.tenant) { - const error = new Error(invalidTenant); - if (!ignoreErrors) { - throw error; - } - result.errors.push(error); - } - if (result.errors.length > 0) { - return result; - } - - let securityToken: { token: string, tokenType?: string }; - let credential: TokenCredentials; - try { - securityToken = await azdata.accounts.getAccountSecurityToken( - account, - subscription.tenant!, - azdata.AzureResource.ResourceManagement - ); - const token = securityToken.token; - const tokenType = securityToken.tokenType; - credential = new TokenCredentials(token, tokenType); - - } catch (err) { - console.error(err); - const error = new Error(unableToFetchTokenError(subscription.tenant)); - if (!ignoreErrors) { - throw error; - } - result.errors.push(error); - } - - try { - const client = new StorageManagementClient(credential, subscription.id); - result.blobContainer = await client.blobContainers.list(storageAccounts.resourceGroup, storageAccounts.name); - } catch (err) { - console.error(err); - if (!ignoreErrors) { - throw err; - } - result.errors.push(err); - } - return result; -} - -export async function getFileShares(account: azdata.Account, subscription: azureResource.AzureResourceSubscription, storageAccounts: azureResource.AzureGraphResource, ignoreErrors: boolean): Promise { - let result: GetFileSharesResult = { fileShares: undefined, errors: [] }; - - if (!account?.properties?.tenants || !Array.isArray(account.properties.tenants)) { - const error = new Error(invalidAzureAccount); - if (!ignoreErrors) { - throw error; - } - result.errors.push(error); - } - - if (!subscription.tenant) { - const error = new Error(invalidTenant); - if (!ignoreErrors) { - throw error; - } - result.errors.push(error); - } - if (result.errors.length > 0) { - return result; - } - - let securityToken: { token: string, tokenType?: string }; - let credential: TokenCredentials; - try { - securityToken = await azdata.accounts.getAccountSecurityToken( - account, - subscription.tenant!, - azdata.AzureResource.ResourceManagement - ); - const token = securityToken.token; - const tokenType = securityToken.tokenType; - credential = new TokenCredentials(token, tokenType); - - } catch (err) { - console.error(err); - const error = new Error(unableToFetchTokenError(subscription.tenant)); - if (!ignoreErrors) { - throw error; - } - result.errors.push(error); - } - - try { - const client = new StorageManagementClient(credential, subscription.id); - result.fileShares = await client.fileShares.list(storageAccounts.resourceGroup, storageAccounts.name); - } catch (err) { - console.error(err); - if (!ignoreErrors) { - throw err; - } - result.errors.push(err); - } - return result; -} - diff --git a/extensions/azurecore/src/azurecore.d.ts b/extensions/azurecore/src/azurecore.d.ts index 3636283534..b56be27607 100644 --- a/extensions/azurecore/src/azurecore.d.ts +++ b/extensions/azurecore/src/azurecore.d.ts @@ -6,8 +6,6 @@ declare module 'azurecore' { import * as azdata from 'azdata'; import { azureResource } from 'azureResource'; - import { BlobContainersListResponse, FileSharesListResponse } from '@azure/arm-storage/esm/models'; - /** * Covers defining what the azurecore extension exports to other extensions * @@ -68,14 +66,8 @@ declare module 'azurecore' { } export interface IExtension { - getSubscriptions(account?: azdata.Account, ignoreErrors?: boolean, selectedOnly?: boolean): Promise; - getResourceGroups(account?: azdata.Account, subscription?: azureResource.AzureResourceSubscription, ignoreErrors?: boolean): Promise; - getSqlManagedInstances(account: azdata.Account, subscriptions: azureResource.AzureResourceSubscription[], ignoreErrors?: boolean): Promise; - getSqlServers(account: azdata.Account, subscriptions: azureResource.AzureResourceSubscription[], ignoreErrors?: boolean): Promise; - getSqlVMServers(account: azdata.Account, subscriptions: azureResource.AzureResourceSubscription[], ignoreErrors?: boolean): Promise; - getStorageAccounts(account: azdata.Account, subscriptions: azureResource.AzureResourceSubscription[], ignoreErrors?: boolean): Promise; - getBlobContainers(account: azdata.Account, subscription: azureResource.AzureResourceSubscription, storageAccount: azureResource.AzureGraphResource, ignoreErrors?: boolean): Promise; - getFileShares(account: azdata.Account, subscription: azureResource.AzureResourceSubscription, storageAccount: azureResource.AzureGraphResource, ignoreErrors?: boolean): Promise; + getSubscriptions(account?: azdata.Account, ignoreErrors?: boolean, selectedOnly?: boolean): Thenable; + getResourceGroups(account?: azdata.Account, subscription?: azureResource.AzureResourceSubscription, ignoreErrors?: boolean): Thenable; /** * Converts a region value (@see AzureRegion) into the localized Display Name * @param region The region value @@ -84,18 +76,10 @@ declare module 'azurecore' { provideResources(): azureResource.IAzureResourceProvider[]; runGraphQuery(account: azdata.Account, subscriptions: azureResource.AzureResourceSubscription[], ignoreErrors: boolean, query: string): Promise>; - makeHttpGetRequest(account: azdata.Account, subscription: azureResource.AzureResourceSubscription, ignoreErrors: boolean, url: string): Promise; } export type GetSubscriptionsResult = { subscriptions: azureResource.AzureResourceSubscription[], errors: Error[] }; export type GetResourceGroupsResult = { resourceGroups: azureResource.AzureResourceResourceGroup[], errors: Error[] }; - export type GetSqlManagedInstancesResult = { resources: azureResource.AzureGraphResource[], errors: Error[] }; - export type GetSqlServersResult = {resources: azureResource.AzureGraphResource[], errors: Error[]}; - export type GetSqlVMServersResult = {resources: azureResource.AzureGraphResource[], errors: Error[]}; - export type GetStorageAccountResult = {resources: azureResource.AzureGraphResource[], errors: Error[]}; - export type GetBlobContainersResult = {blobContainer: BlobContainersListResponse | undefined, errors: Error[]}; - export type GetFileSharesResult = {fileShares: FileSharesListResponse | undefined, errors: Error[]}; export type ResourceQueryResult = { resources: T[], errors: Error[] }; - export type HttpGetRequestResult = { response: any, errors: Error[] }; } diff --git a/extensions/azurecore/src/extension.ts b/extensions/azurecore/src/extension.ts index b892cc4701..55c53cf80b 100644 --- a/extensions/azurecore/src/extension.ts +++ b/extensions/azurecore/src/extension.ts @@ -141,12 +141,12 @@ export async function activate(context: vscode.ExtensionContext): Promise { + getSubscriptions(account?: azdata.Account, ignoreErrors?: boolean, selectedOnly: boolean = false): Thenable { return selectedOnly ? azureResourceUtils.getSelectedSubscriptions(appContext, account, ignoreErrors) : azureResourceUtils.getSubscriptions(appContext, account, ignoreErrors); }, - getResourceGroups(account?: azdata.Account, subscription?: azureResource.AzureResourceSubscription, ignoreErrors?: boolean): Promise { return azureResourceUtils.getResourceGroups(appContext, account, subscription, ignoreErrors); }, + getResourceGroups(account?: azdata.Account, subscription?: azureResource.AzureResourceSubscription, ignoreErrors?: boolean): Thenable { return azureResourceUtils.getResourceGroups(appContext, account, subscription, ignoreErrors); }, provideResources(): azureResource.IAzureResourceProvider[] { const arcFeaturedEnabled = vscode.workspace.getConfiguration(constants.extensionConfigSectionName).get('enableArcFeatures'); const providers: azureResource.IAzureResourceProvider[] = [ @@ -164,50 +164,12 @@ export async function activate(context: vscode.ExtensionContext): Promise { - return azureResourceUtils.runResourceQuery(account, subscriptions, ignoreErrors, `where type == "${azureResource.AzureResourceType.sqlManagedInstance}"`); - }, - getSqlServers(account: azdata.Account, - subscriptions: azureResource.AzureResourceSubscription[], - ignoreErrors: boolean): Promise { - return azureResourceUtils.runResourceQuery(account, subscriptions, ignoreErrors, `where type == "${azureResource.AzureResourceType.sqlServer}"`); - }, - getSqlVMServers(account: azdata.Account, - subscriptions: azureResource.AzureResourceSubscription[], - ignoreErrors: boolean): Promise { - return azureResourceUtils.runResourceQuery(account, subscriptions, ignoreErrors, `where type == "${azureResource.AzureResourceType.virtualMachines}" and properties.storageProfile.imageReference.publisher == "microsoftsqlserver"`); - }, - getStorageAccounts(account: azdata.Account, - subscriptions: azureResource.AzureResourceSubscription[], - ignoreErrors: boolean): Promise { - return azureResourceUtils.runResourceQuery(account, subscriptions, ignoreErrors, `where type == "${azureResource.AzureResourceType.storageAccount}"`); - }, - getBlobContainers(account: azdata.Account, - subscription: azureResource.AzureResourceSubscription, - storageAccount: azureResource.AzureGraphResource, - ignoreErrors: boolean): Promise { - return azureResourceUtils.getBlobContainers(account, subscription, storageAccount, ignoreErrors); - }, - getFileShares(account: azdata.Account, - subscription: azureResource.AzureResourceSubscription, - storageAccount: azureResource.AzureGraphResource, - ignoreErrors: boolean): Promise { - return azureResourceUtils.getFileShares(account, subscription, storageAccount, ignoreErrors); - }, getRegionDisplayName: utils.getRegionDisplayName, runGraphQuery(account: azdata.Account, subscriptions: azureResource.AzureResourceSubscription[], ignoreErrors: boolean, query: string): Promise> { return azureResourceUtils.runResourceQuery(account, subscriptions, ignoreErrors, query); - }, - makeHttpGetRequest(account: azdata.Account, - subscription: azureResource.AzureResourceSubscription, - ignoreErrors: boolean, - url: string) { - return azureResourceUtils.makeHttpGetRequest(account, subscription, ignoreErrors, url); } }; } diff --git a/extensions/azurecore/src/localizedConstants.ts b/extensions/azurecore/src/localizedConstants.ts index e92267dc5b..c93afaa91b 100644 --- a/extensions/azurecore/src/localizedConstants.ts +++ b/extensions/azurecore/src/localizedConstants.ts @@ -74,10 +74,3 @@ export const azureArcPostgresServer = localize('azurecore.azureArcPostgres', "Az export const unableToOpenAzureLink = localize('azure.unableToOpenAzureLink', "Unable to open link, missing required values"); export const azureResourcesGridTitle = localize('azure.azureResourcesGridTitle', "Azure Resources (Preview)"); - -// Azure Request Errors -export const invalidAzureAccount = localize('azurecore.invalidAzureAccount', "Invalid account"); -export const invalidTenant = localize('azurecore.invalidTenant', "Invalid tenant for subscription"); -export function unableToFetchTokenError(tenant: string): string { - return localize('azurecore.unableToFetchToken', "Unable to get token for tenant {0}", tenant); -} diff --git a/extensions/azurecore/yarn.lock b/extensions/azurecore/yarn.lock index 155caa0e06..7ece85bb28 100644 --- a/extensions/azurecore/yarn.lock +++ b/extensions/azurecore/yarn.lock @@ -11,15 +11,6 @@ "@azure/ms-rest-js" "^1.8.1" tslib "^1.9.3" -"@azure/arm-storage@^15.1.0": - version "15.1.0" - resolved "https://registry.yarnpkg.com/@azure/arm-storage/-/arm-storage-15.1.0.tgz#fa14b5e532babf39b47c5cffe89de5aa062e1f80" - integrity sha512-IWomHlT7eEnCSMDHH/z5/XyPHhGAIPmWYgHkIyYB2YQt+Af+hWvE1NIwI79Eeiu+Am4U8BKUsXWmWKqDYh0Srg== - dependencies: - "@azure/ms-rest-azure-js" "^2.0.1" - "@azure/ms-rest-js" "^2.0.4" - tslib "^1.10.0" - "@azure/arm-subscriptions@1.0.0": version "1.0.0" resolved "https://registry.yarnpkg.com/@azure/arm-subscriptions/-/arm-subscriptions-1.0.0.tgz#ab65a5cd4d8b8c878ff6621428f29137b84eb1d6" @@ -37,14 +28,6 @@ "@azure/ms-rest-js" "^1.8.10" tslib "^1.9.3" -"@azure/ms-rest-azure-js@^2.0.1": - version "2.0.1" - resolved "https://registry.yarnpkg.com/@azure/ms-rest-azure-js/-/ms-rest-azure-js-2.0.1.tgz#fa1b38f039b3ee48a9e086a88c8a5b5b7776491c" - integrity sha512-5e+A710O7gRFISoV4KI/ZyLQbKmjXxQZ1L8Z/sx7jSUQqmswjTnN4yyIZxs5JzfLVkobU0rXxbi5/LVzaI8QXQ== - dependencies: - "@azure/ms-rest-js" "^2.0.4" - tslib "^1.10.0" - "@azure/ms-rest-js@^1.1.0", "@azure/ms-rest-js@^1.8.1", "@azure/ms-rest-js@^1.8.10": version "1.8.14" resolved "https://registry.yarnpkg.com/@azure/ms-rest-js/-/ms-rest-js-1.8.14.tgz#657fc145db20b6eb3d58d1a2055473aa72eb609d" @@ -59,22 +42,6 @@ uuid "^3.2.1" xml2js "^0.4.19" -"@azure/ms-rest-js@^2.0.4": - version "2.1.0" - resolved "https://registry.yarnpkg.com/@azure/ms-rest-js/-/ms-rest-js-2.1.0.tgz#41bc541984983b5242dfbcf699ea281acd045946" - integrity sha512-4BXLVImYRt+jcUmEJ5LUWglI8RBNVQndY6IcyvQ4U8O4kIXdmlRz3cJdA/RpXf5rKT38KOoTO2T6Z1f6Z1HDBg== - dependencies: - "@types/node-fetch" "^2.3.7" - "@types/tunnel" "0.0.1" - abort-controller "^3.0.0" - form-data "^2.5.0" - node-fetch "^2.6.0" - tough-cookie "^3.0.1" - tslib "^1.10.0" - tunnel "0.0.6" - uuid "^3.3.2" - xml2js "^0.4.19" - "@babel/code-frame@^7.8.3": version "7.8.3" resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.8.3.tgz#33e25903d7481181534e12ec0a25f16b6fcf419e" @@ -308,14 +275,6 @@ resolved "https://registry.yarnpkg.com/@types/mocha/-/mocha-5.2.7.tgz#315d570ccb56c53452ff8638738df60726d5b6ea" integrity sha512-NYrtPht0wGzhwe9+/idPaBB+TqkY9AhTvOLMkThm0IoEfLaiVQZwBwyJ5puCkO3AUCWrmcoePjp2mbFocKy4SQ== -"@types/node-fetch@^2.3.7": - version "2.5.7" - resolved "https://registry.yarnpkg.com/@types/node-fetch/-/node-fetch-2.5.7.tgz#20a2afffa882ab04d44ca786449a276f9f6bbf3c" - integrity sha512-o2WVNf5UhWRkxlf6eq+jMZDu7kjgpgJfl4xVNlvryc95O/6F2ld8ztKX+qu+Rjyet93WAWm5LjeX9H5FGkODvw== - dependencies: - "@types/node" "*" - form-data "^3.0.0" - "@types/node@*": version "13.9.5" resolved "https://registry.yarnpkg.com/@types/node/-/node-13.9.5.tgz#59738bf30b31aea1faa2df7f4a5f55613750cf00" @@ -365,13 +324,6 @@ dependencies: "@types/node" "*" -"@types/tunnel@0.0.1": - version "0.0.1" - resolved "https://registry.yarnpkg.com/@types/tunnel/-/tunnel-0.0.1.tgz#0d72774768b73df26f25df9184273a42da72b19c" - integrity sha512-AOqu6bQu5MSWwYvehMXLukFHnupHrpZ8nvgae5Ggie9UwzDR1CCwoXgSSWNZJuyOlCdfdsWMA5F2LlmvyoTv8A== - dependencies: - "@types/node" "*" - "@types/ws@^6.0.4": version "6.0.4" resolved "https://registry.yarnpkg.com/@types/ws/-/ws-6.0.4.tgz#7797707c8acce8f76d8c34b370d4645b70421ff1" @@ -379,13 +331,6 @@ dependencies: "@types/node" "*" -abort-controller@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/abort-controller/-/abort-controller-3.0.0.tgz#eaf54d53b62bae4138e809ca225c8439a6efb392" - integrity sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg== - dependencies: - event-target-shim "^5.0.0" - ansi-regex@^2.0.0: version "2.1.1" resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df" @@ -521,7 +466,7 @@ color-name@1.1.3: resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" integrity sha1-p9BVi9icQveV3UIyj3QIMcpTvCU= -combined-stream@^1.0.6, combined-stream@^1.0.8: +combined-stream@^1.0.6: version "1.0.8" resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f" integrity sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg== @@ -651,11 +596,6 @@ escape-string-regexp@1.0.5, escape-string-regexp@^1.0.5: resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ= -event-target-shim@^5.0.0: - version "5.0.1" - resolved "https://registry.yarnpkg.com/event-target-shim/-/event-target-shim-5.0.1.tgz#5d4d3ebdf9583d63a5333ce2deb7480ab2b05789" - integrity sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ== - expand-template@^2.0.3: version "2.0.3" resolved "https://registry.yarnpkg.com/expand-template/-/expand-template-2.0.3.tgz#6e14b3fcee0f3a6340ecb57d2e8918692052a47c" @@ -677,15 +617,6 @@ form-data@^2.3.2, form-data@^2.5.0: combined-stream "^1.0.6" mime-types "^2.1.12" -form-data@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/form-data/-/form-data-3.0.0.tgz#31b7e39c85f1355b7139ee0c647cf0de7f83c682" - integrity sha512-CKMFDglpbMi6PyN+brwB9Q/GOw0eAnsrEZDgcsH5Krhz5Od/haKHAX0NmQfha2zPPz0JpWzA7GJHGSnvCRLWsg== - dependencies: - asynckit "^0.4.0" - combined-stream "^1.0.8" - mime-types "^2.1.12" - fs-constants@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/fs-constants/-/fs-constants-1.0.0.tgz#6be0de9be998ce16af8afc24497b9ee9b7ccd9ad" @@ -802,11 +733,6 @@ ini@~1.3.0: resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.5.tgz#eee25f56db1c9ec6085e0c22778083f596abf927" integrity sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw== -ip-regex@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/ip-regex/-/ip-regex-2.1.0.tgz#fa78bf5d2e6913c911ce9f819ee5146bb6d844e9" - integrity sha1-+ni/XS5pE8kRzp+BnuUUa7bYROk= - is-buffer@~1.1.1: version "1.1.6" resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be" @@ -1083,11 +1009,6 @@ node-abi@^2.7.0: dependencies: semver "^5.4.1" -node-fetch@^2.6.0: - version "2.6.1" - resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.1.tgz#045bd323631f76ed2e2b55573394416b639a0052" - integrity sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw== - noop-logger@^0.1.1: version "0.1.1" resolved "https://registry.yarnpkg.com/noop-logger/-/noop-logger-0.1.1.tgz#94a2b1633c4f1317553007d8966fd0e841b6a4c2" @@ -1468,20 +1389,6 @@ tough-cookie@^2.4.3: psl "^1.1.28" punycode "^2.1.1" -tough-cookie@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-3.0.1.tgz#9df4f57e739c26930a018184887f4adb7dca73b2" - integrity sha512-yQyJ0u4pZsv9D4clxO69OEjLWYw+jbgspjTue4lTQZLfV0c5l1VmK2y1JK8E9ahdpltPOaAThPcp5nKPUgSnsg== - dependencies: - ip-regex "^2.1.0" - psl "^1.1.28" - punycode "^2.1.1" - -tslib@^1.10.0: - version "1.14.1" - resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00" - integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg== - tslib@^1.9.2, tslib@^1.9.3: version "1.11.1" resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.11.1.tgz#eb15d128827fbee2841549e171f45ed338ac7e35" @@ -1518,7 +1425,7 @@ util-deprecate@^1.0.1, util-deprecate@~1.0.1: resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" integrity sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8= -uuid@^3.2.1, uuid@^3.3.2: +uuid@^3.2.1: version "3.4.0" resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.4.0.tgz#b23e4358afa8a202fe7a100af1f5f883f02007ee" integrity sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A== diff --git a/extensions/machine-learning/src/test/stubs.ts b/extensions/machine-learning/src/test/stubs.ts index ea6ff847d0..c11c09a166 100644 --- a/extensions/machine-learning/src/test/stubs.ts +++ b/extensions/machine-learning/src/test/stubs.ts @@ -8,34 +8,13 @@ import * as azurecore from 'azurecore'; import { azureResource } from 'azureResource'; export class AzurecoreApiStub implements azurecore.IExtension { - getFileShares(_account: azdata.Account, _subscription: azureResource.AzureResourceSubscription, _storageAccount: azureResource.AzureGraphResource, _ignoreErrors?: boolean): Promise { - throw new Error('Method not implemented.'); - } - getBlobContainers(_account: azdata.Account, _subscription: azureResource.AzureResourceSubscription, _storageAccount: azureResource.AzureGraphResource, _ignoreErrors?: boolean): Promise { - throw new Error('Method not implemented.'); - } - getSqlManagedInstances(_account: azdata.Account, _subscriptions: azureResource.AzureResourceSubscription[], _ignoreErrors?: boolean): Promise { - throw new Error('Method not implemented.'); - } - getSqlServers(_account: azdata.Account, _subscriptions: azureResource.AzureResourceSubscription[], _ignoreErrors?: boolean): Promise { - throw new Error('Method not implemented.'); - } - getSqlVMServers(_account: azdata.Account, _subscriptions: azureResource.AzureResourceSubscription[], _ignoreErrors?: boolean): Promise { - throw new Error('Method not implemented.'); - } - getStorageAccounts(_account: azdata.Account, _subscriptions: azureResource.AzureResourceSubscription[], _ignoreErrors?: boolean): Promise { - throw new Error('Method not implemented.'); - } - makeHttpGetRequest(_account: azdata.Account, _subscription: azureResource.AzureResourceSubscription, _ignoreErrors: boolean, _url: string): Promise { - throw new Error('Method not implemented.'); - } runGraphQuery(_account: azdata.Account, _subscriptions: azureResource.AzureResourceSubscription[], _ignoreErrors: boolean, _query: string): Promise> { throw new Error('Method not implemented.'); } - getSubscriptions(_account?: azdata.Account | undefined, _ignoreErrors?: boolean | undefined, _selectedOnly?: boolean | undefined): Promise { + getSubscriptions(_account?: azdata.Account | undefined, _ignoreErrors?: boolean | undefined, _selectedOnly?: boolean | undefined): Thenable { throw new Error('Method not implemented.'); } - getResourceGroups(_account?: azdata.Account | undefined, _subscription?: azureResource.AzureResourceSubscription | undefined, _ignoreErrors?: boolean | undefined): Promise { + getResourceGroups(_account?: azdata.Account | undefined, _subscription?: azureResource.AzureResourceSubscription | undefined, _ignoreErrors?: boolean | undefined): Thenable { throw new Error('Method not implemented.'); } getRegionDisplayName(_region?: string | undefined): string { diff --git a/extensions/sql-migration/src/api/azure.ts b/extensions/sql-migration/src/api/azure.ts index e33c230cf5..f2fb45ad2a 100644 --- a/extensions/sql-migration/src/api/azure.ts +++ b/extensions/sql-migration/src/api/azure.ts @@ -39,7 +39,7 @@ export type SqlManagedInstance = AzureProduct; export async function getAvailableManagedInstanceProducts(account: azdata.Account, subscription: Subscription): Promise { const api = await getAzureCoreAPI(); - const result = await api.getSqlManagedInstances(account, [subscription], false); + const result = await api.runGraphQuery(account, [subscription], false, `where type == "${azureResource.AzureResourceType.sqlManagedInstance}"`); return result.resources; } @@ -47,7 +47,7 @@ export type SqlServer = AzureProduct; export async function getAvailableSqlServers(account: azdata.Account, subscription: Subscription): Promise { const api = await getAzureCoreAPI(); - const result = await api.getSqlServers(account, [subscription], false); + const result = await api.runGraphQuery(account, [subscription], false, `where type == "${azureResource.AzureResourceType.sqlServer}"`); return result.resources; } @@ -55,45 +55,6 @@ export type SqlVMServer = AzureProduct; export async function getAvailableSqlVMs(account: azdata.Account, subscription: Subscription): Promise { const api = await getAzureCoreAPI(); - const result = await api.getSqlVMServers(account, [subscription], false); + const result = await api.runGraphQuery(account, [subscription], false, `where type == "${azureResource.AzureResourceType.virtualMachines}" and properties.storageProfile.imageReference.publisher == "microsoftsqlserver"`); return result.resources; } - -export type StorageAccount = AzureProduct; -export async function getAvailableStorageAccounts(account: azdata.Account, subscription: Subscription): Promise { - const api = await getAzureCoreAPI(); - const result = await api.getStorageAccounts(account, [subscription], false); - sortResourceArrayByName(result.resources); - return result.resources; -} - -export async function getFileShares(account: azdata.Account, subscription: Subscription, storageAccount: StorageAccount): Promise { - const api = await getAzureCoreAPI(); - let result = await api.getFileShares(account, subscription, storageAccount, true); - let fileShares = result.fileShares; - sortResourceArrayByName(fileShares!); - return fileShares!; -} - -export async function getBlobContainers(account: azdata.Account, subscription: Subscription, storageAccount: StorageAccount): Promise { - const api = await getAzureCoreAPI(); - let result = await api.getBlobContainers(account, subscription, storageAccount, true); - let blobContainers = result.blobContainer; - sortResourceArrayByName(blobContainers!); - return blobContainers!; -} - -function sortResourceArrayByName(resourceArray: AzureProduct[] | azureResource.FileShare[] | azureResource.BlobContainer[] | undefined): void { - if (!resourceArray) { - return; - } - resourceArray.sort((a: AzureProduct | azureResource.BlobContainer | azureResource.FileShare, b: AzureProduct | azureResource.BlobContainer | azureResource.FileShare) => { - if (a.name! < b.name!) { - return -1; - } - if (a.name! > b.name!) { - return 1; - } - return 0; - }); -} diff --git a/extensions/sql-migration/src/models/migrationWizardPage.ts b/extensions/sql-migration/src/models/migrationWizardPage.ts index fbbf9f4308..4faf988263 100644 --- a/extensions/sql-migration/src/models/migrationWizardPage.ts +++ b/extensions/sql-migration/src/models/migrationWizardPage.ts @@ -7,7 +7,7 @@ import * as azdata from 'azdata'; import { MigrationStateModel, StateChangeEvent } from './stateMachine'; export abstract class MigrationWizardPage { constructor( - protected readonly wizard: azdata.window.Wizard, + private readonly wizard: azdata.window.Wizard, protected readonly wizardPage: azdata.window.WizardPage, protected readonly migrationStateModel: MigrationStateModel ) { } diff --git a/extensions/sql-migration/src/models/stateMachine.ts b/extensions/sql-migration/src/models/stateMachine.ts index 7474a037ab..66c9297fc6 100644 --- a/extensions/sql-migration/src/models/stateMachine.ts +++ b/extensions/sql-migration/src/models/stateMachine.ts @@ -26,51 +26,11 @@ export enum State { EXIT, } -export enum MigrationCutover { - MANUAL, - AUTOMATIC -} - -export enum NetworkContainerType { - FILE_SHARE, - BLOB_CONTAINER, - NETWORK_SHARE -} - -export interface NetworkShare { - networkShareLocation: string; - windowsUser: string; - password: string; - storageSubscriptionId: string; - storageAccountId: string; -} - -export interface BlobContainer { - subscriptionId: string; - storageAccountId: string; - containerId: string; -} - -export interface FileShare { - subscriptionId: string; - storageAccountId: string; - fileShareId: string; - resourceGroupId: string; -} -export interface DatabaseBackupModel { - emailNotification: boolean; - migrationCutover: MigrationCutover; - networkContainerType: NetworkContainerType; - networkContainer: NetworkShare | BlobContainer | FileShare; - azureSecurityToken: string; -} export interface Model { readonly sourceConnection: azdata.connection.Connection; readonly currentState: State; gatheringInformationError: string | undefined; skuRecommendations: SKURecommendations | undefined; - azureAccount: azdata.Account | undefined; - databaseBackup: DatabaseBackupModel | undefined; } export interface StateChangeEvent { @@ -84,8 +44,6 @@ export class MigrationStateModel implements Model, vscode.Disposable { private _gatheringInformationError: string | undefined; private _skuRecommendations: SKURecommendations | undefined; private _assessmentResults: mssql.SqlMigrationAssessmentResultItem[] | undefined; - private _azureAccount!: azdata.Account; - private _databaseBackup!: DatabaseBackupModel; constructor( private readonly _extensionContext: vscode.ExtensionContext, @@ -93,23 +51,6 @@ export class MigrationStateModel implements Model, vscode.Disposable { public readonly migrationService: mssql.ISqlMigrationService ) { this._currentState = State.INIT; - this.databaseBackup = {} as DatabaseBackupModel; - } - - public get azureAccount(): azdata.Account { - return this._azureAccount; - } - - public set azureAccount(account: azdata.Account) { - this._azureAccount = account; - } - - public get databaseBackup(): DatabaseBackupModel { - return this._databaseBackup; - } - - public set databaseBackup(dbBackup: DatabaseBackupModel) { - this._databaseBackup = dbBackup; } public get sourceConnection(): azdata.connection.Connection { diff --git a/extensions/sql-migration/src/models/strings.ts b/extensions/sql-migration/src/models/strings.ts index 067f6f1bf9..5a43acac2d 100644 --- a/extensions/sql-migration/src/models/strings.ts +++ b/extensions/sql-migration/src/models/strings.ts @@ -35,54 +35,3 @@ export const SUBSCRIPTION_SELECTION_AZURE_SUBSCRIPTION_TITLE = localize('sql.mig export const SUBSCRIPTION_SELECTION_AZURE_PRODUCT_TITLE = localize('sql.migration.wizard.subscription.azure.product.title', "Azure Product"); export const CONGRATULATIONS = localize('sql.migration.generic.congratulations', "Congratulations"); - - -// Accounts page -export const ACCOUNTS_SELECTION_PAGE_TITLE = localize('sql.migration.wizard.account.title', "Select your Azure account"); -export const ACCOUNT_SELECTION_PAGE_NO_LINKED_ACCOUNTS_ERROR = localize('sql.migration.wizard.account.noaccount.error', "There is no linked account. Please add an account."); -export const ACCOUNT_ADD_BUTTON_LABEL = localize('sql.migration.wizard.account.add.button.label', "Add account"); -export function accountLinkedMessage(count: number): string { - return count === 1 ? localize('sql.migration.wizard.account.count.single.message', '{0} account linked', count) : localize('sql.migration.wizard.account.count.multiple.message', '{0} accounts linked', count); -} - - -// database backup page -export const DATABASE_BACKUP_PAGE_TITLE = localize('sql.migration.database.page.title', "Database Backup"); -export const DATABASE_BACKUP_PAGE_DESCRIPTION = localize('sql.migration.database.page.description', "Select the location where we can find your database backups (Full, Differential and Log) to use for migration."); -export const DATABASE_BACKUP_NC_NETWORK_SHARE_RADIO_LABEL = localize('sql.migration.nc.network.share.radio.label', "My database backups are on a network share"); -export const DATABASE_BACKUP_NC_NETWORK_SHARE_HELP_TEXT = localize('sql.migration.network.share.help.text', "Enter network share information"); -export const DATABASE_BACKUP_NC_BLOB_STORAGE_RADIO_LABEL = localize('sql.migration.nc.blob.storage.radio.label', "My database backups are in an Azure Storage Blob Container"); -export const DATABASE_BACKUP_NC_FILE_SHARE_RADIO_LABEL = localize('sql.migration.nc.file.share.radio.label', "My database backups are in an Azure Storage File Share"); -export const DATABASE_BACKUP_NETWORK_SHARE_LOCATION_LABEL = localize('sql.migration.network.share.location.label', "Network share location to read backups from."); -export const DATABASE_BACKUP_NETWORK_SHARE_WINDOWS_USER_LABEL = localize('sql.migration.network.share.windows.user.label', "Windows user account with read access to the network share location."); -export const DATABASE_BACKUP_NETWORK_SHARE_PASSWORD_LABEL = localize('sql.migration.network.share.password.label', "Password"); -export const DATABASE_BACKUP_NETWORK_SHARE_PASSWORD_PLACEHOLDER = localize('sql.migration.network.share.password.placeholder', "Enter password"); -export const DATABASE_BACKUP_NETWORK_SHARE_AZURE_ACCOUNT_HELP = localize('sql.migration.network.share.azure.help', "Enter Azure storage account information where the backup will be copied"); -export const DATABASE_BACKUP_NETWORK_SHARE_SUBSCRIPTION_LABEL = localize('sql.migration.network.share.subscription.label', "Select the subscription that contains the storage account."); -export const DATABASE_BACKUP_SUBSCRIPTION_PLACEHOLDER = localize('sql.migration.network.share.subscription.placeholder', "Select subscription"); -export const DATABASE_BACKUP_NETWORK_SHARE_NETWORK_STORAGE_ACCOUNT_LABEL = localize('sql.migration.network.share.storage.account.label', "Select the storage account where backup files will be copied."); -export const DATABASE_BACKUP_STORAGE_ACCOUNT_PLACEHOLDER = localize('sql.migration.network.share.storage.account.placeholder', "Select account"); -export const DATABASE_BACKUP_BLOB_STORAGE_SUBSCRIPTION_LABEL = localize('sql.migration.blob.storage.subscription.label', "Select the subscription that contains the storage account."); -export const DATABASE_BACKUP_BLOB_STORAGE_ACCOUNT_LABEL = localize('sql.migration.blob.storage.account.label', "Select the storage account that contains the backup files."); -export const DATABASE_BACKUP_BLOB_STORAGE_ACCOUNT_CONTAINER_LABEL = localize('sql.migration.blob.storage.container.label', "Select the container that contains the backup files."); -export const DATABASE_BACKUP_BLOB_STORAGE_ACCOUNT_CONTAINER_PLACEHOLDER = localize('sql.migration.blob.storage.container.placeholder', "Select container"); -export const DATABASE_BACKUP_FILE_SHARE_SUBSCRIPTION_LABEL = localize('sql.migration.file.share.subscription.label', "Select the subscription that contains the file share."); -export const DATABASE_BACKUP_FILE_SHARE_STORAGE_ACCOUNT_LABEL = localize('sql.migration.file.share.storage.account.label', "Select the storage account that contains the file share."); -export const DATABASE_BACKUP_FILE_SHARE_LABEL = localize('sql.migration.file.share.label', "Select the file share that contains the backup files."); -export const DATABASE_BACKUP_FILE_SHARE_PLACEHOLDER = localize('sql.migration.file.share.placeholder', "Select share"); -export const DATABASE_BACKUP_MIGRATION_CUTOVER_LABEL = localize('sql.migration.database.migration.cutover.label', "Migration Cutover"); -export const DATABASE_BACKUP_MIGRATION_CUTOVER_DESCRIPTION = localize('sql.migration.database.migration.cutover.description', "Select how you want to cutover when the migration is complete."); -export const DATABASE_BACKUP_MIGRATION_CUTOVER_AUTOMATIC_LABEL = localize('sql.migration.database.migration.cutover.automatic.label', "Automatically cutover when migration is complete"); -export const DATABASE_BACKUP_MIGRATION_CUTOVER_MANUAL_LABEL = localize('sql.migration.database.migration.cutover.manual.label', "Manually cutover when migration is complete"); -export const DATABASE_BACKUP_EMAIL_NOTIFICATION_LABEL = localize('sql.migration.database.backup.email.notification.label', "Email notifications"); -export const DATABASE_BACKUP_EMAIL_NOTIFICATION_CHECKBOX_LABEL = localize('sql.migration.database.backup.email.notification.checkbox.label', "Notify me when migration is complete"); -export const NO_SUBSCRIPTIONS_FOUND = localize('sql.migration.no.subscription.found', "No subscription found"); -export const NO_STORAGE_ACCOUNT_FOUND = localize('sql.migration.no.storageAccount.found', "No storage account found"); -export const NO_FILESHARES_FOUND = localize('sql.migration.no.fileShares.found', "No file shares found"); -export const NO_BLOBCONTAINERS_FOUND = localize('sql.migration.no.blobContainers.found', "No blob containers found"); -export const INVALID_SUBSCRIPTION_ERROR = localize('sql.migration.invalid.subscription.error', "Please select a valid subscription to proceed."); -export const INVALID_STORAGE_ACCOUNT_ERROR = localize('sql.migration.invalid.storageAccout.error', "Please select a valid storage account to proceed."); -export const INVALID_FILESHARE_ERROR = localize('sql.migration.invalid.fileShare.error', "Please select a valid file share to proceed."); -export const INVALID_BLOBCONTAINER_ERROR = localize('sql.migration.invalid.blobContainer.error', "Please select a valid blob container to proceed."); -export const INVALID_NETWORK_SHARE_LOCATION = localize('sql.migration.invalid.network.share.location', "Invalid network share location format. Example: {0}", '\\\\Servername.domainname.com\\Backupfolder'); -export const INVALID_USER_ACCOUNT = localize('sql.migration.invalid.user.account', "Invalid user account format. Example: {0}", 'Domain\\username'); diff --git a/extensions/sql-migration/src/wizard/accountsSelectionPage.ts b/extensions/sql-migration/src/wizard/accountsSelectionPage.ts deleted file mode 100644 index 96dd4e335b..0000000000 --- a/extensions/sql-migration/src/wizard/accountsSelectionPage.ts +++ /dev/null @@ -1,106 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * 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 { MigrationWizardPage } from '../models/migrationWizardPage'; -import { MigrationStateModel, StateChangeEvent } from '../models/stateMachine'; -import * as constants from '../models/strings'; - -export class AccountsSelectionPage extends MigrationWizardPage { - private _azureAccountsDropdown!: azdata.DropDownComponent; - private _accountsMap: Map = new Map(); - - constructor(wizard: azdata.window.Wizard, migrationStateModel: MigrationStateModel) { - super(wizard, azdata.window.createWizardPage(constants.ACCOUNTS_SELECTION_PAGE_TITLE), migrationStateModel); - } - - protected async registerContent(view: azdata.ModelView): Promise { - const form = view.modelBuilder.formContainer() - .withFormItems( - [ - await this.createAzureAccountsDropdown(view) - ] - ); - await view.initializeModel(form.component()); - await this.populateAzureAccountsDropdown(); - } - - private createAzureAccountsDropdown(view: azdata.ModelView): azdata.FormComponent { - - this._azureAccountsDropdown = view.modelBuilder.dropDown().withValidation((c) => { - if ((c.value).displayName === constants.ACCOUNT_SELECTION_PAGE_NO_LINKED_ACCOUNTS_ERROR) { - this.wizard.message = { - text: constants.ACCOUNT_SELECTION_PAGE_NO_LINKED_ACCOUNTS_ERROR, - level: azdata.window.MessageLevel.Error - }; - return false; - } - return true; - }).component(); - - this._azureAccountsDropdown.onValueChanged(async (value) => { - this.migrationStateModel.azureAccount = this._accountsMap.get((this._azureAccountsDropdown.value as azdata.CategoryValue).name)!; - }); - - const addAccountButton = view.modelBuilder.button() - .withProperties({ - label: constants.ACCOUNT_ADD_BUTTON_LABEL, - width: '100px' - }) - .component(); - - addAccountButton.onDidClick(async (event) => { - await vscode.commands.executeCommand('workbench.actions.modal.linkedAccount'); - await this.populateAzureAccountsDropdown(); - }); - - const flexContainer = view.modelBuilder.flexContainer() - .withLayout({ - flexFlow: 'column' - }) - .withItems([this._azureAccountsDropdown, addAccountButton], { CSSStyles: { 'margin': '10px', } }) - .component(); - - return { - title: '', - component: flexContainer - }; - } - - private async populateAzureAccountsDropdown(): Promise { - this._azureAccountsDropdown.loading = true; - let accounts = await azdata.accounts.getAllAccounts(); - - if (accounts.length === 0) { - this._azureAccountsDropdown.value = { - displayName: constants.ACCOUNT_SELECTION_PAGE_NO_LINKED_ACCOUNTS_ERROR, - name: '' - }; - return; - } - - this._azureAccountsDropdown.values = accounts.map((account): azdata.CategoryValue => { - let accountCategoryValue = { - displayName: account.displayInfo.displayName, - name: account.displayInfo.userId - }; - this._accountsMap.set(accountCategoryValue.name, account); - return accountCategoryValue; - }); - - this.migrationStateModel.azureAccount = accounts[0]; - this._azureAccountsDropdown.loading = false; - } - - public async onPageEnter(): Promise { - } - - public async onPageLeave(): Promise { - } - - protected async handleStateChange(e: StateChangeEvent): Promise { - } -} diff --git a/extensions/sql-migration/src/wizard/databaseBackupPage.ts b/extensions/sql-migration/src/wizard/databaseBackupPage.ts deleted file mode 100644 index d9d715cbce..0000000000 --- a/extensions/sql-migration/src/wizard/databaseBackupPage.ts +++ /dev/null @@ -1,702 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * 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 { azureResource } from 'azureResource'; -import { EOL } from 'os'; -import { getAvailableStorageAccounts, getBlobContainers, getFileShares, getSubscriptions, StorageAccount, Subscription } from '../api/azure'; -import { MigrationWizardPage } from '../models/migrationWizardPage'; -import { BlobContainer, FileShare, MigrationCutover, MigrationStateModel, NetworkContainerType, NetworkShare, StateChangeEvent } from '../models/stateMachine'; -import * as constants from '../models/strings'; - -export class DatabaseBackupPage extends MigrationWizardPage { - - private _networkShareContainer!: azdata.FlexContainer; - private _networkShareContainerSubscriptionDropdown!: azdata.DropDownComponent; - private _networkShareContainerStorageAccountDropdown!: azdata.DropDownComponent; - private _networkShareLocationText!: azdata.InputBoxComponent; - private _windowsUserAccountText!: azdata.InputBoxComponent; - private _passwordText!: azdata.InputBoxComponent; - - private _blobContainer!: azdata.FlexContainer; - private _blobContainerSubscriptionDropdown!: azdata.DropDownComponent; - private _blobContainerStorageAccountDropdown!: azdata.DropDownComponent; - private _blobContainerBlobDropdown!: azdata.DropDownComponent; - - private _fileShareContainer!: azdata.FlexContainer; - private _fileShareSubscriptionDropdown!: azdata.DropDownComponent; - private _fileShareStorageAccountDropdown!: azdata.DropDownComponent; - private _fileShareFileShareDropdown!: azdata.DropDownComponent; - - private _networkShare = {} as NetworkShare; - private _fileShare = {} as FileShare; - private _blob = {} as BlobContainer; - - private _subscriptionDropdownValues: azdata.CategoryValue[] = []; - private _subscriptionMap: Map = new Map(); - private _storageAccountMap: Map = new Map(); - - private _errors: string[] = []; - - constructor(wizard: azdata.window.Wizard, migrationStateModel: MigrationStateModel) { - super(wizard, azdata.window.createWizardPage(constants.DATABASE_BACKUP_PAGE_TITLE), migrationStateModel); - this.wizardPage.description = constants.DATABASE_BACKUP_PAGE_DESCRIPTION; - } - - protected async registerContent(view: azdata.ModelView): Promise { - - this._networkShareContainer = this.createNetworkShareContainer(view); - this._blobContainer = this.createBlobContainer(view); - this._fileShareContainer = this.createFileShareContainer(view); - - const networkContainer = view.modelBuilder.flexContainer().withLayout({ - flexFlow: 'column' - }).withItems([ - this._networkShareContainer, - this._blobContainer, - this._fileShareContainer - ]).component(); - - const form = view.modelBuilder.formContainer() - .withFormItems( - [ - this.createBackupLocationComponent(view), - { - title: '', - component: networkContainer - }, - this.migrationCutoverContainer(view), - this.emailNotificationContainer(view), - ] - ); - await view.initializeModel(form.component()); - this.toggleNetworkContainerFields(NetworkContainerType.NETWORK_SHARE, this._networkShare); - } - - private createBackupLocationComponent(view: azdata.ModelView): azdata.FormComponent { - const buttonGroup = 'networkContainer'; - - const networkShareButton = view.modelBuilder.radioButton() - .withProps({ - name: buttonGroup, - label: constants.DATABASE_BACKUP_NC_NETWORK_SHARE_RADIO_LABEL, - checked: true - }).component(); - - networkShareButton.onDidClick((e) => this.toggleNetworkContainerFields(NetworkContainerType.NETWORK_SHARE, this._networkShare)); - - const blobContainerButton = view.modelBuilder.radioButton() - .withProps({ - name: buttonGroup, - label: constants.DATABASE_BACKUP_NC_BLOB_STORAGE_RADIO_LABEL, - }).component(); - - blobContainerButton.onDidClick((e) => this.toggleNetworkContainerFields(NetworkContainerType.BLOB_CONTAINER, this._blob)); - - const fileShareButton = view.modelBuilder.radioButton() - .withProps({ - name: buttonGroup, - label: constants.DATABASE_BACKUP_NC_FILE_SHARE_RADIO_LABEL, - }).component(); - - fileShareButton.onDidClick((e) => this.toggleNetworkContainerFields(NetworkContainerType.FILE_SHARE, this._fileShare)); - - const flexContainer = view.modelBuilder.flexContainer().withItems( - [ - networkShareButton, - blobContainerButton, - fileShareButton - ] - ).withLayout({ - flexFlow: 'column' - }).component(); - - return { - title: '', - component: flexContainer - }; - } - - private createFileShareContainer(view: azdata.ModelView): azdata.FlexContainer { - - const subscriptionLabel = view.modelBuilder.text().withProps({ - value: constants.DATABASE_BACKUP_FILE_SHARE_SUBSCRIPTION_LABEL, - requiredIndicator: true, - }).component(); - this._fileShareSubscriptionDropdown = view.modelBuilder.dropDown().withProps({ - required: true, - }).withValidation((c) => { - if (this.migrationStateModel.databaseBackup.networkContainerType === NetworkContainerType.FILE_SHARE) { - if ((c.value).displayName === constants.NO_SUBSCRIPTIONS_FOUND) { - this.addErrorMessage(constants.INVALID_SUBSCRIPTION_ERROR); - return false; - } else { - this.removeErrorMessage(constants.INVALID_SUBSCRIPTION_ERROR); - } - } - return true; - }).component(); - this._fileShareSubscriptionDropdown.onValueChanged(async (value) => { - this._fileShare.subscriptionId = (this._fileShareSubscriptionDropdown.value as azdata.CategoryValue).name; - await this.loadFileShareStorageDropdown(); - }); - - const storageAccountLabel = view.modelBuilder.text() - .withProps({ - value: constants.DATABASE_BACKUP_FILE_SHARE_STORAGE_ACCOUNT_LABEL, - requiredIndicator: true, - }).component(); - this._fileShareStorageAccountDropdown = view.modelBuilder.dropDown() - .withProps({ - required: true - }).withValidation((c) => { - if (this.migrationStateModel.databaseBackup.networkContainerType === NetworkContainerType.FILE_SHARE) { - if ((c.value).displayName === constants.NO_STORAGE_ACCOUNT_FOUND) { - this.addErrorMessage(constants.INVALID_STORAGE_ACCOUNT_ERROR); - return false; - } else { - this.removeErrorMessage(constants.INVALID_STORAGE_ACCOUNT_ERROR); - } - } - return true; - }).component(); - this._fileShareStorageAccountDropdown.onValueChanged(async (value) => { - this._fileShare.storageAccountId = (this._fileShareStorageAccountDropdown.value as azdata.CategoryValue).name; - await this.loadFileShareDropdown(); - }); - - const fileShareLabel = view.modelBuilder.text() - .withProps({ - value: constants.DATABASE_BACKUP_FILE_SHARE_LABEL, - requiredIndicator: true, - }).component(); - this._fileShareFileShareDropdown = view.modelBuilder.dropDown() - .withProps({ - required: true - }).withValidation((c) => { - if (this.migrationStateModel.databaseBackup.networkContainerType === NetworkContainerType.FILE_SHARE) { - if ((c.value).displayName === constants.NO_FILESHARES_FOUND) { - this.addErrorMessage(constants.INVALID_FILESHARE_ERROR); - return false; - } else { - this.removeErrorMessage(constants.INVALID_FILESHARE_ERROR); - } - } - return true; - }).component(); - this._fileShareFileShareDropdown.onValueChanged((value) => { - this._fileShare.fileShareId = (this._fileShareFileShareDropdown.value as azdata.CategoryValue).name; - }); - - - const flexContainer = view.modelBuilder.flexContainer() - .withItems( - [ - subscriptionLabel, - this._fileShareSubscriptionDropdown, - storageAccountLabel, - this._fileShareStorageAccountDropdown, - fileShareLabel, - this._fileShareFileShareDropdown - ] - ).withLayout({ - flexFlow: 'column' - }).component(); - - return flexContainer; - } - - private createBlobContainer(view: azdata.ModelView): azdata.FlexContainer { - const subscriptionLabel = view.modelBuilder.text() - .withProps({ - value: constants.DATABASE_BACKUP_BLOB_STORAGE_SUBSCRIPTION_LABEL, - requiredIndicator: true, - }).component(); - this._blobContainerSubscriptionDropdown = view.modelBuilder.dropDown() - .withProps({ - required: true - }).withValidation((c) => { - if (this.migrationStateModel.databaseBackup.networkContainerType === NetworkContainerType.BLOB_CONTAINER) { - if ( - (c.value).displayName === constants.NO_SUBSCRIPTIONS_FOUND) { - this.addErrorMessage(constants.INVALID_SUBSCRIPTION_ERROR); - return false; - } else { - this.removeErrorMessage(constants.INVALID_SUBSCRIPTION_ERROR); - } - } - return true; - }).component(); - this._blobContainerSubscriptionDropdown.onValueChanged(async (value) => { - this._blob.subscriptionId = (this._blobContainerSubscriptionDropdown.value as azdata.CategoryValue).name; - await this.loadblobStorageDropdown(); - }); - - const storageAccountLabel = view.modelBuilder.text() - .withProps({ - value: constants.DATABASE_BACKUP_BLOB_STORAGE_ACCOUNT_LABEL, - requiredIndicator: true, - }).component(); - this._blobContainerStorageAccountDropdown = view.modelBuilder.dropDown() - .withProps({ - required: true - }).withValidation((c) => { - if (this.migrationStateModel.databaseBackup.networkContainerType === NetworkContainerType.BLOB_CONTAINER) { - if ((c.value).displayName === constants.NO_STORAGE_ACCOUNT_FOUND) { - this.addErrorMessage(constants.INVALID_STORAGE_ACCOUNT_ERROR); - return false; - } else { - this.removeErrorMessage(constants.INVALID_STORAGE_ACCOUNT_ERROR); - } - } - return true; - }).component(); - this._blobContainerStorageAccountDropdown.onValueChanged(async (value) => { - this._blob.storageAccountId = (this._blobContainerStorageAccountDropdown.value as azdata.CategoryValue).name; - await this.loadBlobContainerDropdown(); - }); - - const containerLabel = view.modelBuilder.text().withProps({ - value: constants.DATABASE_BACKUP_BLOB_STORAGE_ACCOUNT_CONTAINER_LABEL, - requiredIndicator: true, - }).component(); - this._blobContainerBlobDropdown = view.modelBuilder.dropDown() - .withProps({ - required: true - }).withValidation((c) => { - if (this.migrationStateModel.databaseBackup.networkContainerType === NetworkContainerType.BLOB_CONTAINER) { - if ((c.value).displayName === constants.NO_BLOBCONTAINERS_FOUND) { - this.addErrorMessage(constants.INVALID_BLOBCONTAINER_ERROR); - return false; - } else { - this.removeErrorMessage(constants.INVALID_BLOBCONTAINER_ERROR); - } - } - return true; - }).component(); - this._blobContainerBlobDropdown.onValueChanged((value) => { - this._blob.containerId = (this._blobContainerBlobDropdown.value as azdata.CategoryValue).name; - }); - - const flexContainer = view.modelBuilder.flexContainer() - .withItems( - [ - subscriptionLabel, - this._blobContainerSubscriptionDropdown, - storageAccountLabel, - this._blobContainerStorageAccountDropdown, - containerLabel, - this._blobContainerBlobDropdown - ] - ).withLayout({ - flexFlow: 'column' - }).component(); - - return flexContainer; - } - - private createNetworkShareContainer(view: azdata.ModelView): azdata.FlexContainer { - const networkShareHelpText = view.modelBuilder.text() - .withProps({ - value: constants.DATABASE_BACKUP_NC_NETWORK_SHARE_HELP_TEXT, - }).component(); - - const networkShareLocationLabel = view.modelBuilder.text() - .withProps({ - value: constants.DATABASE_BACKUP_NETWORK_SHARE_LOCATION_LABEL, - requiredIndicator: true, - }).component(); - this._networkShareLocationText = view.modelBuilder.inputBox() - .withProps({ - placeHolder: '\\\\Servername.domainname.com\\Backupfolder', - required: true, - validationErrorMessage: constants.INVALID_NETWORK_SHARE_LOCATION - }) - .withValidation((component) => { - if (component.value) { - if (!/^(\\)(\\[\w\.-_]+){2,}(\\?)$/.test(component.value)) { - return false; - } - } - return true; - }).component(); - this._networkShareLocationText.onTextChanged((value) => { - this._networkShare.networkShareLocation = value; - }); - - const windowsUserAccountLabel = view.modelBuilder.text() - .withProps({ - value: constants.DATABASE_BACKUP_NETWORK_SHARE_WINDOWS_USER_LABEL, - requiredIndicator: true, - }).component(); - this._windowsUserAccountText = view.modelBuilder.inputBox() - .withProps({ - placeHolder: 'Domain\\username', - required: true, - validationErrorMessage: constants.INVALID_USER_ACCOUNT - }) - .withValidation((component) => { - if (component.value) { - if (!/^[a-zA-Z][a-zA-Z0-9\-\.]{0,61}[a-zA-Z]\\\w[\w\.\- ]*$/.test(component.value)) { - return false; - } - } - return true; - }).component(); - this._windowsUserAccountText.onTextChanged((value) => { - this._networkShare.windowsUser = value; - }); - - const passwordLabel = view.modelBuilder.text() - .withProps({ - value: constants.DATABASE_BACKUP_NETWORK_SHARE_PASSWORD_LABEL, - requiredIndicator: true, - }).component(); - this._passwordText = view.modelBuilder.inputBox() - .withProps({ - placeHolder: constants.DATABASE_BACKUP_NETWORK_SHARE_PASSWORD_PLACEHOLDER, - inputType: 'password', - required: true - }).component(); - this._passwordText.onTextChanged((value) => { - this._networkShare.password = value; - }); - - const azureAccountHelpText = view.modelBuilder.text() - .withProps({ - value: constants.DATABASE_BACKUP_NETWORK_SHARE_AZURE_ACCOUNT_HELP, - }).component(); - - const subscriptionLabel = view.modelBuilder.text() - .withProps({ - value: constants.DATABASE_BACKUP_NETWORK_SHARE_SUBSCRIPTION_LABEL, - requiredIndicator: true, - }).component(); - this._networkShareContainerSubscriptionDropdown = view.modelBuilder.dropDown() - .withProps({ - required: true - }).withValidation((c) => { - if (this.migrationStateModel.databaseBackup.networkContainerType === NetworkContainerType.NETWORK_SHARE) { - if ((c.value).displayName === constants.NO_SUBSCRIPTIONS_FOUND) { - this.addErrorMessage(constants.INVALID_SUBSCRIPTION_ERROR); - return false; - } else { - this.removeErrorMessage(constants.INVALID_SUBSCRIPTION_ERROR); - } - } - return true; - }).component(); - this._networkShareContainerSubscriptionDropdown.onValueChanged(async (value) => { - this._networkShare.storageSubscriptionId = (this._networkShareContainerSubscriptionDropdown.value as azdata.CategoryValue).name; - await this.loadNetworkShareStorageDropdown(); - }); - - const storageAccountLabel = view.modelBuilder.text() - .withProps({ - value: constants.DATABASE_BACKUP_NETWORK_SHARE_NETWORK_STORAGE_ACCOUNT_LABEL, - requiredIndicator: true, - }).component(); - this._networkShareContainerStorageAccountDropdown = view.modelBuilder.dropDown() - .withProps({ - required: true - }).withValidation((c) => { - if (this.migrationStateModel.databaseBackup.networkContainerType === NetworkContainerType.NETWORK_SHARE) { - if ((c.value).displayName === constants.NO_STORAGE_ACCOUNT_FOUND) { - this.addErrorMessage(constants.INVALID_STORAGE_ACCOUNT_ERROR); - return false; - } else { - this.removeErrorMessage(constants.INVALID_STORAGE_ACCOUNT_ERROR); - } - } - return true; - }).component(); - this._networkShareContainerStorageAccountDropdown.onValueChanged((value) => { - this._networkShare.storageAccountId = (this._networkShareContainerStorageAccountDropdown.value as azdata.CategoryValue).name; - }); - - const flexContainer = view.modelBuilder.flexContainer().withItems( - [ - networkShareHelpText, - networkShareLocationLabel, - this._networkShareLocationText, - windowsUserAccountLabel, - this._windowsUserAccountText, - passwordLabel, - this._passwordText, - azureAccountHelpText, - subscriptionLabel, - this._networkShareContainerSubscriptionDropdown, - storageAccountLabel, - this._networkShareContainerStorageAccountDropdown - ] - ).withLayout({ - flexFlow: 'column' - }).component(); - - return flexContainer; - } - - private emailNotificationContainer(view: azdata.ModelView): azdata.FormComponent { - const emailCheckbox = view.modelBuilder.checkBox().withProps({ - label: constants.DATABASE_BACKUP_EMAIL_NOTIFICATION_CHECKBOX_LABEL - }).component(); - - emailCheckbox.onChanged((value) => this.migrationStateModel.databaseBackup.emailNotification = value); - - return { - title: constants.DATABASE_BACKUP_EMAIL_NOTIFICATION_LABEL, - component: emailCheckbox - }; - } - - private migrationCutoverContainer(view: azdata.ModelView): azdata.FormComponent { - const description = view.modelBuilder.text().withProps({ - value: constants.DATABASE_BACKUP_MIGRATION_CUTOVER_DESCRIPTION - }).component(); - - const buttonGroup = 'cutoverContainer'; - - const automaticButton = view.modelBuilder.radioButton().withProps({ - label: constants.DATABASE_BACKUP_MIGRATION_CUTOVER_AUTOMATIC_LABEL, - name: buttonGroup, - checked: true - }).component(); - - this.migrationStateModel.databaseBackup.migrationCutover = MigrationCutover.AUTOMATIC; - - automaticButton.onDidClick((e) => this.migrationStateModel.databaseBackup.migrationCutover = MigrationCutover.AUTOMATIC); - - const manualButton = view.modelBuilder.radioButton().withProps({ - label: constants.DATABASE_BACKUP_MIGRATION_CUTOVER_MANUAL_LABEL, - name: buttonGroup - }).component(); - - manualButton.onDidClick((e) => this.migrationStateModel.databaseBackup.migrationCutover = MigrationCutover.MANUAL); - - const flexContainer = view.modelBuilder.flexContainer().withItems( - [ - description, - automaticButton, - manualButton - ] - ).withLayout({ - flexFlow: 'column' - }).component(); - - return { - title: constants.DATABASE_BACKUP_MIGRATION_CUTOVER_LABEL, - component: flexContainer - }; - } - - public async onPageEnter(): Promise { - await this.getSubscriptionValues(); - } - - public async onPageLeave(): Promise { - } - - protected async handleStateChange(e: StateChangeEvent): Promise { - } - - private toggleNetworkContainerFields(containerType: NetworkContainerType, networkContainer: NetworkShare | BlobContainer | FileShare): void { - this.migrationStateModel.databaseBackup.networkContainer = networkContainer; - this.migrationStateModel.databaseBackup.networkContainerType = containerType; - this._fileShareContainer.updateCssStyles({ 'display': (containerType === NetworkContainerType.FILE_SHARE) ? 'inline' : 'none' }); - this._blobContainer.updateCssStyles({ 'display': (containerType === NetworkContainerType.BLOB_CONTAINER) ? 'inline' : 'none' }); - this._networkShareContainer.updateCssStyles({ 'display': (containerType === NetworkContainerType.NETWORK_SHARE) ? 'inline' : 'none' }); - this._networkShareLocationText.updateProperties({ - required: containerType === NetworkContainerType.NETWORK_SHARE - }); - this._windowsUserAccountText.updateProperties({ - required: containerType === NetworkContainerType.NETWORK_SHARE - }); - this._passwordText.updateProperties({ - required: containerType === NetworkContainerType.NETWORK_SHARE - }); - } - - private async getSubscriptionValues(): Promise { - this._networkShareContainerSubscriptionDropdown.loading = true; - this._fileShareSubscriptionDropdown.loading = true; - this._blobContainerSubscriptionDropdown.loading = true; - - let subscriptions: azureResource.AzureResourceSubscription[] = []; - - try { - subscriptions = await getSubscriptions(this.migrationStateModel.azureAccount); - subscriptions.forEach((subscription) => { - this._subscriptionMap.set(subscription.id, subscription); - this._subscriptionDropdownValues.push({ - name: subscription.id, - displayName: subscription.name + ' - ' + subscription.id, - }); - }); - - if (!this._subscriptionDropdownValues) { - this._subscriptionDropdownValues = [ - { - displayName: constants.NO_SUBSCRIPTIONS_FOUND, - name: '' - } - ]; - } - - this._fileShareSubscriptionDropdown.values = this._subscriptionDropdownValues; - this._networkShareContainerSubscriptionDropdown.values = this._subscriptionDropdownValues; - this._blobContainerSubscriptionDropdown.values = this._subscriptionDropdownValues; - - this._networkShare.storageSubscriptionId = this._subscriptionDropdownValues[0].name; - this._fileShare.subscriptionId = this._subscriptionDropdownValues[0].name; - this._blob.subscriptionId = this._subscriptionDropdownValues[0].name; - - } catch (error) { - - console.log(error); - this.setEmptyDropdownPlaceHolder(this._fileShareSubscriptionDropdown, constants.NO_SUBSCRIPTIONS_FOUND); - this.setEmptyDropdownPlaceHolder(this._networkShareContainerSubscriptionDropdown, constants.NO_SUBSCRIPTIONS_FOUND); - this.setEmptyDropdownPlaceHolder(this._blobContainerSubscriptionDropdown, constants.NO_SUBSCRIPTIONS_FOUND); - } - - this._networkShareContainerSubscriptionDropdown.loading = false; - this._fileShareSubscriptionDropdown.loading = false; - this._blobContainerSubscriptionDropdown.loading = false; - - await this.loadNetworkShareStorageDropdown(); - await this.loadFileShareStorageDropdown(); - await this.loadblobStorageDropdown(); - this._networkShareContainerSubscriptionDropdown.validate(); - this._networkShareContainerStorageAccountDropdown.validate(); - } - - private async loadNetworkShareStorageDropdown(): Promise { - this._networkShareContainerStorageAccountDropdown.loading = true; - - const subscriptionId = (this._networkShareContainerSubscriptionDropdown.value).name; - if (!subscriptionId.length) { - this.setEmptyDropdownPlaceHolder(this._networkShareContainerStorageAccountDropdown, constants.NO_STORAGE_ACCOUNT_FOUND); - } else { - const storageAccounts = await this.loadStorageAccounts(this._networkShare.storageSubscriptionId); - - if (storageAccounts && storageAccounts.length) { - this._networkShareContainerStorageAccountDropdown.values = storageAccounts.map(s => { name: s.id, displayName: s.name }); - this._networkShare.storageAccountId = storageAccounts[0].id; - } - else { - this.setEmptyDropdownPlaceHolder(this._networkShareContainerStorageAccountDropdown, constants.NO_STORAGE_ACCOUNT_FOUND); - } - } - this._networkShareContainerStorageAccountDropdown.loading = false; - } - - private async loadFileShareStorageDropdown(): Promise { - this._fileShareStorageAccountDropdown.loading = true; - this._fileShareFileShareDropdown.loading = true; - - const subscriptionId = (this._fileShareSubscriptionDropdown.value).name; - if (!subscriptionId.length) { - this.setEmptyDropdownPlaceHolder(this._fileShareStorageAccountDropdown, constants.NO_STORAGE_ACCOUNT_FOUND); - } else { - const storageAccounts = await this.loadStorageAccounts(this._fileShare.subscriptionId); - if (storageAccounts && storageAccounts.length) { - this._fileShareStorageAccountDropdown.values = storageAccounts.map(s => { name: s.id, displayName: s.name }); - this._fileShare.storageAccountId = storageAccounts[0].id; - } - else { - this.setEmptyDropdownPlaceHolder(this._fileShareStorageAccountDropdown, constants.NO_STORAGE_ACCOUNT_FOUND); - this._fileShareStorageAccountDropdown.loading = false; - } - } - this._fileShareStorageAccountDropdown.loading = false; - await this.loadFileShareDropdown(); - } - - private async loadblobStorageDropdown(): Promise { - this._blobContainerStorageAccountDropdown.loading = true; - this._blobContainerBlobDropdown.loading = true; - - const subscriptionId = (this._blobContainerSubscriptionDropdown.value).name; - if (!subscriptionId.length) { - this.setEmptyDropdownPlaceHolder(this._blobContainerStorageAccountDropdown, constants.NO_STORAGE_ACCOUNT_FOUND); - } else { - const storageAccounts = await this.loadStorageAccounts(this._blob.subscriptionId); - if (storageAccounts.length) { - this._blobContainerStorageAccountDropdown.values = storageAccounts.map(s => { name: s.id, displayName: s.name }); - this._blob.storageAccountId = storageAccounts[0].id; - } else { - this.setEmptyDropdownPlaceHolder(this._blobContainerStorageAccountDropdown, constants.NO_STORAGE_ACCOUNT_FOUND); - } - } - this._blobContainerStorageAccountDropdown.loading = false; - await this.loadBlobContainerDropdown(); - } - - private async loadStorageAccounts(subscriptionId: string): Promise { - const storageAccounts = await getAvailableStorageAccounts(this.migrationStateModel.azureAccount, this._subscriptionMap.get(subscriptionId)!); - storageAccounts.forEach(s => { - this._storageAccountMap.set(s.id, s); - }); - return storageAccounts; - } - - private async loadFileShareDropdown(): Promise { - this._fileShareFileShareDropdown.loading = true; - const storageAccountId = (this._fileShareStorageAccountDropdown.value).name; - if (!storageAccountId.length) { - this.setEmptyDropdownPlaceHolder(this._fileShareFileShareDropdown, constants.NO_FILESHARES_FOUND); - } else { - const fileShares = await getFileShares(this.migrationStateModel.azureAccount, this._subscriptionMap.get(this._fileShare.subscriptionId)!, this._storageAccountMap.get(storageAccountId)!); - if (fileShares && fileShares.length) { - this._fileShareFileShareDropdown.values = fileShares.map(f => { name: f.id, displayName: f.name }); - this._fileShare.fileShareId = fileShares[0].id!; - } else { - this.setEmptyDropdownPlaceHolder(this._fileShareFileShareDropdown, constants.NO_FILESHARES_FOUND); - } - } - this._fileShareFileShareDropdown.loading = false; - } - - private async loadBlobContainerDropdown(): Promise { - this._blobContainerBlobDropdown.loading = true; - const storageAccountId = (this._blobContainerStorageAccountDropdown.value).name; - if (!storageAccountId.length) { - this.setEmptyDropdownPlaceHolder(this._blobContainerBlobDropdown, constants.NO_BLOBCONTAINERS_FOUND); - } else { - const blobContainer = await getBlobContainers(this.migrationStateModel.azureAccount, this._subscriptionMap.get(this._blob.subscriptionId)!, this._storageAccountMap.get(storageAccountId)!); - if (blobContainer && blobContainer.length) { - this._blobContainerBlobDropdown.values = blobContainer.map(f => { name: f.id, displayName: f.name }); - this._blob.containerId = blobContainer[0].id!; - } else { - this.setEmptyDropdownPlaceHolder(this._blobContainerBlobDropdown, constants.NO_BLOBCONTAINERS_FOUND); - } - } - this._blobContainerBlobDropdown.loading = false; - } - - private setEmptyDropdownPlaceHolder(dropDown: azdata.DropDownComponent, placeholder: string): void { - dropDown.values = [{ - displayName: placeholder, - name: '' - }]; - } - - private addErrorMessage(message: string) { - if (!this._errors.includes(message)) { - this._errors.push(message); - } - this.wizard.message = { - text: this._errors.join(EOL), - level: azdata.window.MessageLevel.Error - }; - } - - private removeErrorMessage(message: string) { - this._errors = this._errors.filter(e => e !== message); - this.wizard.message = { - text: this._errors.join(EOL), - level: azdata.window.MessageLevel.Error - }; - } -} diff --git a/extensions/sql-migration/src/wizard/wizardController.ts b/extensions/sql-migration/src/wizard/wizardController.ts index 704ca9b04b..f30a45b89e 100644 --- a/extensions/sql-migration/src/wizard/wizardController.ts +++ b/extensions/sql-migration/src/wizard/wizardController.ts @@ -11,8 +11,6 @@ import { WIZARD_TITLE } from '../models/strings'; import { MigrationWizardPage } from '../models/migrationWizardPage'; import { SKURecommendationPage } from './skuRecommendationPage'; import { SubscriptionSelectionPage } from './subscriptionSelectionPage'; -import { DatabaseBackupPage } from './databaseBackupPage'; -import { AccountsSelectionPage } from './accountsSelectionPage'; export class WizardController { constructor(private readonly extensionContext: vscode.ExtensionContext) { @@ -36,9 +34,8 @@ export class WizardController { const sourceConfigurationPage = new SourceConfigurationPage(wizard, stateModel); const skuRecommendationPage = new SKURecommendationPage(wizard, stateModel); const subscriptionSelectionPage = new SubscriptionSelectionPage(wizard, stateModel); - const azureAccountsPage = new AccountsSelectionPage(wizard, stateModel); - const databaseBackupPage = new DatabaseBackupPage(wizard, stateModel); - const pages: MigrationWizardPage[] = [sourceConfigurationPage, skuRecommendationPage, subscriptionSelectionPage, azureAccountsPage, databaseBackupPage]; + + const pages: MigrationWizardPage[] = [sourceConfigurationPage, skuRecommendationPage, subscriptionSelectionPage]; wizard.pages = pages.map(p => p.getwizardPage());