Remove unused files in sql and extensions folders (#22444)

This commit is contained in:
Cory Rivera
2023-03-27 16:40:32 -07:00
committed by GitHub
parent e741fa0bbd
commit 97eb69477e
33 changed files with 20 additions and 3485 deletions

View File

@@ -3,16 +3,16 @@
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { ControllerInfo } from 'arc';
import { v4 as uuid } from 'uuid';
import { ControllerModel } from '../../models/controllerModel';
import { AzureArcTreeDataProvider } from '../../ui/tree/azureArcTreeDataProvider';
// import { ControllerInfo } from 'arc';
// import { v4 as uuid } from 'uuid';
// import { ControllerModel } from '../../models/controllerModel';
// import { AzureArcTreeDataProvider } from '../../ui/tree/azureArcTreeDataProvider';
export class FakeControllerModel extends ControllerModel {
// export class FakeControllerModel extends ControllerModel {
constructor(treeDataProvider?: AzureArcTreeDataProvider, info?: Partial<ControllerInfo>) {
const _info: ControllerInfo = Object.assign({ id: uuid(), endpoint: '', kubeConfigFilePath: '', kubeClusterContext: '', name: '', namespace: '', username: '', rememberPassword: false, resources: [], resourceGroup: '', connectionMode: '', location: '', customLocation: '' }, info);
super(treeDataProvider!, _info);
}
// constructor(treeDataProvider?: AzureArcTreeDataProvider, info?: Partial<ControllerInfo>) {
// const _info: ControllerInfo = Object.assign({ id: uuid(), endpoint: '', kubeConfigFilePath: '', kubeClusterContext: '', name: '', namespace: '', username: '', rememberPassword: false, resources: [], resourceGroup: '', connectionMode: '', location: '', customLocation: '' }, info);
// super(treeDataProvider!, _info);
// }
}
// }

View File

@@ -1,66 +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 vscode from 'vscode';
import * as azdata from 'azdata';
import * as loc from '../../../localizedConstants';
import { IconPathHelper, cssStyles } from '../../../constants';
import { DashboardPage } from '../../components/dashboardPage';
import { PostgresModel } from '../../../models/postgresModel';
import { ControllerModel } from '../../../models/controllerModel';
export class PostgresDiagnoseAndSolveProblemsPage extends DashboardPage {
constructor(modelView: azdata.ModelView, dashboard: azdata.window.ModelViewDashboard, private _context: vscode.ExtensionContext, private _controllerModel: ControllerModel, private _postgresModel: PostgresModel) {
super(modelView, dashboard);
}
protected get title(): string {
return loc.diagnoseAndSolveProblems;
}
protected get id(): string {
return 'postgres-diagnose-and-solve-problems';
}
protected get icon(): { dark: string; light: string; } {
return IconPathHelper.wrench;
}
protected get container(): azdata.Component {
const root = this.modelView.modelBuilder.divContainer().component();
const content = this.modelView.modelBuilder.divContainer().component();
root.addItem(content, { CSSStyles: { 'margin': '20px' } });
content.addItem(this.modelView.modelBuilder.text().withProps({
value: loc.diagnoseAndSolveProblems,
CSSStyles: { ...cssStyles.title, 'margin-bottom': '20px' }
}).component());
content.addItem(this.modelView.modelBuilder.text().withProps({
value: loc.clickTheTroubleshootButton('Postgres'),
CSSStyles: { ...cssStyles.text, 'margin-bottom': '20px' }
}).component());
const troubleshootButton = this.modelView.modelBuilder.button().withProps({
iconPath: IconPathHelper.wrench,
label: loc.troubleshoot,
width: '160px'
}).component();
this.disposables.push(
troubleshootButton.onDidClick(() => {
process.env['POSTGRES_SERVER_NAMESPACE'] = this._controllerModel.controllerConfig?.metadata.namespace ?? '';
process.env['POSTGRES_SERVER_NAME'] = this._postgresModel.info.name;
vscode.commands.executeCommand('bookTreeView.openBook', this._context.asAbsolutePath('notebooks/arcDataServices'), true, 'postgres/tsg100-troubleshoot-postgres');
}));
content.addItem(troubleshootButton);
return root;
}
protected get toolbarContainer(): azdata.ToolbarContainer {
return this.modelView.modelBuilder.toolbarContainer().component();
}
}

View File

@@ -1,119 +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 vscode from 'vscode';
import * as azdata from 'azdata';
import * as loc from '../../../localizedConstants';
import { IconPathHelper, cssStyles } from '../../../constants';
import { KeyValueContainer, KeyValue, InputKeyValue, TextKeyValue, LinkKeyValue } from '../../components/keyValueContainer';
import { DashboardPage } from '../../components/dashboardPage';
import { ControllerModel } from '../../../models/controllerModel';
import { PostgresModel } from '../../../models/postgresModel';
import { ControllerDashboard } from '../controller/controllerDashboard';
export class PostgresPropertiesPage extends DashboardPage {
private loading?: azdata.LoadingComponent;
private keyValueContainer?: KeyValueContainer;
constructor(modelView: azdata.ModelView, dashboard: azdata.window.ModelViewDashboard, private _controllerModel: ControllerModel, private _postgresModel: PostgresModel) {
super(modelView, dashboard);
this.disposables.push(this._postgresModel.onConfigUpdated(
() => this.eventuallyRunOnInitialized(() => this.handleServiceUpdated())));
this.disposables.push(this._controllerModel.onRegistrationsUpdated(
() => this.eventuallyRunOnInitialized(() => this.handleRegistrationsUpdated())));
}
protected get title(): string {
return loc.properties;
}
protected get id(): string {
return 'postgres-properties';
}
protected get icon(): { dark: string; light: string; } {
return IconPathHelper.properties;
}
protected get container(): azdata.Component {
const root = this.modelView.modelBuilder.divContainer().component();
const content = this.modelView.modelBuilder.divContainer().component();
root.addItem(content, { CSSStyles: { 'margin': '20px' } });
content.addItem(this.modelView.modelBuilder.text().withProps({
value: loc.properties,
CSSStyles: { ...cssStyles.title, 'margin-bottom': '25px' }
}).component());
this.keyValueContainer = new KeyValueContainer(this.modelView.modelBuilder, this.getProperties());
this.keyValueContainer.container.updateCssStyles({ 'max-width': '750px' });
this.disposables.push(this.keyValueContainer);
this.loading = this.modelView.modelBuilder.loadingComponent()
.withItem(this.keyValueContainer.container)
.withProps({
loading: !this._postgresModel.configLastUpdated && !this._controllerModel.registrationsLastUpdated
}).component();
content.addItem(this.loading);
this.initialized = true;
return root;
}
protected get toolbarContainer(): azdata.ToolbarContainer {
const refreshButton = this.modelView.modelBuilder.button().withProps({
label: loc.refresh,
iconPath: IconPathHelper.refresh
}).component();
this.disposables.push(
refreshButton.onDidClick(async () => {
refreshButton.enabled = false;
try {
this.loading!.loading = true;
await Promise.all([
this._postgresModel.refresh(),
this._controllerModel.refresh(false, this._controllerModel.info.namespace)
]);
} catch (error) {
vscode.window.showErrorMessage(loc.refreshFailed(error));
}
finally {
refreshButton.enabled = true;
}
}));
return this.modelView.modelBuilder.toolbarContainer().withToolbarItems([
{ component: refreshButton }
]).component();
}
private getProperties(): KeyValue[] {
const endpoint = this._postgresModel.endpoint;
const status = this._postgresModel.config?.status;
const controllerDashboard = new ControllerDashboard(this._controllerModel);
return [
new InputKeyValue(this.modelView.modelBuilder, loc.coordinatorEndpoint, endpoint ? `postgresql://postgres@${endpoint.ip}:${endpoint.port}` : ''),
new InputKeyValue(this.modelView.modelBuilder, loc.postgresAdminUsername, 'postgres'),
new InputKeyValue(this.modelView.modelBuilder, loc.subscriptionId, this._controllerModel.controllerConfig?.spec.settings.azure.subscription ?? ''),
new TextKeyValue(this.modelView.modelBuilder, loc.resourceGroup, this._controllerModel.controllerConfig?.spec.settings.azure.resourceGroup ?? ''),
new LinkKeyValue(this.modelView.modelBuilder, loc.dataController, this._controllerModel.controllerConfig?.metadata.name ?? '', () => controllerDashboard.showDashboard()),
new TextKeyValue(this.modelView.modelBuilder, loc.status, status ? `${status.state} (${status.readyPods} ${loc.podsReady})` : loc.unknown)
];
}
private handleRegistrationsUpdated() {
this.keyValueContainer?.refresh(this.getProperties());
this.loading!.loading = false;
}
private handleServiceUpdated() {
this.keyValueContainer?.refresh(this.getProperties());
this.loading!.loading = false;
}
}

View File

@@ -1,348 +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 vscode from 'vscode';
import * as azdata from 'azdata';
import * as loc from '../../../localizedConstants';
import { IconPathHelper, cssStyles, iconSize } from '../../../constants';
import { DashboardPage } from '../../components/dashboardPage';
import { PostgresModel } from '../../../models/postgresModel';
export type PodHealthModel = {
condition: string,
details: azdata.Component,
lastUpdate: string
};
export enum PodConditionType {
initialized = 'Initialized',
ready = 'Ready',
containersReady = 'ContainersReady',
podScheduled = 'PodScheduled'
}
export class PostgresResourceHealthPage extends DashboardPage {
private podSummaryContainer!: azdata.DivContainer;
private podConditionsContainer!: azdata.DivContainer;
private podConditionsLoading!: azdata.LoadingComponent;
private podConditionsTable!: azdata.DeclarativeTableComponent;
private podConditionsTableIndexes: Map<string, number[]> = new Map();
private podDropDown!: azdata.DropDownComponent;
private coordinatorPodName!: string;
private coordinatorData: PodHealthModel[] = [];
private podsData: PodHealthModel[] = [];
constructor(modelView: azdata.ModelView, dashboard: azdata.window.ModelViewDashboard, private _postgresModel: PostgresModel) {
super(modelView, dashboard);
this.disposables.push(
this._postgresModel.onConfigUpdated(() => this.eventuallyRunOnInitialized(() => this.handleConfigUpdated())));
}
protected get title(): string {
return loc.resourceHealth;
}
protected get id(): string {
return 'postgres-resource-health';
}
protected get icon(): { dark: string; light: string; } {
return IconPathHelper.health;
}
protected get container(): azdata.Component {
const root = this.modelView.modelBuilder.divContainer().component();
const content = this.modelView.modelBuilder.divContainer().component();
root.addItem(content, { CSSStyles: { 'margin': '10px 20px 0px 20px' } });
content.addItem(this.modelView.modelBuilder.text().withProps({
value: loc.resourceHealth,
CSSStyles: { ...cssStyles.title }
}).component());
content.addItem(this.modelView.modelBuilder.text().withProps({
value: loc.resourceHealthDescription,
CSSStyles: { ...cssStyles.text, 'margin-block-start': '0px', 'margin-block-end': '0px' }
}).component());
this.podSummaryContainer = this.modelView.modelBuilder.divContainer().component();
this.refreshPodSummarySection();
content.addItem(this.podSummaryContainer);
// Pod Conditions
content.addItem(this.modelView.modelBuilder.text().withProps({
value: loc.podsPresent,
CSSStyles: { ...cssStyles.title }
}).component());
content.addItem(this.modelView.modelBuilder.text().withProps({
value: loc.podsUsedDescription,
CSSStyles: { ...cssStyles.text, 'margin-block-start': '0px', 'margin-block-end': '0px', 'margin-top': '10px' }
}).component());
this.podConditionsContainer = this.modelView.modelBuilder.divContainer().component();
this.podConditionsTable = this.modelView.modelBuilder.declarativeTable().withProps({
width: '100%',
ariaLabel: loc.podConditionsTable,
columns: [
{
displayName: loc.condition,
valueType: azdata.DeclarativeDataType.string,
isReadOnly: true,
width: '20%',
headerCssStyles: cssStyles.tableHeader,
rowCssStyles: cssStyles.tableRow
},
{
displayName: loc.details,
valueType: azdata.DeclarativeDataType.component,
isReadOnly: true,
width: '50%',
headerCssStyles: cssStyles.tableHeader,
rowCssStyles: {
...cssStyles.tableRow,
'min-width': '150px'
}
},
{
displayName: loc.lastTransition,
valueType: azdata.DeclarativeDataType.string,
isReadOnly: true,
width: '30%',
headerCssStyles: cssStyles.tableHeader,
rowCssStyles: cssStyles.tableRow
}
],
dataValues: this.createPodConditionsDataValues(this.coordinatorData)
}).component();
this.podDropDown = this.modelView.modelBuilder.dropDown().withProps({
width: '150px',
ariaLabel: loc.podsUsedDescriptionAria
}).component();
this.disposables.push(
this.podDropDown.onValueChanged(() => {
this.podConditionsTable.setFilter(this.podConditionsTableIndexes.get(String(this.podDropDown.value)));
})
);
this.podConditionsContainer.addItem(this.podDropDown, { CSSStyles: { 'margin': '10px 0px 10px 0px' } });
this.podConditionsContainer.addItem(this.podConditionsTable);
this.podConditionsLoading = this.modelView.modelBuilder.loadingComponent()
.withItem(this.podConditionsContainer)
.withProps({
loading: !this._postgresModel.configLastUpdated
}).component();
this.refreshPodConditions();
content.addItem(this.podConditionsLoading, { CSSStyles: cssStyles.text });
this.initialized = true;
return root;
}
protected get toolbarContainer(): azdata.ToolbarContainer {
// Refresh
const refreshButton = this.modelView.modelBuilder.button().withProps({
label: loc.refresh,
iconPath: IconPathHelper.refresh
}).component();
this.disposables.push(
refreshButton.onDidClick(async () => {
refreshButton.enabled = false;
try {
this.podConditionsLoading!.loading = true;
await this._postgresModel.refresh();
} catch (error) {
vscode.window.showErrorMessage(loc.refreshFailed(error));
}
finally {
refreshButton.enabled = true;
}
}));
return this.modelView.modelBuilder.toolbarContainer().withToolbarItems([
{ component: refreshButton }
]).component();
}
private createPodList(): string[] {
const podStatus = this._postgresModel.config?.status.podsStatus;
let podNames: string[] = [];
podStatus?.forEach(p => {
let podHealthModels: PodHealthModel[] = [];
let indexes: number[] = [];
p.conditions.forEach(c => {
let message: string;
let imageComponent = this.modelView.modelBuilder.image().withProps({
width: iconSize,
height: iconSize,
iconHeight: '15px',
iconWidth: '15px'
}).component();
if (c.status === 'False') {
imageComponent.iconPath = IconPathHelper.fail;
message = c.message ?? c.reason ?? '';
} else {
imageComponent.iconPath = IconPathHelper.success;
if (c.type === PodConditionType.initialized) {
message = loc.podInitialized;
} else if (c.type === PodConditionType.ready) {
message = loc.podReady;
} else if (c.type === PodConditionType.containersReady) {
message = loc.containerReady;
} else if (c.type === PodConditionType.podScheduled) {
message = loc.podScheduled;
} else {
message = c.message ?? c.reason ?? '';
}
}
const conditionContainer = this.modelView.modelBuilder.flexContainer().withProps({
CSSStyles: { 'alignItems': 'center', 'height': '15px' }
}).component();
conditionContainer.addItem(imageComponent, { CSSStyles: { 'margin-right': '0px' } });
conditionContainer.addItem(this.modelView.modelBuilder.text().withProps({
value: message,
}).component());
indexes.push(this.podsData.length);
this.podsData.push({
condition: c.type,
details: conditionContainer,
lastUpdate: c.lastTransitionTime
});
});
if (p.role.toUpperCase() !== loc.coordinator.toUpperCase()) {
podNames.push(p.name);
} else {
this.coordinatorData = podHealthModels;
this.coordinatorPodName = p.name;
podNames.unshift(p.name);
}
this.podConditionsTableIndexes.set(p.name, indexes);
});
this.podConditionsTable.setDataValues(this.createPodConditionsDataValues(this.podsData));
return podNames;
}
private createPodConditionsDataValues(podInfo: PodHealthModel[]): azdata.DeclarativeTableCellValue[][] {
let podDataValues: (string | azdata.Component)[][] = podInfo.map(p => [p.condition, p.details, p.lastUpdate]);
return podDataValues.map(p => {
return p.map((value): azdata.DeclarativeTableCellValue => {
return { value: value };
});
});
}
private findPodIssues(): string[] {
const podStatus = this._postgresModel.config?.status.podsStatus;
let issueCount = 0;
let podIssuesDetected: string[] = [];
podStatus?.forEach(p => {
p.conditions.forEach(c => {
if (c.status === 'False') {
issueCount++;
}
});
if (issueCount > 0) {
podIssuesDetected.push(loc.numberOfIssuesDetected(p.name, issueCount));
issueCount = 0;
}
});
return podIssuesDetected;
}
private refreshPodSummarySection(): void {
let podSummaryTitle = this.modelView.modelBuilder.flexContainer().withProps({
CSSStyles: { 'alignItems': 'center', 'height': '15px', 'margin-top': '20px' }
}).component();
if (!this._postgresModel.config) {
podSummaryTitle.addItem(this.modelView.modelBuilder.loadingComponent().component(), { CSSStyles: { 'margin-right': '5px' } });
podSummaryTitle.addItem(this.modelView.modelBuilder.text().withProps({
value: loc.loading,
CSSStyles: { ...cssStyles.title }
}).component());
this.podSummaryContainer.addItem(podSummaryTitle);
} else {
let components: azdata.Component[] = [];
let imageComponent = this.modelView.modelBuilder.image().withProps({
iconPath: IconPathHelper.success,
width: iconSize,
height: iconSize,
iconHeight: '20px',
iconWidth: '20px'
}).component();
let podIssues = this.findPodIssues();
if (podIssues.length === 0) {
imageComponent.iconPath = IconPathHelper.success;
podSummaryTitle.addItem(imageComponent, { CSSStyles: { 'margin-right': '5px' } });
podSummaryTitle.addItem(this.modelView.modelBuilder.text().withProps({
value: loc.available,
CSSStyles: { ...cssStyles.title, 'margin-left': '0px' }
}).component());
components.push(podSummaryTitle);
components.push(this.modelView.modelBuilder.text().withProps({
value: loc.noPodIssuesDetected,
CSSStyles: { ...cssStyles.text, 'margin-top': '20px' }
}).component());
} else {
imageComponent.iconPath = IconPathHelper.fail;
podSummaryTitle.addItem(imageComponent, { CSSStyles: { 'margin-right': '5px' } });
podSummaryTitle.addItem(this.modelView.modelBuilder.text().withProps({
value: loc.issuesDetected,
CSSStyles: { ...cssStyles.title }
}).component());
components.push(podSummaryTitle);
components.push(this.modelView.modelBuilder.text().withProps({
value: loc.podIssuesDetected,
CSSStyles: { ...cssStyles.text, 'margin-top': '20px 0px 10px 0px' }
}).component());
components.push(...podIssues.map(i => {
return this.modelView.modelBuilder.text().withProps({
value: i,
CSSStyles: { ...cssStyles.text, 'margin': '0px' }
}).component();
}));
}
this.podSummaryContainer.addItems(components);
}
}
private refreshPodConditions(): void {
if (this._postgresModel.config) {
this.podConditionsTableIndexes = new Map();
this.podsData = [];
this.podDropDown.values = this.createPodList();
this.podConditionsTable.setFilter(this.podConditionsTableIndexes.get(this.coordinatorPodName!));
this.podConditionsLoading.loading = false;
}
}
private handleConfigUpdated() {
this.podSummaryContainer.clearItems();
this.refreshPodSummarySection();
this.refreshPodConditions();
}
}

View File

@@ -1,99 +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 { Deferred } from '../../common/promise';
import * as loc from '../../localizedConstants';
import { cssStyles } from '../../constants';
import { InitializingComponent } from '../components/initializingComponent';
import { PostgresModel } from '../../models/postgresModel';
export const validExtensions = ['citus', 'pgaudit', 'pgautofailover', 'pg_cron', 'pg_partman', 'plv8', 'postgis', 'postgis_raster', 'postgis_sfcgal', 'postgis_tiger_geocoder', 'tdigest'];
export class AddPGExtensionsDialog extends InitializingComponent {
protected modelBuilder!: azdata.ModelBuilder;
protected extensionsListInputBox!: azdata.InputBoxComponent;
protected _completionPromise = new Deferred<string | undefined>();
constructor(protected _model: PostgresModel) {
super();
}
public showDialog(dialogTitle: string): azdata.window.Dialog {
const dialog = azdata.window.createModelViewDialog(dialogTitle);
dialog.cancelButton.onClick(() => this.handleCancel());
dialog.registerContent(async view => {
this.modelBuilder = view.modelBuilder;
const info = this.modelBuilder.text().withProps({
value: loc.extensionsAddFunction(validExtensions.join(', ')),
CSSStyles: { ...cssStyles.text, 'margin-block-start': '0px', 'margin-block-end': '0px' }
}).component();
const link = this.modelBuilder.hyperlink().withProps({
label: loc.extensionsLearnMore,
url: 'https://docs.microsoft.com/azure/azure-arc/data/using-extensions-in-postgresql-hyperscale-server-group',
}).component();
const infoAndLink = this.modelBuilder.flexContainer().withLayout({ flexWrap: 'wrap' }).component();
infoAndLink.addItem(info, { CSSStyles: { 'margin-right': '5px' } });
infoAndLink.addItem(link);
this.extensionsListInputBox = this.modelBuilder.inputBox()
.withProps({
value: '',
ariaLabel: loc.extensionsAddList,
enabled: true,
validationErrorMessage: loc.extensionsAddErrorrMessage(validExtensions.join(','))
}).withValidation((component) => {
if (!component.value) {
return true;
}
let newExtensions = component.value.split(',');
return newExtensions.every(e => validExtensions.includes(e));
}).component();
let formModel = this.modelBuilder.formContainer()
.withFormItems([{
components: [
{
component: infoAndLink
},
{
component: this.extensionsListInputBox,
title: loc.extensionsAddList,
required: true
}
],
title: ''
}]).withLayout({ width: '100%' }).component();
await view.initializeModel(formModel);
this.extensionsListInputBox.focus();
this.initialized = true;
});
dialog.registerCloseValidator(async () => await this.validate());
dialog.okButton.label = loc.loadExtensions;
dialog.cancelButton.label = loc.cancel;
azdata.window.openDialog(dialog);
return dialog;
}
public async validate(): Promise<boolean> {
this._completionPromise.resolve(this.extensionsListInputBox.value);
return true;
}
private handleCancel(): void {
this._completionPromise.resolve(undefined);
}
public waitForClose(): Promise<string | undefined> {
return this._completionPromise.promise;
}
}

View File

@@ -1,15 +0,0 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
interface PlatformReleaseInfo {
version: string; // "20.0.1"
link?: string; // "https://aka.ms/az-msi"
}
export interface AzReleaseInfo {
win32: PlatformReleaseInfo,
darwin: PlatformReleaseInfo,
linux: PlatformReleaseInfo
}

View File

@@ -9,12 +9,12 @@
* @param promise The promise to verify was rejected
* @param message The message to include in the error if the promise isn't rejected
*/
export async function assertRejected(promise: Promise<any>, message: string): Promise<void> {
try {
await promise;
} catch {
return;
}
throw new Error(message);
}
// export async function assertRejected(promise: Promise<any>, message: string): Promise<void> {
// try {
// await promise;
// } catch {
// return;
// }
// throw new Error(message);
// }

View File

@@ -1,214 +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 vscode from 'vscode';
import * as azdata from 'azdata';
import { AppContext } from '../../appContext';
import * as nls from 'vscode-nls';
const localize = nls.loadMessageBundle();
import { TreeNode } from '../treeNode';
import { AzureResourceMessageTreeNode } from '../messageTreeNode';
import { AzureResourceContainerTreeNodeBase } from './baseTreeNodes';
import { AzureResourceErrorMessageUtil, filterAccounts } from '../utils';
import { IAzureResourceTreeChangeHandler } from './treeChangeHandler';
import { IAzureResourceNodeWithProviderId, IAzureResourceSubscriptionService } from '../interfaces';
import { AzureResourceServiceNames } from '../constants';
import { AzureResourceService } from '../resourceService';
import { Logger } from '../../utils/Logger';
export class FlatAzureResourceTreeProvider implements vscode.TreeDataProvider<TreeNode>, IAzureResourceTreeChangeHandler {
public isSystemInitialized: boolean = false;
private _onDidChangeTreeData = new vscode.EventEmitter<TreeNode | undefined>();
private resourceLoader: ResourceLoader | undefined;
public constructor(private readonly appContext: AppContext,
private readonly authLibrary: string) {
}
public async getChildren(element?: TreeNode): Promise<TreeNode[]> {
if (element) {
return element.getChildren(true);
}
if (!this.resourceLoader) {
this.resourceLoader = new ResourceLoader(this.appContext, this.authLibrary);
this.resourceLoader.onDidAddNewResource(e => this._onDidChangeTreeData.fire(e));
}
if (this.resourceLoader.state === LoaderState.NotStarted) {
this.resourceLoader.start().catch(err => console.error('Error loading Azure Resources for FlatAzureResourceTreeProvider ', err));
return [AzureResourceMessageTreeNode.create(localize('azure.resource.tree.treeProvider.loadingLabel', "Loading ..."), undefined)];
}
return this.resourceLoader.children;
}
public get onDidChangeTreeData(): vscode.Event<TreeNode | undefined> {
return this._onDidChangeTreeData.event;
}
public notifyNodeChanged(node: TreeNode): void {
this._onDidChangeTreeData.fire(node);
}
public async refresh(node: TreeNode, isClearingCache: boolean): Promise<void> {
if (isClearingCache) {
if ((node instanceof AzureResourceContainerTreeNodeBase)) {
node.clearCache();
}
}
this._onDidChangeTreeData.fire(node);
}
public getTreeItem(element: TreeNode): vscode.TreeItem | Thenable<vscode.TreeItem> {
return element.getTreeItem();
}
}
enum LoaderState {
NotStarted,
Loading,
Complete
}
class ResourceLoader {
private _state: LoaderState = LoaderState.NotStarted;
private readonly resourceGroups = new Map<string, AzureResourceResourceTreeNode>();
private readonly subscriptionService: IAzureResourceSubscriptionService;
private readonly resourceService: AzureResourceService;
private readonly _onDidAddNewResource = new vscode.EventEmitter<TreeNode | undefined>();
public readonly onDidAddNewResource = this._onDidAddNewResource.event;
constructor(private readonly appContext: AppContext,
private readonly authLibrary: string) {
this.subscriptionService = appContext.getService<IAzureResourceSubscriptionService>(AzureResourceServiceNames.subscriptionService);
this.resourceService = appContext.getService<AzureResourceService>(AzureResourceServiceNames.resourceService);
}
get state(): LoaderState {
return this._state;
}
get children(): AzureResourceResourceTreeNode[] {
return Array.from(this.resourceGroups.values());
}
async start(): Promise<void> {
if (this.state === LoaderState.Loading) {
throw new Error('Resource Loader already loading');
}
let doRefresh = false;
// if we just fire every time we get an a new resource we crash the application
// this effectively buffers the event so that we don't cause hangs.
let interval = setInterval(() => {
if (doRefresh) {
doRefresh = false;
this._onDidAddNewResource.fire(undefined);
}
}, 500);
this._state = LoaderState.Loading;
const accounts = filterAccounts(await azdata.accounts.getAllAccounts(), this.authLibrary);
for (const account of accounts) {
for (const tenant of account.properties.tenants) {
for (const subscription of await this.subscriptionService.getSubscriptions(account, [tenant.id])) {
for (const providerId of await this.resourceService.listResourceProviderIds()) {
for (const group of await this.resourceService.getRootChildren(providerId, account, subscription)) {
const children = await this.resourceService.getChildren(providerId, group.resourceNode);
let groupNode: AzureResourceResourceTreeNode | undefined = this.resourceGroups.get(group.resourceProviderId);
if (groupNode) {
groupNode.pushItems(...children);
} else {
groupNode = new AzureResourceResourceTreeNode(group, this.appContext);
this.resourceGroups.set(group.resourceProviderId, groupNode);
groupNode.pushItems(...children);
}
doRefresh = true;
}
}
}
}
}
Logger.verbose('finished loading all accounts and subscriptions');
clearInterval(interval);
this._state = LoaderState.Complete;
}
}
class AzureResourceResourceTreeNode extends TreeNode {
private _resourceService: AzureResourceService;
public constructor(
public readonly resourceNodeWithProviderId: IAzureResourceNodeWithProviderId,
private appContext: AppContext
) {
super();
this._resourceService = appContext.getService<AzureResourceService>(AzureResourceServiceNames.resourceService);
}
private _children: IAzureResourceNodeWithProviderId[] = [];
pushItems(...items: IAzureResourceNodeWithProviderId[]): void {
this._children.push(...items);
}
public async getChildren(): Promise<TreeNode[]> {
// It is a leaf node.
try {
if (this._children.length === 0) {
return [AzureResourceMessageTreeNode.create(localize('azure.resource.resourceTreeNode.noResourcesLabel', "No Resources found"), this)];
} else {
return this._children.map((child) => {
// To make tree node's id unique, otherwise, treeModel.js would complain 'item already registered'
child.resourceNode.treeItem.id = `${this.resourceNodeWithProviderId.resourceNode.treeItem.id}.${child.resourceNode.treeItem.id}`;
return new AzureResourceResourceTreeNode(child, this.appContext);
});
}
} catch (error) {
return [AzureResourceMessageTreeNode.create(AzureResourceErrorMessageUtil.getErrorMessage(error), this)];
}
}
public getTreeItem(): vscode.TreeItem | Promise<vscode.TreeItem> {
return this._resourceService.getTreeItem(this.resourceNodeWithProviderId.resourceProviderId, this.resourceNodeWithProviderId.resourceNode);
}
public getNodeInfo(): azdata.NodeInfo {
const treeItem = this.resourceNodeWithProviderId.resourceNode.treeItem;
return {
label: <any>treeItem.label,
isLeaf: treeItem.collapsibleState === vscode.TreeItemCollapsibleState.None ? true : false,
errorMessage: undefined,
metadata: undefined,
nodePath: this.generateNodePath(),
parentNodePath: this.parent?.generateNodePath() ?? '',
nodeStatus: undefined,
nodeType: treeItem.contextValue || '',
nodeSubType: undefined,
iconType: treeItem.contextValue
};
}
public get nodePathValue(): string {
return this.resourceNodeWithProviderId.resourceNode.treeItem.id || '';
}
}

View File

@@ -1,33 +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';
/**
* Mock CredentialsProvider to be used for testing
*/
export class CredentialsTestProvider implements azdata.CredentialProvider {
handle: number = 0;
public storedCredentials: { [K: string]: azdata.Credential } = {};
saveCredential(credentialId: string, password: string): Thenable<boolean> {
this.storedCredentials[credentialId] = {
credentialId: credentialId,
password: password
};
return Promise.resolve(true);
}
readCredential(credentialId: string): Thenable<azdata.Credential> {
return Promise.resolve(this.storedCredentials[credentialId]);
}
deleteCredential(credentialId: string): Thenable<boolean> {
let exists = this.storedCredentials[credentialId] !== undefined;
delete this.storedCredentials[credentialId];
return Promise.resolve(exists);
}
}

View File

@@ -1,25 +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 { Transform } from 'stream';
import * as vscode from 'vscode';
import * as nls from 'vscode-nls';
const localize = nls.loadMessageBundle();
export class CancelableStream extends Transform {
constructor(private cancelationToken: vscode.CancellationTokenSource) {
super();
}
public override _transform(chunk: any, _encoding: string, callback: Function): void {
if (this.cancelationToken && this.cancelationToken.token.isCancellationRequested) {
callback(new Error(localize('streamCanceled', 'Stream operation canceled by the user')));
} else {
this.push(chunk);
callback();
}
}
}

View File

@@ -1,77 +0,0 @@
// This code is originally from https://github.com/DonJayamanne/bowerVSCode
// License: https://github.com/DonJayamanne/bowerVSCode/blob/master/LICENSE
import { window } from 'vscode';
import PromptFactory from './factory';
import EscapeException from './escapeException';
import { IQuestion, IPrompter, IPromptCallback, Answers } from './question';
// Supports simple pattern for prompting for user input and acting on this
export default class CodeAdapter implements IPrompter {
// TODO define question interface
private fixQuestion(question: IQuestion): any {
if (question.type === 'checkbox' && Array.isArray(question.choices)) {
// For some reason when there's a choice of checkboxes, they aren't formatted properly
// Not sure where the issue is
question.choices = question.choices.map(item => {
if (typeof (item) === 'string') {
return { checked: false, name: item, value: item };
} else {
return item;
}
});
}
}
public async promptSingle<T>(question: IQuestion, ignoreFocusOut?: boolean): Promise<T | undefined> {
let questions: IQuestion[] = [question];
const answers = await this.prompt<T>(questions, ignoreFocusOut);
if (answers) {
let response: T = answers[question.name];
return response || undefined;
}
return undefined;
}
public async prompt<T>(questions: IQuestion[], ignoreFocusOut?: boolean): Promise<Answers<T> | undefined> {
// Collapse multiple questions into a set of prompt steps
const promptResult = new Promise<Answers<T>>((resolve) => {
let answers: Answers<T> = {};
questions.forEach(async (question: IQuestion) => {
this.fixQuestion(question);
const prompt = PromptFactory.createPrompt(question, ignoreFocusOut);
if (!question.shouldPrompt || question.shouldPrompt(answers) === true) {
const result = await prompt.render();
answers[question.name] = result;
if (question.onAnswered) {
question.onAnswered(result);
}
return;
}
});
resolve(answers);
});
try {
return await promptResult;
} catch (err) {
if (err instanceof EscapeException || err instanceof TypeError) {
window.showErrorMessage(err.message);
}
return undefined;
}
}
// Helper to make it possible to prompt using callback pattern. Generally Promise is a preferred flow
public promptCallback(questions: IQuestion[], callback: IPromptCallback | undefined): void {
// Collapse multiple questions into a set of prompt steps
this.prompt(questions).then(answers => {
if (callback && answers) {
callback(answers);
}
});
}
}

View File

@@ -1,70 +0,0 @@
'use strict';
// This code is originally from https://github.com/DonJayamanne/bowerVSCode
// License: https://github.com/DonJayamanne/bowerVSCode/blob/master/LICENSE
import { window, StatusBarItem, StatusBarAlignment } from 'vscode';
export default class ProgressIndicator {
private _statusBarItem: StatusBarItem;
constructor() {
this._statusBarItem = window.createStatusBarItem(StatusBarAlignment.Left);
}
private _tasks: string[] = [];
public beginTask(task: string): void {
this._tasks.push(task);
this.displayProgressIndicator();
}
public endTask(_task: string): void {
if (this._tasks.length > 0) {
this._tasks.pop();
}
this.setMessage();
}
private setMessage(): void {
if (this._tasks.length === 0) {
this._statusBarItem.text = '';
this.hideProgressIndicator();
return;
}
this._statusBarItem.text = this._tasks[this._tasks.length - 1];
this._statusBarItem.show();
}
private _interval: any;
private displayProgressIndicator(): void {
this.setMessage();
this.hideProgressIndicator();
this._interval = setInterval(() => this.onDisplayProgressIndicator(), 100);
}
private hideProgressIndicator(): void {
if (this._interval) {
clearInterval(this._interval);
this._interval = undefined;
}
this.ProgressCounter = 0;
}
private ProgressText = ['|', '/', '-', '\\', '|', '/', '-', '\\'];
private ProgressCounter = 0;
private onDisplayProgressIndicator(): void {
if (this._tasks.length === 0) {
return;
}
let txt = this.ProgressText[this.ProgressCounter];
this._statusBarItem.text = this._tasks[this._tasks.length - 1] + ' ' + txt;
this.ProgressCounter++;
if (this.ProgressCounter >= this.ProgressText.length - 1) {
this.ProgressCounter = 0;
}
}
}

View File

@@ -1,47 +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 fs from 'fs';
import { IFileSource, IFile } from '../fileSources';
export class MockFileSource implements IFileSource {
filesToReturn: Map<string, IFile[]>;
constructor() {
this.filesToReturn = new Map<string, IFile[]>();
}
enumerateFiles(filePath: string): Promise<IFile[]> {
let files: IFile[] = this.filesToReturn.get(filePath);
return Promise.resolve(files);
}
mkdir(dirName: string, remoteBasePath: string): Promise<void> {
return Promise.resolve(undefined);
}
writeFile(localFile: IFile, remoteDir: string): Promise<string> {
return Promise.resolve(undefined);
}
delete(filePath: string): Promise<void> {
throw new Error('Method not implemented.');
}
readFile(filePath: string, maxBytes?: number): Promise<Buffer> {
throw new Error('Method not implemented.');
}
readFileLines(path: string, maxLines: number): Promise<Buffer> {
throw new Error("Method not implemented.");
}
createReadStream(filePath: string): fs.ReadStream {
throw new Error('Method not implemented.');
}
exists(filePath: string): Promise<boolean> {
throw new Error('Method not implemented.');
}
}

View File

@@ -1,19 +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 assert from 'assert';
export async function assertThrowsAsync(fn: Function, msg: string): Promise<void> {
let f = () => {
// Empty
};
try {
await fn();
} catch (e) {
f = () => { throw e; };
} finally {
assert.throws(f, undefined, msg);
}
}

View File

@@ -1,27 +0,0 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import { Transform } from 'stream';
import * as vscode from 'vscode';
import * as nls from 'vscode-nls';
const localize = nls.loadMessageBundle();
export class CancelableStream extends Transform {
constructor(private cancelationToken: vscode.CancellationTokenSource) {
super();
}
public override _transform(chunk: any, encoding: string, callback: Function): void {
if (this.cancelationToken && this.cancelationToken.token.isCancellationRequested) {
callback(new Error(localize('streamCanceled', 'Stream operation canceled by the user')));
} else {
this.push(chunk);
callback();
}
}
}

View File

@@ -1,77 +0,0 @@
// This code is originally from https://github.com/DonJayamanne/bowerVSCode
// License: https://github.com/DonJayamanne/bowerVSCode/blob/master/LICENSE
import { window } from 'vscode';
import PromptFactory from './factory';
import EscapeException from './escapeException';
import { IQuestion, IPrompter, IPromptCallback, Answers } from './question';
// Supports simple pattern for prompting for user input and acting on this
export default class CodeAdapter implements IPrompter {
// TODO define question interface
private fixQuestion(question: IQuestion): any {
if (question.type === 'checkbox' && Array.isArray(question.choices)) {
// For some reason when there's a choice of checkboxes, they aren't formatted properly
// Not sure where the issue is
question.choices = question.choices.map(item => {
if (typeof (item) === 'string') {
return { checked: false, name: item, value: item };
} else {
return item;
}
});
}
}
public async promptSingle<T>(question: IQuestion, ignoreFocusOut?: boolean): Promise<T | undefined> {
let questions: IQuestion[] = [question];
const answers = await this.prompt<T>(questions, ignoreFocusOut);
if (answers) {
let response: T = answers[question.name];
return response || undefined;
}
return undefined;
}
public async prompt<T>(questions: IQuestion[], ignoreFocusOut?: boolean): Promise<Answers<T> | undefined> {
// Collapse multiple questions into a set of prompt steps
const promptResult = new Promise<Answers<T>>((resolve) => {
let answers: Answers<T> = {};
questions.forEach(async (question: IQuestion) => {
this.fixQuestion(question);
const prompt = PromptFactory.createPrompt(question, ignoreFocusOut);
if (!question.shouldPrompt || question.shouldPrompt(answers) === true) {
const result = await prompt.render();
answers[question.name] = result;
if (question.onAnswered) {
question.onAnswered(result);
}
return;
}
});
resolve(answers);
});
try {
return await promptResult;
} catch (err) {
if (err instanceof EscapeException || err instanceof TypeError) {
window.showErrorMessage(err.message);
}
return undefined;
}
}
// Helper to make it possible to prompt using callback pattern. Generally Promise is a preferred flow
public promptCallback(questions: IQuestion[], callback: IPromptCallback | undefined): void {
// Collapse multiple questions into a set of prompt steps
this.prompt(questions).then(answers => {
if (callback && answers) {
callback(answers);
}
});
}
}

View File

@@ -1,70 +0,0 @@
'use strict';
// This code is originally from https://github.com/DonJayamanne/bowerVSCode
// License: https://github.com/DonJayamanne/bowerVSCode/blob/master/LICENSE
import { window, StatusBarItem, StatusBarAlignment } from 'vscode';
export default class ProgressIndicator {
private _statusBarItem: StatusBarItem;
constructor() {
this._statusBarItem = window.createStatusBarItem(StatusBarAlignment.Left);
}
private _tasks: string[] = [];
public beginTask(task: string): void {
this._tasks.push(task);
this.displayProgressIndicator();
}
public endTask(task: string): void {
if (this._tasks.length > 0) {
this._tasks.pop();
}
this.setMessage();
}
private setMessage(): void {
if (this._tasks.length === 0) {
this._statusBarItem.text = '';
this.hideProgressIndicator();
return;
}
this._statusBarItem.text = this._tasks[this._tasks.length - 1];
this._statusBarItem.show();
}
private _interval: any;
private displayProgressIndicator(): void {
this.setMessage();
this.hideProgressIndicator();
this._interval = setInterval(() => this.onDisplayProgressIndicator(), 100);
}
private hideProgressIndicator(): void {
if (this._interval) {
clearInterval(this._interval);
this._interval = undefined;
}
this.ProgressCounter = 0;
}
private ProgressText = ['|', '/', '-', '\\', '|', '/', '-', '\\'];
private ProgressCounter = 0;
private onDisplayProgressIndicator(): void {
if (this._tasks.length === 0) {
return;
}
let txt = this.ProgressText[this.ProgressCounter];
this._statusBarItem.text = this._tasks[this._tasks.length - 1] + ' ' + txt;
this.ProgressCounter++;
if (this.ProgressCounter >= this.ProgressText.length - 1) {
this.ProgressCounter = 0;
}
}
}

View File

@@ -1,22 +0,0 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
const _typeof = {
undefined: 'undefined'
};
/**
* @returns whether the provided parameter is undefined or null.
*/
export function isUndefinedOrNull(obj: any): boolean {
return isUndefined(obj) || obj === null;
}
/**
* @returns whether the provided parameter is undefined.
*/
export function isUndefined(obj: any): boolean {
return typeof (obj) === _typeof.undefined;
}

View File

@@ -1,39 +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 { MigrationTargetType } from './stateMachine';
export interface Base {
uuid: string;
}
export interface BaseRequest extends Base { }
export interface BaseResponse<T> extends Base {
error?: string;
response: T;
}
export interface GatherInformationRequest extends BaseRequest {
connection: azdata.connection.Connection;
}
export interface Checks {
}
export interface SKURecommendation {
product: MigrationTargetType;
checks: Checks;
}
export interface SKURecommendations {
recommendations: SKURecommendation[];
}
export interface GatherInformationResponse extends BaseResponse<SKURecommendations> {
}

View File

@@ -1,163 +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 { MigrationSourceAuthenticationType, MigrationStateModel, StateChangeEvent } from '../models/stateMachine';
import * as constants from '../constants/strings';
import { createLabelTextComponent, createHeadingTextComponent, WIZARD_INPUT_COMPONENT_WIDTH } from './wizardController';
import { getSourceConnectionCredentials, getSourceConnectionProfile, getSourceConnectionUri } from '../api/sqlUtils';
export class SqlSourceConfigurationPage extends MigrationWizardPage {
private _view!: azdata.ModelView;
private _usernameInput!: azdata.InputBoxComponent;
private _password!: azdata.InputBoxComponent;
private _disposables: vscode.Disposable[] = [];
constructor(wizard: azdata.window.Wizard, migrationStateModel: MigrationStateModel) {
super(wizard, azdata.window.createWizardPage(constants.SOURCE_CONFIGURATION, 'MigrationModePage'), migrationStateModel);
}
protected async registerContent(view: azdata.ModelView): Promise<void> {
this.wizard.customButtons[0].enabled = true;
this._view = view;
const form = view.modelBuilder.formContainer()
.withFormItems(
[
await this.createSourceCredentialContainer(),
]
);
this._disposables.push(this._view.onClosed(e => {
this._disposables.forEach(
d => { try { d.dispose(); } catch { } });
}));
await view.initializeModel(form.component());
}
public async onPageEnter(pageChangeInfo: azdata.window.WizardPageChangeInfo): Promise<void> {
this.wizard.registerNavigationValidator(pageChangeInfo => true);
}
public async onPageLeave(pageChangeInfo: azdata.window.WizardPageChangeInfo): Promise<void> {
this.wizard.registerNavigationValidator(pageChangeInfo => true);
this.wizard.message = { text: '' };
}
protected async handleStateChange(e: StateChangeEvent): Promise<void> {
}
private async createSourceCredentialContainer(): Promise<azdata.FormComponent> {
const connectionProfile = await getSourceConnectionProfile();
const queryProvider = azdata.dataprotocol.getProvider<azdata.QueryProvider>(connectionProfile.providerId, azdata.DataProviderType.QueryProvider);
const query = 'select SUSER_NAME()';
const results = await queryProvider.runQueryAndReturn(await getSourceConnectionUri(), query);
const username = results.rows[0][0].displayValue;
this.migrationStateModel._authenticationType = connectionProfile.authenticationType === azdata.connection.AuthenticationType.SqlLogin
? MigrationSourceAuthenticationType.Sql
: connectionProfile.authenticationType === azdata.connection.AuthenticationType.Integrated
? MigrationSourceAuthenticationType.Integrated
: undefined!;
const sourceCredText = await createHeadingTextComponent(this._view, constants.SOURCE_CREDENTIALS);
const enterYourCredText = createLabelTextComponent(
this._view,
constants.ENTER_YOUR_SQL_CREDS,
{
'width': '600px',
'font-size': '13px',
}
);
const serverLabel = this._view.modelBuilder.text().withProps({
value: constants.SERVER,
width: WIZARD_INPUT_COMPONENT_WIDTH,
CSSStyles: {
'font-size': '13px',
'font-weight': 'bold',
}
}).component();
const server = this._view.modelBuilder.inputBox().withProps({
value: connectionProfile.serverName,
enabled: false,
width: WIZARD_INPUT_COMPONENT_WIDTH
}).component();
const authenticationTypeLable = this._view.modelBuilder.text().withProps({
value: constants.AUTHENTICATION_TYPE,
width: WIZARD_INPUT_COMPONENT_WIDTH,
CSSStyles: {
'font-size': '13px',
'font-weight': 'bold',
}
}).component();
const authenticationTypeInput = this._view.modelBuilder.inputBox().withProps({
value: this.migrationStateModel._authenticationType === MigrationSourceAuthenticationType.Sql ? 'SQL Login' : 'Windows Authentication',
enabled: false,
width: WIZARD_INPUT_COMPONENT_WIDTH
}).component();
const usernameLable = this._view.modelBuilder.text().withProps({
value: constants.USERNAME,
width: WIZARD_INPUT_COMPONENT_WIDTH,
CSSStyles: {
'font-size': '13px',
'font-weight': 'bold',
}
}).component();
this._usernameInput = this._view.modelBuilder.inputBox().withProps({
value: username,
required: true,
enabled: false,
width: WIZARD_INPUT_COMPONENT_WIDTH
}).component();
this._disposables.push(this._usernameInput.onTextChanged(value => {
this.migrationStateModel._sqlServerUsername = value;
}));
const passwordLabel = this._view.modelBuilder.text().withProps({
value: constants.DATABASE_BACKUP_NETWORK_SHARE_PASSWORD_LABEL,
width: WIZARD_INPUT_COMPONENT_WIDTH,
CSSStyles: {
'font-size': '13px',
'font-weight': 'bold',
}
}).component();
this._password = this._view.modelBuilder.inputBox().withProps({
value: (await getSourceConnectionCredentials()).password,
required: true,
inputType: 'password',
width: WIZARD_INPUT_COMPONENT_WIDTH
}).component();
this._disposables.push(this._password.onTextChanged(value => {
this.migrationStateModel._sqlServerPassword = value;
}));
const container = this._view.modelBuilder.flexContainer().withItems(
[
sourceCredText,
enterYourCredText,
serverLabel,
server,
authenticationTypeLable,
authenticationTypeInput,
usernameLable,
this._usernameInput,
passwordLabel,
this._password
]
).withLayout({
flexFlow: 'column'
}).component();
return {
component: container
};
}
}