mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-02-16 10:58:30 -05:00
[SQL Migration] Improve IR registration experience (#22926)
* Add registration instructions to IR page * Clean up * Typo * Fix typo * Replace link with aka.ms link * Refactor + implement regenerate auth keys * Update strings and clean up comments * Fix sqlMigrationServiceDetailsDialog * Fix sqlMigrationServiceDetailsDialog width * Extract helpers to utils * Add IR registration instructions to sqlMigrationServiceDetailsDialog * Update SHIR description slightly
This commit is contained in:
@@ -3,7 +3,7 @@
|
|||||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||||
*--------------------------------------------------------------------------------------------*/
|
*--------------------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
import { window, Account, accounts, CategoryValue, DropDownComponent, IconPath, DisplayType, Component } from 'azdata';
|
import { window, Account, accounts, CategoryValue, DropDownComponent, IconPath, DisplayType, Component, ModelView, DeclarativeTableComponent, DeclarativeDataType, FlexContainer } from 'azdata';
|
||||||
import * as vscode from 'vscode';
|
import * as vscode from 'vscode';
|
||||||
import { IconPathHelper } from '../constants/iconPathHelper';
|
import { IconPathHelper } from '../constants/iconPathHelper';
|
||||||
import * as crypto from 'crypto';
|
import * as crypto from 'crypto';
|
||||||
@@ -14,6 +14,8 @@ import { logError, TelemetryViews } from '../telemetry';
|
|||||||
import { AdsMigrationStatus } from '../dashboard/tabBase';
|
import { AdsMigrationStatus } from '../dashboard/tabBase';
|
||||||
import { getMigrationMode, getMigrationStatus, getMigrationTargetType, hasRestoreBlockingReason, PipelineStatusCodes } from '../constants/helper';
|
import { getMigrationMode, getMigrationStatus, getMigrationTargetType, hasRestoreBlockingReason, PipelineStatusCodes } from '../constants/helper';
|
||||||
import * as os from 'os';
|
import * as os from 'os';
|
||||||
|
import * as styles from '../constants/styles';
|
||||||
|
import { SqlMigrationService, getSqlMigrationServiceAuthKeys, regenerateSqlMigrationServiceAuthKey } from './azure';
|
||||||
|
|
||||||
export type TargetServerType = azure.SqlVMServer | azureResource.AzureSqlManagedInstance | azure.AzureSqlDatabaseServer;
|
export type TargetServerType = azure.SqlVMServer | azureResource.AzureSqlManagedInstance | azure.AzureSqlDatabaseServer;
|
||||||
|
|
||||||
@@ -958,3 +960,210 @@ export async function isAdmin(): Promise<boolean> {
|
|||||||
|
|
||||||
return isAdmin;
|
return isAdmin;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function createAuthenticationKeyTable(view: ModelView, columnWidth: string, stretchWidth: string): DeclarativeTableComponent {
|
||||||
|
const WIZARD_INPUT_COMPONENT_WIDTH = '600px';
|
||||||
|
|
||||||
|
const authKeyTable = view.modelBuilder.declarativeTable()
|
||||||
|
.withProps({
|
||||||
|
ariaLabel: constants.DATABASE_MIGRATION_SERVICE_AUTHENTICATION_KEYS,
|
||||||
|
columns: [
|
||||||
|
{
|
||||||
|
displayName: constants.NAME,
|
||||||
|
valueType: DeclarativeDataType.string,
|
||||||
|
width: columnWidth,
|
||||||
|
isReadOnly: true,
|
||||||
|
rowCssStyles: { ...styles.BODY_CSS },
|
||||||
|
headerCssStyles: { ...styles.BODY_CSS, 'font-weight': '600' }
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: constants.AUTH_KEY_COLUMN_HEADER,
|
||||||
|
valueType: DeclarativeDataType.string,
|
||||||
|
width: stretchWidth,
|
||||||
|
isReadOnly: true,
|
||||||
|
rowCssStyles: { ...styles.BODY_CSS },
|
||||||
|
headerCssStyles: { ...styles.BODY_CSS, 'font-weight': '600' }
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: '',
|
||||||
|
valueType: DeclarativeDataType.component,
|
||||||
|
width: columnWidth,
|
||||||
|
isReadOnly: true,
|
||||||
|
rowCssStyles: { ...styles.BODY_CSS },
|
||||||
|
headerCssStyles: { ...styles.BODY_CSS }
|
||||||
|
}
|
||||||
|
],
|
||||||
|
CSSStyles: { 'margin-top': '5px', 'width': WIZARD_INPUT_COMPONENT_WIDTH }
|
||||||
|
}).component();
|
||||||
|
return authKeyTable;
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function refreshAuthenticationKeyTable(view: ModelView, table: DeclarativeTableComponent, account: Account, subscription: azureResource.AzureResourceSubscription, resourceGroup: string, location: string, service: SqlMigrationService): Promise<void> {
|
||||||
|
var _disposables: vscode.Disposable[] = [];
|
||||||
|
|
||||||
|
const copyKey1Button = view.modelBuilder.button().withProps({
|
||||||
|
title: constants.COPY_KEY1,
|
||||||
|
iconPath: IconPathHelper.copy,
|
||||||
|
ariaLabel: constants.COPY_KEY1,
|
||||||
|
}).component();
|
||||||
|
|
||||||
|
_disposables.push(copyKey1Button.onDidClick(async (e) => {
|
||||||
|
await vscode.env.clipboard.writeText(<string>table.dataValues![0][1].value);
|
||||||
|
void vscode.window.showInformationMessage(constants.SERVICE_KEY1_COPIED_HELP);
|
||||||
|
}));
|
||||||
|
|
||||||
|
const copyKey2Button = view.modelBuilder.button().withProps({
|
||||||
|
title: constants.COPY_KEY2,
|
||||||
|
iconPath: IconPathHelper.copy,
|
||||||
|
ariaLabel: constants.COPY_KEY2,
|
||||||
|
}).component();
|
||||||
|
|
||||||
|
_disposables.push(copyKey2Button.onDidClick(async (e) => {
|
||||||
|
await vscode.env.clipboard.writeText(<string>table.dataValues![1][1].value);
|
||||||
|
void vscode.window.showInformationMessage(constants.SERVICE_KEY2_COPIED_HELP);
|
||||||
|
}));
|
||||||
|
|
||||||
|
const refreshKey1Button = view.modelBuilder.button().withProps({
|
||||||
|
title: constants.REFRESH_KEY1,
|
||||||
|
iconPath: IconPathHelper.refresh,
|
||||||
|
ariaLabel: constants.REFRESH_KEY1,
|
||||||
|
}).component();
|
||||||
|
|
||||||
|
_disposables.push(refreshKey1Button.onDidClick(async (e) => {
|
||||||
|
const keys = await regenerateSqlMigrationServiceAuthKey(
|
||||||
|
account,
|
||||||
|
subscription,
|
||||||
|
resourceGroup,
|
||||||
|
location,
|
||||||
|
service.name,
|
||||||
|
'authKey1');
|
||||||
|
|
||||||
|
const dataValues = table.dataValues!;
|
||||||
|
dataValues![0][1].value = keys.authKey1;
|
||||||
|
await table.setDataValues([]);
|
||||||
|
await table.setDataValues(dataValues);
|
||||||
|
await vscode.window.showInformationMessage(constants.AUTH_KEY_REFRESHED(constants.SERVICE_KEY1_LABEL));
|
||||||
|
}));
|
||||||
|
|
||||||
|
const refreshKey2Button = view.modelBuilder.button().withProps({
|
||||||
|
title: constants.REFRESH_KEY2,
|
||||||
|
iconPath: IconPathHelper.refresh,
|
||||||
|
ariaLabel: constants.REFRESH_KEY2,
|
||||||
|
}).component();
|
||||||
|
|
||||||
|
_disposables.push(refreshKey2Button.onDidClick(async (e) => {
|
||||||
|
const keys = await regenerateSqlMigrationServiceAuthKey(
|
||||||
|
account,
|
||||||
|
subscription,
|
||||||
|
resourceGroup,
|
||||||
|
location,
|
||||||
|
service.name,
|
||||||
|
'authKey2');
|
||||||
|
|
||||||
|
const dataValues = table.dataValues!;
|
||||||
|
dataValues![1][1].value = keys.authKey2;
|
||||||
|
await table.setDataValues([]);
|
||||||
|
await table.setDataValues(dataValues);
|
||||||
|
await vscode.window.showInformationMessage(constants.AUTH_KEY_REFRESHED(constants.SERVICE_KEY2_LABEL));
|
||||||
|
}));
|
||||||
|
|
||||||
|
const keys = await getSqlMigrationServiceAuthKeys(
|
||||||
|
account,
|
||||||
|
subscription,
|
||||||
|
resourceGroup,
|
||||||
|
location,
|
||||||
|
service.name);
|
||||||
|
|
||||||
|
|
||||||
|
await table.updateProperties({
|
||||||
|
dataValues: [
|
||||||
|
[
|
||||||
|
{
|
||||||
|
value: constants.SERVICE_KEY1_LABEL
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: keys.authKey1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: view.modelBuilder.flexContainer().withItems([copyKey1Button, refreshKey1Button]).component()
|
||||||
|
}
|
||||||
|
],
|
||||||
|
[
|
||||||
|
{
|
||||||
|
value: constants.SERVICE_KEY2_LABEL
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: keys.authKey2
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: view.modelBuilder.flexContainer().withItems([copyKey2Button, refreshKey2Button]).component()
|
||||||
|
}
|
||||||
|
]
|
||||||
|
]
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export function createRegistrationInstructions(view: ModelView, testConnectionButton: boolean): FlexContainer {
|
||||||
|
const setupIRHeadingText = view.modelBuilder.text().withProps({
|
||||||
|
value: constants.SERVICE_CONTAINER_HEADING,
|
||||||
|
CSSStyles: {
|
||||||
|
...styles.LABEL_CSS
|
||||||
|
}
|
||||||
|
}).component();
|
||||||
|
|
||||||
|
const setupIRdescription1 = view.modelBuilder.text().withProps({
|
||||||
|
value: constants.SERVICE_CONTAINER_DESCRIPTION1,
|
||||||
|
CSSStyles: {
|
||||||
|
...styles.BODY_CSS
|
||||||
|
}
|
||||||
|
}).component();
|
||||||
|
|
||||||
|
const setupIRdescription2 = view.modelBuilder.text().withProps({
|
||||||
|
value: constants.SERVICE_CONTAINER_DESCRIPTION2,
|
||||||
|
CSSStyles: {
|
||||||
|
...styles.BODY_CSS
|
||||||
|
}
|
||||||
|
}).component();
|
||||||
|
|
||||||
|
const irSetupStep1Text = view.modelBuilder.text().withProps({
|
||||||
|
value: constants.SERVICE_STEP1,
|
||||||
|
CSSStyles: {
|
||||||
|
...styles.BODY_CSS
|
||||||
|
},
|
||||||
|
links: [
|
||||||
|
{
|
||||||
|
text: constants.SERVICE_STEP1_LINK,
|
||||||
|
url: 'https://aka.ms/sql-migration-shir-download'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}).component();
|
||||||
|
|
||||||
|
const irSetupStep2Text = view.modelBuilder.text().withProps({
|
||||||
|
value: constants.SERVICE_STEP2,
|
||||||
|
CSSStyles: {
|
||||||
|
...styles.BODY_CSS
|
||||||
|
}
|
||||||
|
}).component();
|
||||||
|
|
||||||
|
const irSetupStep3Text = view.modelBuilder.text().withProps({
|
||||||
|
value: constants.SERVICE_STEP3(testConnectionButton),
|
||||||
|
CSSStyles: {
|
||||||
|
'margin-top': '10px',
|
||||||
|
'margin-bottom': '10px',
|
||||||
|
...styles.BODY_CSS
|
||||||
|
}
|
||||||
|
}).component();
|
||||||
|
|
||||||
|
return view.modelBuilder.flexContainer().withItems(
|
||||||
|
[
|
||||||
|
setupIRHeadingText,
|
||||||
|
setupIRdescription1,
|
||||||
|
setupIRdescription2,
|
||||||
|
irSetupStep1Text,
|
||||||
|
irSetupStep2Text,
|
||||||
|
irSetupStep3Text,
|
||||||
|
]
|
||||||
|
).withLayout({
|
||||||
|
flexFlow: 'column'
|
||||||
|
}).component();
|
||||||
|
}
|
||||||
|
|||||||
@@ -738,15 +738,23 @@ export const MIGRATION_SERVICE_LOCATION_INFO = localize('sql.migration.services.
|
|||||||
export const MIGRATION_SERVICE_RESOURCE_GROUP_INFO = localize('sql.migration.services.resource.group', "Resource group for your Azure Database Migration Service.");
|
export const MIGRATION_SERVICE_RESOURCE_GROUP_INFO = localize('sql.migration.services.resource.group', "Resource group for your Azure Database Migration Service.");
|
||||||
export const MIGRATION_SERVICE_NAME_INFO = localize('sql.migration.services.name', "Azure Database Migration Service name.");
|
export const MIGRATION_SERVICE_NAME_INFO = localize('sql.migration.services.name', "Azure Database Migration Service name.");
|
||||||
export const MIGRATION_SERVICE_TARGET_INFO = localize('sql.migration.services.target', "Azure SQL target selected as default.");
|
export const MIGRATION_SERVICE_TARGET_INFO = localize('sql.migration.services.target', "Azure SQL target selected as default.");
|
||||||
export const MIGRATION_SERVICE_DIALOG_DESCRIPTION = localize('sql.migration.services.container.description', "Enter the information below to add a new Azure Database Migration Service.");
|
export function MIGRATION_SERVICE_DIALOG_DESCRIPTION(networkShareScenario: boolean) {
|
||||||
|
return networkShareScenario
|
||||||
|
? localize('sql.migration.services.container.description.network', "Enter the information below to add a new Azure Database Migration Service. To register self-hosted integration runtime, select 'My database backups are on a network share' on the previous page.")
|
||||||
|
: localize('sql.migration.services.container.description', "Enter the information below to add a new Azure Database Migration Service.");
|
||||||
|
}
|
||||||
export const LOADING_MIGRATION_SERVICES = localize('sql.migration.service.container.loading.help', "Loading Migration Services");
|
export const LOADING_MIGRATION_SERVICES = localize('sql.migration.service.container.loading.help', "Loading Migration Services");
|
||||||
export const SERVICE_CONTAINER_HEADING = localize('sql.migration.service.container.heading', "Setup integration runtime");
|
export const SERVICE_CONTAINER_HEADING = localize('sql.migration.service.container.heading', "Set up integration runtime");
|
||||||
export const SERVICE_CONTAINER_DESCRIPTION1 = localize('sql.migration.service.container.container.description1', "Azure Database Migration Service leverages Azure Data Factory's self-hosted integration runtime to upload backups from on-premises network file share to Azure.");
|
export const SERVICE_CONTAINER_DESCRIPTION1 = localize('sql.migration.service.container.container.description1', "Azure Database Migration Service leverages Azure Data Factory's self-hosted integration runtime to handle connectivity between source and target and upload backups from an on-premises network file share to Azure (if applicable).");
|
||||||
export const SERVICE_CONTAINER_DESCRIPTION2 = localize('sql.migration.service.container.container.description2', "Follow the instructions below to setup self-hosted integration runtime.");
|
export const SERVICE_CONTAINER_DESCRIPTION2 = localize('sql.migration.service.container.container.description2', "Follow the instructions below to set up self-hosted integration runtime.");
|
||||||
export const SERVICE_STEP1 = localize('sql.migration.ir.setup.step1', "Step 1: {0}");
|
export const SERVICE_STEP1 = localize('sql.migration.ir.setup.step1', "Step 1: {0}");
|
||||||
export const SERVICE_STEP1_LINK = localize('sql.migration.option', "Download and install integration runtime");
|
export const SERVICE_STEP1_LINK = localize('sql.migration.option', "Download and install integration runtime");
|
||||||
export const SERVICE_STEP2 = localize('sql.migration.ir.setup.step2', "Step 2: Use this key to register your integration runtime");
|
export const SERVICE_STEP2 = localize('sql.migration.ir.setup.step2', "Step 2: Use the keys below to register your integration runtime");
|
||||||
export const SERVICE_STEP3 = localize('sql.migration.ir.setup.step3', "Step 3: Click on 'Test connection' button to check the connection between Azure Database Migration Service and integration runtime");
|
export function SERVICE_STEP3(testConnectionButton: boolean) {
|
||||||
|
return testConnectionButton
|
||||||
|
? localize('sql.migration.ir.setup.step3', "Step 3: Click on the 'Test connection' button to check the connection between Azure Database Migration Service and integration runtime")
|
||||||
|
: localize('sql.migration.ir.setup.step3.alternate', "Step 3: Click on the Refresh button above to check the connection between Azure Database Migration Service and integration runtime")
|
||||||
|
}
|
||||||
export const SERVICE_CONNECTION_STATUS = localize('sql.migration.connection.status', "Connection status");
|
export const SERVICE_CONNECTION_STATUS = localize('sql.migration.connection.status', "Connection status");
|
||||||
export const SERVICE_KEY1_LABEL = localize('sql.migration.key1.label', "Key 1");
|
export const SERVICE_KEY1_LABEL = localize('sql.migration.key1.label', "Key 1");
|
||||||
export const SERVICE_KEY2_LABEL = localize('sql.migration.key2.label', "Key 2");
|
export const SERVICE_KEY2_LABEL = localize('sql.migration.key2.label', "Key 2");
|
||||||
@@ -760,8 +768,10 @@ export const AUTH_KEY_COLUMN_HEADER = localize('sql.migration.authKeys.header',
|
|||||||
export function AUTH_KEY_REFRESHED(keyName: string): string {
|
export function AUTH_KEY_REFRESHED(keyName: string): string {
|
||||||
return localize('sql.migration.authKeys.refresh.message', "Authentication key '{0}' has been refreshed.", keyName);
|
return localize('sql.migration.authKeys.refresh.message', "Authentication key '{0}' has been refreshed.", keyName);
|
||||||
}
|
}
|
||||||
export function SERVICE_NOT_READY(serviceName: string): string {
|
export function SERVICE_NOT_READY(serviceName: string, instructionsBelow: boolean): string {
|
||||||
return localize('sql.migration.service.not.ready', "Azure Database Migration Service is not registered. Azure Database Migration Service '{0}' needs to be registered with self-hosted integration runtime on any node.", serviceName);
|
return instructionsBelow
|
||||||
|
? localize('sql.migration.service.not.ready.below', "Azure Database Migration Service is not registered. Azure Database Migration Service '{0}' needs to be registered with self-hosted integration runtime on any node.\n\nSee below for registration instructions.", serviceName)
|
||||||
|
: localize('sql.migration.service.not.ready', "Azure Database Migration Service is not registered. Azure Database Migration Service '{0}' needs to be registered with self-hosted integration runtime on any node.", serviceName);
|
||||||
}
|
}
|
||||||
export function SERVICE_ERROR_NOT_READY(serviceName: string, error: string): string {
|
export function SERVICE_ERROR_NOT_READY(serviceName: string, error: string): string {
|
||||||
return localize('sql.migration.service.error.not.ready',
|
return localize('sql.migration.service.error.not.ready',
|
||||||
@@ -769,8 +779,11 @@ export function SERVICE_ERROR_NOT_READY(serviceName: string, error: string): str
|
|||||||
serviceName,
|
serviceName,
|
||||||
error);
|
error);
|
||||||
}
|
}
|
||||||
export function SERVICE_READY(serviceName: string, host: string): string {
|
export function SERVICE_READY(serviceName: string, nodes: string, instructionsBelow: boolean): string {
|
||||||
return localize('sql.migration.service.ready', "Azure Database Migration Service '{0}' is connected to self-hosted integration runtime running on the node - {1}", serviceName, host);
|
return instructionsBelow
|
||||||
|
? localize('sql.migration.service.ready.below', "Azure Database Migration Service '{0}' is connected to self-hosted integration runtime running on node(s) - {1}\n\nFor improved performance and high availability, you can register additional nodes. See below for registration instructions.", serviceName, nodes)
|
||||||
|
: localize('sql.migration.service.ready', "Azure Database Migration Service '{0}' is connected to self-hosted integration runtime running on node(s) - {1}\n\nFor improved performance and high availability, you can register additional nodes.", serviceName, nodes);
|
||||||
|
|
||||||
}
|
}
|
||||||
export const INVALID_SERVICE_NAME_ERROR = localize('sql.migration.invalid.service.name.error', "Enter a valid name for the Migration Service.");
|
export const INVALID_SERVICE_NAME_ERROR = localize('sql.migration.invalid.service.name.error', "Enter a valid name for the Migration Service.");
|
||||||
export const SERVICE_NOT_FOUND = localize('sql.migration.service.not.found', "No Migration Services found. To continue, create a new one.");
|
export const SERVICE_NOT_FOUND = localize('sql.migration.service.not.found', "No Migration Services found. To continue, create a new one.");
|
||||||
|
|||||||
@@ -5,15 +5,13 @@
|
|||||||
|
|
||||||
import * as azdata from 'azdata';
|
import * as azdata from 'azdata';
|
||||||
import * as vscode from 'vscode';
|
import * as vscode from 'vscode';
|
||||||
import { createSqlMigrationService, getResourceName, getSqlMigrationService, getSqlMigrationServiceAuthKeys, getSqlMigrationServiceMonitoringData, SqlMigrationService } from '../../api/azure';
|
import { createSqlMigrationService, getResourceName, getSqlMigrationService, getSqlMigrationServiceMonitoringData, SqlMigrationService } from '../../api/azure';
|
||||||
import { MigrationStateModel } from '../../models/stateMachine';
|
import { MigrationStateModel } from '../../models/stateMachine';
|
||||||
import { logError, TelemetryViews } from '../../telemetry';
|
import { logError, TelemetryViews } from '../../telemetry';
|
||||||
import * as constants from '../../constants/strings';
|
import * as constants from '../../constants/strings';
|
||||||
import * as os from 'os';
|
import * as os from 'os';
|
||||||
import { azureResource } from 'azurecore';
|
import { azureResource } from 'azurecore';
|
||||||
import { IconPathHelper } from '../../constants/iconPathHelper';
|
|
||||||
import { CreateResourceGroupDialog } from '../createResourceGroup/createResourceGroupDialog';
|
import { CreateResourceGroupDialog } from '../createResourceGroup/createResourceGroupDialog';
|
||||||
import { createAuthenticationKeyTable } from '../../wizard/integrationRuntimePage';
|
|
||||||
import * as EventEmitter from 'events';
|
import * as EventEmitter from 'events';
|
||||||
import * as utils from '../../api/utils';
|
import * as utils from '../../api/utils';
|
||||||
import * as styles from '../../constants/styles';
|
import * as styles from '../../constants/styles';
|
||||||
@@ -33,10 +31,6 @@ export class CreateSqlMigrationServiceDialog {
|
|||||||
private _refreshLoadingComponent!: azdata.LoadingComponent;
|
private _refreshLoadingComponent!: azdata.LoadingComponent;
|
||||||
private migrationServiceAuthKeyTable!: azdata.DeclarativeTableComponent;
|
private migrationServiceAuthKeyTable!: azdata.DeclarativeTableComponent;
|
||||||
private _connectionStatus!: azdata.InfoBoxComponent;
|
private _connectionStatus!: azdata.InfoBoxComponent;
|
||||||
private _copyKey1Button!: azdata.ButtonComponent;
|
|
||||||
private _copyKey2Button!: azdata.ButtonComponent;
|
|
||||||
private _refreshKey1Button!: azdata.ButtonComponent;
|
|
||||||
private _refreshKey2Button!: azdata.ButtonComponent;
|
|
||||||
private _setupContainer!: azdata.FlexContainer;
|
private _setupContainer!: azdata.FlexContainer;
|
||||||
private _resourceGroupPreset!: string;
|
private _resourceGroupPreset!: string;
|
||||||
|
|
||||||
@@ -119,7 +113,17 @@ export class CreateSqlMigrationServiceDialog {
|
|||||||
};
|
};
|
||||||
} else {
|
} else {
|
||||||
await this.refreshStatus();
|
await this.refreshStatus();
|
||||||
await this.refreshAuthTable();
|
|
||||||
|
await utils.refreshAuthenticationKeyTable(
|
||||||
|
this._view,
|
||||||
|
this.migrationServiceAuthKeyTable,
|
||||||
|
this._model._azureAccount,
|
||||||
|
subscription,
|
||||||
|
resourceGroup.name,
|
||||||
|
location,
|
||||||
|
this._createdMigrationService);
|
||||||
|
|
||||||
|
|
||||||
this._setupContainer.display = 'inline';
|
this._setupContainer.display = 'inline';
|
||||||
this._testConnectionButton.hidden = false;
|
this._testConnectionButton.hidden = false;
|
||||||
}
|
}
|
||||||
@@ -214,7 +218,7 @@ export class CreateSqlMigrationServiceDialog {
|
|||||||
|
|
||||||
private async migrationServiceDropdownContainer(): Promise<azdata.FlexContainer> {
|
private async migrationServiceDropdownContainer(): Promise<azdata.FlexContainer> {
|
||||||
const dialogDescription = this._view.modelBuilder.text().withProps({
|
const dialogDescription = this._view.modelBuilder.text().withProps({
|
||||||
value: constants.MIGRATION_SERVICE_DIALOG_DESCRIPTION,
|
value: constants.MIGRATION_SERVICE_DIALOG_DESCRIPTION(!this._model.isSqlDbTarget),
|
||||||
CSSStyles: {
|
CSSStyles: {
|
||||||
...styles.BODY_CSS
|
...styles.BODY_CSS
|
||||||
}
|
}
|
||||||
@@ -410,56 +414,7 @@ export class CreateSqlMigrationServiceDialog {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private createServiceStatus(): azdata.FlexContainer {
|
private createServiceStatus(): azdata.FlexContainer {
|
||||||
|
const instructions = utils.createRegistrationInstructions(this._view, true);
|
||||||
const setupIRHeadingText = this._view.modelBuilder.text().withProps({
|
|
||||||
value: constants.SERVICE_CONTAINER_HEADING,
|
|
||||||
CSSStyles: {
|
|
||||||
...styles.LABEL_CSS
|
|
||||||
}
|
|
||||||
}).component();
|
|
||||||
|
|
||||||
const setupIRdescription1 = this._view.modelBuilder.text().withProps({
|
|
||||||
value: constants.SERVICE_CONTAINER_DESCRIPTION1,
|
|
||||||
CSSStyles: {
|
|
||||||
...styles.BODY_CSS
|
|
||||||
}
|
|
||||||
}).component();
|
|
||||||
|
|
||||||
const setupIRdescription2 = this._view.modelBuilder.text().withProps({
|
|
||||||
value: constants.SERVICE_CONTAINER_DESCRIPTION2,
|
|
||||||
CSSStyles: {
|
|
||||||
...styles.BODY_CSS
|
|
||||||
}
|
|
||||||
}).component();
|
|
||||||
|
|
||||||
const irSetupStep1Text = this._view.modelBuilder.text().withProps({
|
|
||||||
value: constants.SERVICE_STEP1,
|
|
||||||
CSSStyles: {
|
|
||||||
...styles.BODY_CSS
|
|
||||||
},
|
|
||||||
links: [
|
|
||||||
{
|
|
||||||
text: constants.SERVICE_STEP1_LINK,
|
|
||||||
url: 'https://www.microsoft.com/download/details.aspx?id=39717'
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}).component();
|
|
||||||
|
|
||||||
const irSetupStep2Text = this._view.modelBuilder.text().withProps({
|
|
||||||
value: constants.SERVICE_STEP2,
|
|
||||||
CSSStyles: {
|
|
||||||
...styles.BODY_CSS
|
|
||||||
}
|
|
||||||
}).component();
|
|
||||||
|
|
||||||
const irSetupStep3Text = this._view.modelBuilder.text().withProps({
|
|
||||||
value: constants.SERVICE_STEP3,
|
|
||||||
CSSStyles: {
|
|
||||||
'margin-top': '10px',
|
|
||||||
'margin-bottom': '10px',
|
|
||||||
...styles.BODY_CSS
|
|
||||||
}
|
|
||||||
}).component();
|
|
||||||
|
|
||||||
this._connectionStatus = this._view.modelBuilder.infoBox().withProps({
|
this._connectionStatus = this._view.modelBuilder.infoBox().withProps({
|
||||||
text: '',
|
text: '',
|
||||||
@@ -480,17 +435,12 @@ export class CreateSqlMigrationServiceDialog {
|
|||||||
}
|
}
|
||||||
}).component();
|
}).component();
|
||||||
|
|
||||||
this.migrationServiceAuthKeyTable = createAuthenticationKeyTable(this._view);
|
this.migrationServiceAuthKeyTable = utils.createAuthenticationKeyTable(this._view, '50px', '500px');
|
||||||
|
|
||||||
this._setupContainer = this._view.modelBuilder.flexContainer().withItems(
|
this._setupContainer = this._view.modelBuilder.flexContainer().withItems(
|
||||||
[
|
[
|
||||||
setupIRHeadingText,
|
instructions,
|
||||||
setupIRdescription1,
|
|
||||||
setupIRdescription2,
|
|
||||||
irSetupStep1Text,
|
|
||||||
irSetupStep2Text,
|
|
||||||
this.migrationServiceAuthKeyTable,
|
this.migrationServiceAuthKeyTable,
|
||||||
irSetupStep3Text,
|
|
||||||
this._connectionStatus,
|
this._connectionStatus,
|
||||||
this._refreshLoadingComponent
|
this._refreshLoadingComponent
|
||||||
], {
|
], {
|
||||||
@@ -550,16 +500,16 @@ export class CreateSqlMigrationServiceDialog {
|
|||||||
|
|
||||||
if (state === 'Online') {
|
if (state === 'Online') {
|
||||||
await this._connectionStatus.updateProperties(<azdata.InfoBoxComponentProperties>{
|
await this._connectionStatus.updateProperties(<azdata.InfoBoxComponentProperties>{
|
||||||
text: constants.SERVICE_READY(this._createdMigrationService!.name, this.irNodes.join(', ')),
|
text: constants.SERVICE_READY(this._createdMigrationService!.name, this.irNodes.join(', '), false),
|
||||||
style: 'success',
|
style: 'success',
|
||||||
CSSStyles: {
|
CSSStyles: {
|
||||||
...styles.BODY_CSS
|
...styles.BODY_CSS
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
this._connectionStatus.text = constants.SERVICE_NOT_READY(this._createdMigrationService!.name);
|
this._connectionStatus.text = constants.SERVICE_NOT_READY(this._createdMigrationService!.name, false);
|
||||||
await this._connectionStatus.updateProperties(<azdata.InfoBoxComponentProperties>{
|
await this._connectionStatus.updateProperties(<azdata.InfoBoxComponentProperties>{
|
||||||
text: constants.SERVICE_NOT_READY(this._createdMigrationService!.name),
|
text: constants.SERVICE_NOT_READY(this._createdMigrationService!.name, false),
|
||||||
style: 'warning',
|
style: 'warning',
|
||||||
CSSStyles: {
|
CSSStyles: {
|
||||||
...styles.BODY_CSS
|
...styles.BODY_CSS
|
||||||
@@ -570,89 +520,6 @@ export class CreateSqlMigrationServiceDialog {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private async refreshAuthTable(): Promise<void> {
|
|
||||||
const subscription = this._model._sqlMigrationServiceSubscription;
|
|
||||||
const resourceGroupId = (this.migrationServiceResourceGroupDropdown.value as azdata.CategoryValue).name;
|
|
||||||
const resourceGroup = getResourceName(resourceGroupId);
|
|
||||||
const location = this._model._location.name;
|
|
||||||
const keys = await getSqlMigrationServiceAuthKeys(
|
|
||||||
this._model._azureAccount,
|
|
||||||
subscription,
|
|
||||||
resourceGroup,
|
|
||||||
location,
|
|
||||||
this._createdMigrationService!.name);
|
|
||||||
|
|
||||||
this._copyKey1Button = this._view.modelBuilder.button().withProps({
|
|
||||||
title: constants.COPY_KEY1,
|
|
||||||
iconPath: IconPathHelper.copy,
|
|
||||||
ariaLabel: constants.COPY_KEY1,
|
|
||||||
}).component();
|
|
||||||
|
|
||||||
this._disposables.push(this._copyKey1Button.onDidClick(async (e) => {
|
|
||||||
await vscode.env.clipboard.writeText(<string>this.migrationServiceAuthKeyTable.dataValues![0][1].value);
|
|
||||||
void vscode.window.showInformationMessage(constants.SERVICE_KEY1_COPIED_HELP);
|
|
||||||
}));
|
|
||||||
|
|
||||||
this._copyKey2Button = this._view.modelBuilder.button().withProps({
|
|
||||||
title: constants.COPY_KEY2,
|
|
||||||
iconPath: IconPathHelper.copy,
|
|
||||||
ariaLabel: constants.COPY_KEY2,
|
|
||||||
}).component();
|
|
||||||
|
|
||||||
this._disposables.push(this._copyKey2Button.onDidClick(async (e) => {
|
|
||||||
await vscode.env.clipboard.writeText(<string>this.migrationServiceAuthKeyTable.dataValues![1][1].value);
|
|
||||||
void vscode.window.showInformationMessage(constants.SERVICE_KEY2_COPIED_HELP);
|
|
||||||
}));
|
|
||||||
|
|
||||||
this._refreshKey1Button = this._view.modelBuilder.button().withProps({
|
|
||||||
title: constants.REFRESH_KEY1,
|
|
||||||
iconPath: IconPathHelper.refresh,
|
|
||||||
ariaLabel: constants.REFRESH_KEY1,
|
|
||||||
}).component();
|
|
||||||
|
|
||||||
this._disposables.push(this._refreshKey1Button.onDidClick((e) => {
|
|
||||||
//TODO: add refresh logic
|
|
||||||
}));
|
|
||||||
|
|
||||||
this._refreshKey2Button = this._view.modelBuilder.button().withProps({
|
|
||||||
title: constants.REFRESH_KEY2,
|
|
||||||
iconPath: IconPathHelper.refresh,
|
|
||||||
ariaLabel: constants.REFRESH_KEY2,
|
|
||||||
}).component();
|
|
||||||
|
|
||||||
this._disposables.push(this._refreshKey2Button.onDidClick((e) => {
|
|
||||||
//TODO: add refresh logic
|
|
||||||
}));
|
|
||||||
|
|
||||||
await this.migrationServiceAuthKeyTable.updateProperties({
|
|
||||||
dataValues: [
|
|
||||||
[
|
|
||||||
{
|
|
||||||
value: constants.SERVICE_KEY1_LABEL
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: keys.authKey1
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: this._view.modelBuilder.flexContainer().withItems([this._copyKey1Button, this._refreshKey1Button]).component()
|
|
||||||
}
|
|
||||||
],
|
|
||||||
[
|
|
||||||
{
|
|
||||||
value: constants.SERVICE_KEY2_LABEL
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: keys.authKey2
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: this._view.modelBuilder.flexContainer().withItems([this._copyKey2Button, this._refreshKey2Button]).component()
|
|
||||||
}
|
|
||||||
]
|
|
||||||
]
|
|
||||||
});
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
private setDialogMessage(message: string, level: azdata.window.MessageLevel = azdata.window.MessageLevel.Error): void {
|
private setDialogMessage(message: string, level: azdata.window.MessageLevel = azdata.window.MessageLevel.Error): void {
|
||||||
this._dialogObject.message = {
|
this._dialogObject.message = {
|
||||||
text: message,
|
text: message,
|
||||||
|
|||||||
@@ -5,22 +5,18 @@
|
|||||||
|
|
||||||
import * as azdata from 'azdata';
|
import * as azdata from 'azdata';
|
||||||
import * as vscode from 'vscode';
|
import * as vscode from 'vscode';
|
||||||
import { DatabaseMigration, getSqlMigrationServiceAuthKeys, getSqlMigrationServiceMonitoringData, regenerateSqlMigrationServiceAuthKey } from '../../api/azure';
|
import { DatabaseMigration, getSqlMigrationServiceMonitoringData } from '../../api/azure';
|
||||||
import { IconPathHelper } from '../../constants/iconPathHelper';
|
import { IconPathHelper } from '../../constants/iconPathHelper';
|
||||||
import * as constants from '../../constants/strings';
|
import * as constants from '../../constants/strings';
|
||||||
import { MigrationServiceContext } from '../../models/migrationLocalStorage';
|
import { MigrationServiceContext } from '../../models/migrationLocalStorage';
|
||||||
import * as styles from '../../constants/styles';
|
import * as styles from '../../constants/styles';
|
||||||
|
import { createAuthenticationKeyTable, createRegistrationInstructions, refreshAuthenticationKeyTable } from '../../api/utils';
|
||||||
|
|
||||||
const CONTROL_MARGIN = '10px';
|
const CONTROL_MARGIN = '10px';
|
||||||
const COLUMN_WIDTH = '50px';
|
|
||||||
const STRETCH_WIDTH = '100%';
|
const STRETCH_WIDTH = '100%';
|
||||||
const LABEL_MARGIN = '0 10px 0 10px';
|
const LABEL_MARGIN = '0 10px 0 10px';
|
||||||
const VALUE_MARGIN = '0 10px 10px 10px';
|
const VALUE_MARGIN = '0 10px 10px 10px';
|
||||||
const INFO_VALUE_MARGIN = '0 10px 0 0';
|
|
||||||
const ICON_SIZE = '28px';
|
const ICON_SIZE = '28px';
|
||||||
const IMAGE_SIZE = '21px';
|
|
||||||
const AUTH_KEY1 = 'authKey1';
|
|
||||||
const AUTH_KEY2 = 'authKey2';
|
|
||||||
|
|
||||||
export class SqlMigrationServiceDetailsDialog {
|
export class SqlMigrationServiceDetailsDialog {
|
||||||
|
|
||||||
@@ -35,7 +31,7 @@ export class SqlMigrationServiceDetailsDialog {
|
|||||||
this._dialog = azdata.window.createModelViewDialog(
|
this._dialog = azdata.window.createModelViewDialog(
|
||||||
'',
|
'',
|
||||||
'SqlMigrationServiceDetailsDialog',
|
'SqlMigrationServiceDetailsDialog',
|
||||||
580,
|
750,
|
||||||
'flyout');
|
'flyout');
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -62,7 +58,13 @@ export class SqlMigrationServiceDetailsDialog {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private async createServiceContent(view: azdata.ModelView, serviceContext: MigrationServiceContext, migration: DatabaseMigration): Promise<void> {
|
private async createServiceContent(view: azdata.ModelView, serviceContext: MigrationServiceContext, migration: DatabaseMigration): Promise<void> {
|
||||||
this._migrationServiceAuthKeyTable = this._createIrTable(view);
|
const instructions = createRegistrationInstructions(view, false);
|
||||||
|
await instructions.updateCssStyles({
|
||||||
|
...styles.BODY_CSS,
|
||||||
|
'margin': LABEL_MARGIN,
|
||||||
|
})
|
||||||
|
|
||||||
|
this._migrationServiceAuthKeyTable = createAuthenticationKeyTable(view, '50px', '100%');
|
||||||
const serviceNode = (await getSqlMigrationServiceMonitoringData(
|
const serviceNode = (await getSqlMigrationServiceMonitoringData(
|
||||||
serviceContext.azureAccount!,
|
serviceContext.azureAccount!,
|
||||||
serviceContext.subscription!,
|
serviceContext.subscription!,
|
||||||
@@ -88,11 +90,7 @@ export class SqlMigrationServiceDetailsDialog {
|
|||||||
this._createTextItem(view, serviceContext.migrationService?.properties.resourceGroup!, VALUE_MARGIN),
|
this._createTextItem(view, serviceContext.migrationService?.properties.resourceGroup!, VALUE_MARGIN),
|
||||||
this._createTextItem(view, constants.SQL_MIGRATION_SERVICE_DETAILS_IR_LABEL, LABEL_MARGIN),
|
this._createTextItem(view, constants.SQL_MIGRATION_SERVICE_DETAILS_IR_LABEL, LABEL_MARGIN),
|
||||||
this._createTextItem(view, serviceNodeName, VALUE_MARGIN),
|
this._createTextItem(view, serviceNodeName, VALUE_MARGIN),
|
||||||
this._createTextItem(
|
instructions,
|
||||||
view,
|
|
||||||
constants.SQL_MIGRATION_SERVICE_DETAILS_AUTH_KEYS_LABEL,
|
|
||||||
INFO_VALUE_MARGIN,
|
|
||||||
constants.SQL_MIGRATION_SERVICE_DETAILS_AUTH_KEYS_TITLE),
|
|
||||||
this._migrationServiceAuthKeyTable,
|
this._migrationServiceAuthKeyTable,
|
||||||
])
|
])
|
||||||
.withLayout({ flexFlow: 'column' })
|
.withLayout({ flexFlow: 'column' })
|
||||||
@@ -100,7 +98,16 @@ export class SqlMigrationServiceDetailsDialog {
|
|||||||
.component();
|
.component();
|
||||||
|
|
||||||
await view.initializeModel(flexContainer);
|
await view.initializeModel(flexContainer);
|
||||||
return await this._refreshAuthTable(view, serviceContext, migration);
|
|
||||||
|
await refreshAuthenticationKeyTable(
|
||||||
|
view,
|
||||||
|
this._migrationServiceAuthKeyTable,
|
||||||
|
serviceContext.azureAccount!,
|
||||||
|
serviceContext.subscription!,
|
||||||
|
serviceContext.migrationService?.properties.resourceGroup!,
|
||||||
|
serviceContext.migrationService?.location.toUpperCase()!,
|
||||||
|
serviceContext.migrationService!
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
private _createHeading(view: azdata.ModelView, migration: DatabaseMigration): azdata.FlexContainer {
|
private _createHeading(view: azdata.ModelView, migration: DatabaseMigration): azdata.FlexContainer {
|
||||||
@@ -164,153 +171,4 @@ export class SqlMigrationServiceDetailsDialog {
|
|||||||
})
|
})
|
||||||
.component();
|
.component();
|
||||||
}
|
}
|
||||||
|
|
||||||
private _createIrTable(view: azdata.ModelView): azdata.DeclarativeTableComponent {
|
|
||||||
return view.modelBuilder
|
|
||||||
.declarativeTable()
|
|
||||||
.withProps({
|
|
||||||
columns: [
|
|
||||||
this._createColumn(constants.NAME, COLUMN_WIDTH, azdata.DeclarativeDataType.string),
|
|
||||||
this._createColumn(constants.AUTH_KEY_COLUMN_HEADER, STRETCH_WIDTH, azdata.DeclarativeDataType.string),
|
|
||||||
this._createColumn('', COLUMN_WIDTH, azdata.DeclarativeDataType.component),
|
|
||||||
],
|
|
||||||
CSSStyles: {
|
|
||||||
'margin': VALUE_MARGIN,
|
|
||||||
'text-align': 'left',
|
|
||||||
},
|
|
||||||
})
|
|
||||||
.component();
|
|
||||||
}
|
|
||||||
|
|
||||||
private _createColumn(name: string, width: string, valueType: azdata.DeclarativeDataType): azdata.DeclarativeTableColumn {
|
|
||||||
return {
|
|
||||||
displayName: name,
|
|
||||||
valueType: valueType,
|
|
||||||
width: width,
|
|
||||||
isReadOnly: true,
|
|
||||||
rowCssStyles: {
|
|
||||||
...styles.BODY_CSS
|
|
||||||
},
|
|
||||||
headerCssStyles: {
|
|
||||||
...styles.BODY_CSS
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
private async _regenerateAuthKey(view: azdata.ModelView, serviceContext: MigrationServiceContext, migration: DatabaseMigration, keyName: string): Promise<void> {
|
|
||||||
const keys = await regenerateSqlMigrationServiceAuthKey(
|
|
||||||
serviceContext.azureAccount!,
|
|
||||||
serviceContext.subscription!,
|
|
||||||
serviceContext.migrationService?.properties.resourceGroup!,
|
|
||||||
serviceContext.migrationService?.properties.location?.toUpperCase()!,
|
|
||||||
serviceContext.migrationService?.name!,
|
|
||||||
keyName);
|
|
||||||
|
|
||||||
if (keys?.authKey1 && keyName === AUTH_KEY1) {
|
|
||||||
await this._updateTableCell(this._migrationServiceAuthKeyTable, 0, 1, keys.authKey1, constants.SERVICE_KEY1_LABEL);
|
|
||||||
}
|
|
||||||
else if (keys?.authKey2 && keyName === AUTH_KEY2) {
|
|
||||||
await this._updateTableCell(this._migrationServiceAuthKeyTable, 1, 1, keys.authKey2, constants.SERVICE_KEY2_LABEL);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private async _updateTableCell(table: azdata.DeclarativeTableComponent, row: number, col: number, value: string, keyName: string): Promise<void> {
|
|
||||||
const dataValues = table.dataValues!;
|
|
||||||
dataValues![row][col].value = value;
|
|
||||||
await table.setDataValues([]);
|
|
||||||
await table.setDataValues(dataValues);
|
|
||||||
await vscode.window.showInformationMessage(constants.AUTH_KEY_REFRESHED(keyName));
|
|
||||||
}
|
|
||||||
|
|
||||||
private async _refreshAuthTable(view: azdata.ModelView, serviceContext: MigrationServiceContext, migration: DatabaseMigration): Promise<void> {
|
|
||||||
const keys = await getSqlMigrationServiceAuthKeys(
|
|
||||||
serviceContext.azureAccount!,
|
|
||||||
serviceContext.subscription!,
|
|
||||||
serviceContext.migrationService?.properties.resourceGroup!,
|
|
||||||
serviceContext.migrationService?.location.toUpperCase()!,
|
|
||||||
serviceContext.migrationService?.name!);
|
|
||||||
|
|
||||||
const copyKey1Button = view.modelBuilder
|
|
||||||
.button()
|
|
||||||
.withProps({
|
|
||||||
title: constants.COPY_KEY1,
|
|
||||||
iconPath: IconPathHelper.copy,
|
|
||||||
height: IMAGE_SIZE,
|
|
||||||
width: IMAGE_SIZE,
|
|
||||||
ariaLabel: constants.COPY_KEY1,
|
|
||||||
})
|
|
||||||
.component();
|
|
||||||
|
|
||||||
this._disposables.push(copyKey1Button.onDidClick(async (e) => {
|
|
||||||
await vscode.env.clipboard.writeText(keys.authKey1);
|
|
||||||
void vscode.window.showInformationMessage(constants.SERVICE_KEY1_COPIED_HELP);
|
|
||||||
}));
|
|
||||||
|
|
||||||
const copyKey2Button = view.modelBuilder
|
|
||||||
.button()
|
|
||||||
.withProps({
|
|
||||||
title: constants.COPY_KEY2,
|
|
||||||
iconPath: IconPathHelper.copy,
|
|
||||||
height: IMAGE_SIZE,
|
|
||||||
width: IMAGE_SIZE,
|
|
||||||
ariaLabel: constants.COPY_KEY2,
|
|
||||||
})
|
|
||||||
.component();
|
|
||||||
|
|
||||||
this._disposables.push(copyKey2Button.onDidClick(async (e) => {
|
|
||||||
await vscode.env.clipboard.writeText(keys.authKey2);
|
|
||||||
void vscode.window.showInformationMessage(constants.SERVICE_KEY2_COPIED_HELP);
|
|
||||||
}));
|
|
||||||
|
|
||||||
const refreshKey1Button = view.modelBuilder
|
|
||||||
.button()
|
|
||||||
.withProps({
|
|
||||||
title: constants.REFRESH_KEY1,
|
|
||||||
iconPath: IconPathHelper.refresh,
|
|
||||||
height: IMAGE_SIZE,
|
|
||||||
width: IMAGE_SIZE,
|
|
||||||
ariaLabel: constants.REFRESH_KEY1,
|
|
||||||
})
|
|
||||||
.component();
|
|
||||||
this._disposables.push(refreshKey1Button.onDidClick(
|
|
||||||
async (e) => await this._regenerateAuthKey(view, serviceContext, migration, AUTH_KEY1)));
|
|
||||||
|
|
||||||
const refreshKey2Button = view.modelBuilder
|
|
||||||
.button()
|
|
||||||
.withProps({
|
|
||||||
title: constants.REFRESH_KEY2,
|
|
||||||
iconPath: IconPathHelper.refresh,
|
|
||||||
height: IMAGE_SIZE,
|
|
||||||
width: IMAGE_SIZE,
|
|
||||||
ariaLabel: constants.REFRESH_KEY2,
|
|
||||||
})
|
|
||||||
.component();
|
|
||||||
this._disposables.push(refreshKey2Button.onDidClick(
|
|
||||||
async (e) => await this._regenerateAuthKey(view, serviceContext, migration, AUTH_KEY2)));
|
|
||||||
|
|
||||||
await this._migrationServiceAuthKeyTable.updateProperties({
|
|
||||||
dataValues: [
|
|
||||||
[
|
|
||||||
{ value: constants.SERVICE_KEY1_LABEL },
|
|
||||||
{ value: keys.authKey1 },
|
|
||||||
{
|
|
||||||
value: view.modelBuilder
|
|
||||||
.flexContainer()
|
|
||||||
.withItems([copyKey1Button, refreshKey1Button])
|
|
||||||
.component()
|
|
||||||
}
|
|
||||||
],
|
|
||||||
[
|
|
||||||
{ value: constants.SERVICE_KEY2_LABEL },
|
|
||||||
{ value: keys.authKey2 },
|
|
||||||
{
|
|
||||||
value: view.modelBuilder
|
|
||||||
.flexContainer()
|
|
||||||
.withItems([copyKey2Button, refreshKey2Button])
|
|
||||||
.component()
|
|
||||||
}
|
|
||||||
]
|
|
||||||
]
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ import { MigrationMode, MigrationStateModel, NetworkContainerType, StateChangeEv
|
|||||||
import { CreateSqlMigrationServiceDialog } from '../dialog/createSqlMigrationService/createSqlMigrationServiceDialog';
|
import { CreateSqlMigrationServiceDialog } from '../dialog/createSqlMigrationService/createSqlMigrationServiceDialog';
|
||||||
import * as constants from '../constants/strings';
|
import * as constants from '../constants/strings';
|
||||||
import { WIZARD_INPUT_COMPONENT_WIDTH } from './wizardController';
|
import { WIZARD_INPUT_COMPONENT_WIDTH } from './wizardController';
|
||||||
import { getFullResourceGroupFromId, getSqlMigrationService, getSqlMigrationServiceAuthKeys, getSqlMigrationServiceMonitoringData, SqlVMServer } from '../api/azure';
|
import { getFullResourceGroupFromId, getSqlMigrationService, getSqlMigrationServiceMonitoringData, SqlVMServer } from '../api/azure';
|
||||||
import { IconPathHelper } from '../constants/iconPathHelper';
|
import { IconPathHelper } from '../constants/iconPathHelper';
|
||||||
import { logError, TelemetryViews } from '../telemetry';
|
import { logError, TelemetryViews } from '../telemetry';
|
||||||
import * as utils from '../api/utils';
|
import * as utils from '../api/utils';
|
||||||
@@ -27,10 +27,6 @@ export class IntergrationRuntimePage extends MigrationWizardPage {
|
|||||||
private _dmsStatusInfoBox!: azdata.InfoBoxComponent;
|
private _dmsStatusInfoBox!: azdata.InfoBoxComponent;
|
||||||
private _authKeyTable!: azdata.DeclarativeTableComponent;
|
private _authKeyTable!: azdata.DeclarativeTableComponent;
|
||||||
private _refreshButton!: azdata.ButtonComponent;
|
private _refreshButton!: azdata.ButtonComponent;
|
||||||
private _copy1!: azdata.ButtonComponent;
|
|
||||||
private _copy2!: azdata.ButtonComponent;
|
|
||||||
private _refresh1!: azdata.ButtonComponent;
|
|
||||||
private _refresh2!: azdata.ButtonComponent;
|
|
||||||
private _onlineButton!: azdata.RadioButtonComponent;
|
private _onlineButton!: azdata.RadioButtonComponent;
|
||||||
private _offlineButton!: azdata.RadioButtonComponent;
|
private _offlineButton!: azdata.RadioButtonComponent;
|
||||||
private _modeContainer!: azdata.FlexContainer;
|
private _modeContainer!: azdata.FlexContainer;
|
||||||
@@ -507,58 +503,13 @@ export class IntergrationRuntimePage extends MigrationWizardPage {
|
|||||||
CSSStyles: { ...styles.BODY_CSS }
|
CSSStyles: { ...styles.BODY_CSS }
|
||||||
}).component();
|
}).component();
|
||||||
|
|
||||||
const authenticationKeysLabel = this._view.modelBuilder.text()
|
const instructions = utils.createRegistrationInstructions(this._view, false);
|
||||||
.withProps({
|
|
||||||
value: constants.AUTHENTICATION_KEYS,
|
|
||||||
CSSStyles: { ...styles.LABEL_CSS }
|
|
||||||
}).component();
|
|
||||||
|
|
||||||
this._copy1 = this._view.modelBuilder.button()
|
this._authKeyTable = utils.createAuthenticationKeyTable(this._view, '50px', '500px');
|
||||||
.withProps({
|
|
||||||
title: constants.COPY_KEY1,
|
|
||||||
iconPath: IconPathHelper.copy,
|
|
||||||
ariaLabel: constants.COPY_KEY1,
|
|
||||||
}).component();
|
|
||||||
|
|
||||||
this._disposables.push(
|
|
||||||
this._copy1.onDidClick(
|
|
||||||
async (e) => {
|
|
||||||
await vscode.env.clipboard.writeText(<string>this._authKeyTable.dataValues![0][1].value);
|
|
||||||
void vscode.window.showInformationMessage(constants.SERVICE_KEY1_COPIED_HELP);
|
|
||||||
}));
|
|
||||||
|
|
||||||
this._copy2 = this._view.modelBuilder.button()
|
|
||||||
.withProps({
|
|
||||||
title: constants.COPY_KEY2,
|
|
||||||
iconPath: IconPathHelper.copy,
|
|
||||||
ariaLabel: constants.COPY_KEY2,
|
|
||||||
}).component();
|
|
||||||
|
|
||||||
this._disposables.push(
|
|
||||||
this._copy2.onDidClick(async (e) => {
|
|
||||||
await vscode.env.clipboard.writeText(<string>this._authKeyTable.dataValues![1][1].value);
|
|
||||||
void vscode.window.showInformationMessage(constants.SERVICE_KEY2_COPIED_HELP);
|
|
||||||
}));
|
|
||||||
|
|
||||||
this._refresh1 = this._view.modelBuilder.button()
|
|
||||||
.withProps({
|
|
||||||
title: constants.REFRESH_KEY1,
|
|
||||||
iconPath: IconPathHelper.refresh,
|
|
||||||
ariaLabel: constants.REFRESH_KEY1,
|
|
||||||
}).component();
|
|
||||||
|
|
||||||
this._refresh2 = this._view.modelBuilder.button()
|
|
||||||
.withProps({
|
|
||||||
title: constants.REFRESH_KEY2,
|
|
||||||
iconPath: IconPathHelper.refresh,
|
|
||||||
ariaLabel: constants.REFRESH_KEY2,
|
|
||||||
}).component();
|
|
||||||
|
|
||||||
this._authKeyTable = createAuthenticationKeyTable(this._view);
|
|
||||||
|
|
||||||
statusContainer.addItems([
|
statusContainer.addItems([
|
||||||
this._dmsStatusInfoBox,
|
this._dmsStatusInfoBox,
|
||||||
authenticationKeysLabel,
|
instructions,
|
||||||
this._authKeyTable]);
|
this._authKeyTable]);
|
||||||
|
|
||||||
container.addItems([
|
container.addItems([
|
||||||
@@ -686,53 +637,23 @@ export class IntergrationRuntimePage extends MigrationWizardPage {
|
|||||||
// exit if new call has started
|
// exit if new call has started
|
||||||
if (callSequence !== this._lastIn) { return; }
|
if (callSequence !== this._lastIn) { return; }
|
||||||
|
|
||||||
const migrationServiceAuthKeys = await getSqlMigrationServiceAuthKeys(
|
|
||||||
account,
|
|
||||||
subscription,
|
|
||||||
resourceGroup,
|
|
||||||
location,
|
|
||||||
serviceName);
|
|
||||||
|
|
||||||
// exit if new call has started
|
|
||||||
if (callSequence !== this._lastIn) { return; }
|
|
||||||
|
|
||||||
const state = migrationService.properties.integrationRuntimeState;
|
const state = migrationService.properties.integrationRuntimeState;
|
||||||
if (state === 'Online') {
|
if (state === 'Online') {
|
||||||
await this._dmsStatusInfoBox.updateProperties(<azdata.InfoBoxComponentProperties>{
|
await this._dmsStatusInfoBox.updateProperties(<azdata.InfoBoxComponentProperties>{
|
||||||
text: constants.SERVICE_READY(serviceName, nodeNames.join(', ')),
|
text: constants.SERVICE_READY(serviceName, nodeNames.join(', '), true),
|
||||||
style: 'success'
|
style: 'success'
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
await this._dmsStatusInfoBox.updateProperties(<azdata.InfoBoxComponentProperties>{
|
await this._dmsStatusInfoBox.updateProperties(<azdata.InfoBoxComponentProperties>{
|
||||||
text: constants.SERVICE_NOT_READY(serviceName),
|
text: constants.SERVICE_NOT_READY(serviceName, true),
|
||||||
style: 'error'
|
style: 'error'
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
const data = [
|
|
||||||
[
|
|
||||||
{ value: constants.SERVICE_KEY1_LABEL },
|
|
||||||
{ value: migrationServiceAuthKeys.authKey1 },
|
|
||||||
{
|
|
||||||
value: this._view.modelBuilder.flexContainer()
|
|
||||||
.withItems([this._copy1, this._refresh1])
|
|
||||||
.component()
|
|
||||||
}
|
|
||||||
],
|
|
||||||
[
|
|
||||||
{ value: constants.SERVICE_KEY2_LABEL },
|
|
||||||
{ value: migrationServiceAuthKeys.authKey2 },
|
|
||||||
{
|
|
||||||
value: this._view.modelBuilder.flexContainer()
|
|
||||||
.withItems([this._copy2, this._refresh2])
|
|
||||||
.component()
|
|
||||||
}
|
|
||||||
]];
|
|
||||||
|
|
||||||
// exit if new call has started
|
// exit if new call has started
|
||||||
if (callSequence !== this._lastIn) { return; }
|
if (callSequence !== this._lastIn) { return; }
|
||||||
|
|
||||||
await this._authKeyTable.setDataValues(data);
|
await utils.refreshAuthenticationKeyTable(this._view, this._authKeyTable, account, subscription, resourceGroup, location, migrationService);
|
||||||
|
|
||||||
this.migrationStateModel._sqlMigrationService = migrationService;
|
this.migrationStateModel._sqlMigrationService = migrationService;
|
||||||
this.migrationStateModel._sqlMigrationServiceSubscription = subscription;
|
this.migrationStateModel._sqlMigrationServiceSubscription = subscription;
|
||||||
@@ -752,38 +673,3 @@ export class IntergrationRuntimePage extends MigrationWizardPage {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function createAuthenticationKeyTable(view: azdata.ModelView,): azdata.DeclarativeTableComponent {
|
|
||||||
const authKeyTable = view.modelBuilder.declarativeTable()
|
|
||||||
.withProps({
|
|
||||||
ariaLabel: constants.DATABASE_MIGRATION_SERVICE_AUTHENTICATION_KEYS,
|
|
||||||
columns: [
|
|
||||||
{
|
|
||||||
displayName: constants.NAME,
|
|
||||||
valueType: azdata.DeclarativeDataType.string,
|
|
||||||
width: '50px',
|
|
||||||
isReadOnly: true,
|
|
||||||
rowCssStyles: { ...styles.BODY_CSS },
|
|
||||||
headerCssStyles: { ...styles.BODY_CSS, 'font-weight': '600' }
|
|
||||||
},
|
|
||||||
{
|
|
||||||
displayName: constants.AUTH_KEY_COLUMN_HEADER,
|
|
||||||
valueType: azdata.DeclarativeDataType.string,
|
|
||||||
width: '500px',
|
|
||||||
isReadOnly: true,
|
|
||||||
rowCssStyles: { ...styles.BODY_CSS },
|
|
||||||
headerCssStyles: { ...styles.BODY_CSS, 'font-weight': '600' }
|
|
||||||
},
|
|
||||||
{
|
|
||||||
displayName: '',
|
|
||||||
valueType: azdata.DeclarativeDataType.component,
|
|
||||||
width: '30px',
|
|
||||||
isReadOnly: true,
|
|
||||||
rowCssStyles: { ...styles.BODY_CSS },
|
|
||||||
headerCssStyles: { ...styles.BODY_CSS }
|
|
||||||
}
|
|
||||||
],
|
|
||||||
CSSStyles: { 'margin-top': '5px', 'width': WIZARD_INPUT_COMPONENT_WIDTH }
|
|
||||||
}).component();
|
|
||||||
return authKeyTable;
|
|
||||||
}
|
|
||||||
|
|||||||
Reference in New Issue
Block a user