mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-02-16 18:46:40 -05:00
Add deploy options support (#11567)
* add getOptionsFromProfile request * update deploy and generate script to accept options * fix tests * update message * update message to say what isn't supported * bump sqltoolsservice version
This commit is contained in:
@@ -56,4 +56,92 @@ export class DacFxTestService implements mssql.IDacFxService {
|
|||||||
};
|
};
|
||||||
return Promise.resolve(deployPlan);
|
return Promise.resolve(deployPlan);
|
||||||
}
|
}
|
||||||
|
getOptionsFromProfile(profilePath: string): Thenable<mssql.DacFxOptionsResult> {
|
||||||
|
const optionsResult: mssql.DacFxOptionsResult = {
|
||||||
|
success: true,
|
||||||
|
errorMessage: '',
|
||||||
|
deploymentOptions: {
|
||||||
|
ignoreTableOptions: false,
|
||||||
|
ignoreSemicolonBetweenStatements: false,
|
||||||
|
ignoreRouteLifetime: false,
|
||||||
|
ignoreRoleMembership: false,
|
||||||
|
ignoreQuotedIdentifiers: false,
|
||||||
|
ignorePermissions: false,
|
||||||
|
ignorePartitionSchemes: false,
|
||||||
|
ignoreObjectPlacementOnPartitionScheme: false,
|
||||||
|
ignoreNotForReplication: false,
|
||||||
|
ignoreLoginSids: false,
|
||||||
|
ignoreLockHintsOnIndexes: false,
|
||||||
|
ignoreKeywordCasing: false,
|
||||||
|
ignoreIndexPadding: false,
|
||||||
|
ignoreIndexOptions: false,
|
||||||
|
ignoreIncrement: false,
|
||||||
|
ignoreIdentitySeed: false,
|
||||||
|
ignoreUserSettingsObjects: false,
|
||||||
|
ignoreFullTextCatalogFilePath: false,
|
||||||
|
ignoreWhitespace: false,
|
||||||
|
ignoreWithNocheckOnForeignKeys: false,
|
||||||
|
verifyCollationCompatibility: false,
|
||||||
|
unmodifiableObjectWarnings: false,
|
||||||
|
treatVerificationErrorsAsWarnings: false,
|
||||||
|
scriptRefreshModule: false,
|
||||||
|
scriptNewConstraintValidation: false,
|
||||||
|
scriptFileSize: false,
|
||||||
|
scriptDeployStateChecks: false,
|
||||||
|
scriptDatabaseOptions: false,
|
||||||
|
scriptDatabaseCompatibility: false,
|
||||||
|
scriptDatabaseCollation: false,
|
||||||
|
runDeploymentPlanExecutors: false,
|
||||||
|
registerDataTierApplication: false,
|
||||||
|
populateFilesOnFileGroups: false,
|
||||||
|
noAlterStatementsToChangeClrTypes: false,
|
||||||
|
includeTransactionalScripts: false,
|
||||||
|
includeCompositeObjects: false,
|
||||||
|
allowUnsafeRowLevelSecurityDataMovement: false,
|
||||||
|
ignoreWithNocheckOnCheckConstraints: false,
|
||||||
|
ignoreFillFactor: false,
|
||||||
|
ignoreFileSize: false,
|
||||||
|
ignoreFilegroupPlacement: false,
|
||||||
|
doNotAlterReplicatedObjects: false,
|
||||||
|
doNotAlterChangeDataCaptureObjects: false,
|
||||||
|
disableAndReenableDdlTriggers: false,
|
||||||
|
deployDatabaseInSingleUserMode: false,
|
||||||
|
createNewDatabase: false,
|
||||||
|
compareUsingTargetCollation: false,
|
||||||
|
commentOutSetVarDeclarations: false,
|
||||||
|
blockWhenDriftDetected: false,
|
||||||
|
blockOnPossibleDataLoss: false,
|
||||||
|
backupDatabaseBeforeChanges: false,
|
||||||
|
allowIncompatiblePlatform: false,
|
||||||
|
allowDropBlockingAssemblies: false,
|
||||||
|
dropConstraintsNotInSource: false,
|
||||||
|
dropDmlTriggersNotInSource: false,
|
||||||
|
dropExtendedPropertiesNotInSource: false,
|
||||||
|
dropIndexesNotInSource: false,
|
||||||
|
ignoreFileAndLogFilePath: false,
|
||||||
|
ignoreExtendedProperties: false,
|
||||||
|
ignoreDmlTriggerState: false,
|
||||||
|
ignoreDmlTriggerOrder: false,
|
||||||
|
ignoreDefaultSchema: false,
|
||||||
|
ignoreDdlTriggerState: false,
|
||||||
|
ignoreDdlTriggerOrder: false,
|
||||||
|
ignoreCryptographicProviderFilePath: false,
|
||||||
|
verifyDeployment: false,
|
||||||
|
ignoreComments: false,
|
||||||
|
ignoreColumnCollation: false,
|
||||||
|
ignoreAuthorizer: false,
|
||||||
|
ignoreAnsiNulls: false,
|
||||||
|
generateSmartDefaults: false,
|
||||||
|
dropStatisticsNotInSource: false,
|
||||||
|
dropRoleMembersNotInSource: false,
|
||||||
|
dropPermissionsNotInSource: false,
|
||||||
|
dropObjectsNotInSource: false,
|
||||||
|
ignoreColumnOrder: false,
|
||||||
|
doNotDropObjectTypes: [],
|
||||||
|
excludeObjectTypes: []
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return Promise.resolve(optionsResult);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"downloadUrl": "https://github.com/Microsoft/sqltoolsservice/releases/download/v{#version#}/microsoft.sqltools.servicelayer-{#fileName#}",
|
"downloadUrl": "https://github.com/Microsoft/sqltoolsservice/releases/download/v{#version#}/microsoft.sqltools.servicelayer-{#fileName#}",
|
||||||
"version": "3.0.0-release.4",
|
"version": "3.0.0-release.8",
|
||||||
"downloadFileNames": {
|
"downloadFileNames": {
|
||||||
"Windows_86": "win-x86-netcoreapp3.1.zip",
|
"Windows_86": "win-x86-netcoreapp3.1.zip",
|
||||||
"Windows_64": "win-x64-netcoreapp3.1.zip",
|
"Windows_64": "win-x64-netcoreapp3.1.zip",
|
||||||
|
|||||||
@@ -452,6 +452,7 @@ export interface DeployParams {
|
|||||||
databaseName: string;
|
databaseName: string;
|
||||||
upgradeExisting: boolean;
|
upgradeExisting: boolean;
|
||||||
sqlCommandVariableValues?: Record<string, string>;
|
sqlCommandVariableValues?: Record<string, string>;
|
||||||
|
deploymentOptions?: mssql.DeploymentOptions;
|
||||||
ownerUri: string;
|
ownerUri: string;
|
||||||
taskExecutionMode: TaskExecutionMode;
|
taskExecutionMode: TaskExecutionMode;
|
||||||
}
|
}
|
||||||
@@ -460,6 +461,7 @@ export interface GenerateDeployScriptParams {
|
|||||||
packageFilePath: string;
|
packageFilePath: string;
|
||||||
databaseName: string;
|
databaseName: string;
|
||||||
sqlCommandVariableValues?: Record<string, string>;
|
sqlCommandVariableValues?: Record<string, string>;
|
||||||
|
deploymentOptions?: mssql.DeploymentOptions
|
||||||
ownerUri: string;
|
ownerUri: string;
|
||||||
taskExecutionMode: TaskExecutionMode;
|
taskExecutionMode: TaskExecutionMode;
|
||||||
}
|
}
|
||||||
@@ -471,6 +473,9 @@ export interface GenerateDeployPlanParams {
|
|||||||
taskExecutionMode: TaskExecutionMode;
|
taskExecutionMode: TaskExecutionMode;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface GetOptionsFromProfileParams {
|
||||||
|
profilePath: string;
|
||||||
|
}
|
||||||
export namespace ExportRequest {
|
export namespace ExportRequest {
|
||||||
export const type = new RequestType<ExportParams, mssql.DacFxResult, void, void>('dacfx/export');
|
export const type = new RequestType<ExportParams, mssql.DacFxResult, void, void>('dacfx/export');
|
||||||
}
|
}
|
||||||
@@ -494,6 +499,10 @@ export namespace GenerateDeployScriptRequest {
|
|||||||
export namespace GenerateDeployPlanRequest {
|
export namespace GenerateDeployPlanRequest {
|
||||||
export const type = new RequestType<GenerateDeployPlanParams, mssql.GenerateDeployPlanResult, void, void>('dacfx/generateDeployPlan');
|
export const type = new RequestType<GenerateDeployPlanParams, mssql.GenerateDeployPlanResult, void, void>('dacfx/generateDeployPlan');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export namespace GetOptionsFromProfileRequest {
|
||||||
|
export const type = new RequestType<GetOptionsFromProfileParams, mssql.DacFxOptionsResult, void, void>('dacfx/getOptionsFromProfile');
|
||||||
|
}
|
||||||
// ------------------------------- < DacFx > ------------------------------------
|
// ------------------------------- < DacFx > ------------------------------------
|
||||||
|
|
||||||
// ------------------------------- <CMS> ----------------------------------------
|
// ------------------------------- <CMS> ----------------------------------------
|
||||||
|
|||||||
@@ -76,8 +76,8 @@ export class DacFxService implements mssql.IDacFxService {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public deployDacpac(packageFilePath: string, targetDatabaseName: string, upgradeExisting: boolean, ownerUri: string, taskExecutionMode: azdata.TaskExecutionMode, sqlCommandVariableValues?: Record<string, string>): Thenable<mssql.DacFxResult> {
|
public deployDacpac(packageFilePath: string, targetDatabaseName: string, upgradeExisting: boolean, ownerUri: string, taskExecutionMode: azdata.TaskExecutionMode, sqlCommandVariableValues?: Record<string, string>, deploymentOptions?: mssql.DeploymentOptions): Thenable<mssql.DacFxResult> {
|
||||||
const params: contracts.DeployParams = { packageFilePath: packageFilePath, databaseName: targetDatabaseName, upgradeExisting: upgradeExisting, sqlCommandVariableValues: sqlCommandVariableValues, ownerUri: ownerUri, taskExecutionMode: taskExecutionMode };
|
const params: contracts.DeployParams = { packageFilePath: packageFilePath, databaseName: targetDatabaseName, upgradeExisting: upgradeExisting, sqlCommandVariableValues: sqlCommandVariableValues, deploymentOptions: deploymentOptions, ownerUri: ownerUri, taskExecutionMode: taskExecutionMode };
|
||||||
return this.client.sendRequest(contracts.DeployRequest.type, params).then(
|
return this.client.sendRequest(contracts.DeployRequest.type, params).then(
|
||||||
undefined,
|
undefined,
|
||||||
e => {
|
e => {
|
||||||
@@ -87,8 +87,8 @@ export class DacFxService implements mssql.IDacFxService {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public generateDeployScript(packageFilePath: string, targetDatabaseName: string, ownerUri: string, taskExecutionMode: azdata.TaskExecutionMode, sqlCommandVariableValues?: Record<string, string>): Thenable<mssql.DacFxResult> {
|
public generateDeployScript(packageFilePath: string, targetDatabaseName: string, ownerUri: string, taskExecutionMode: azdata.TaskExecutionMode, sqlCommandVariableValues?: Record<string, string>, deploymentOptions?: mssql.DeploymentOptions): Thenable<mssql.DacFxResult> {
|
||||||
const params: contracts.GenerateDeployScriptParams = { packageFilePath: packageFilePath, databaseName: targetDatabaseName, sqlCommandVariableValues: sqlCommandVariableValues, ownerUri: ownerUri, taskExecutionMode: taskExecutionMode };
|
const params: contracts.GenerateDeployScriptParams = { packageFilePath: packageFilePath, databaseName: targetDatabaseName, sqlCommandVariableValues: sqlCommandVariableValues, deploymentOptions: deploymentOptions, ownerUri: ownerUri, taskExecutionMode: taskExecutionMode };
|
||||||
return this.client.sendRequest(contracts.GenerateDeployScriptRequest.type, params).then(
|
return this.client.sendRequest(contracts.GenerateDeployScriptRequest.type, params).then(
|
||||||
undefined,
|
undefined,
|
||||||
e => {
|
e => {
|
||||||
@@ -108,4 +108,15 @@ export class DacFxService implements mssql.IDacFxService {
|
|||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public getOptionsFromProfile(profilePath: string): Thenable<mssql.DacFxOptionsResult> {
|
||||||
|
const params: contracts.GetOptionsFromProfileParams = { profilePath: profilePath };
|
||||||
|
return this.client.sendRequest(contracts.GetOptionsFromProfileRequest.type, params).then(
|
||||||
|
undefined,
|
||||||
|
e => {
|
||||||
|
this.client.logFailedRequest(contracts.GetOptionsFromProfileRequest.type, e);
|
||||||
|
return Promise.resolve(undefined);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
9
extensions/mssql/src/mssql.d.ts
vendored
9
extensions/mssql/src/mssql.d.ts
vendored
@@ -333,9 +333,10 @@ export interface IDacFxService {
|
|||||||
importBacpac(packageFilePath: string, databaseName: string, ownerUri: string, taskExecutionMode: azdata.TaskExecutionMode): Thenable<DacFxResult>;
|
importBacpac(packageFilePath: string, databaseName: string, ownerUri: string, taskExecutionMode: azdata.TaskExecutionMode): Thenable<DacFxResult>;
|
||||||
extractDacpac(databaseName: string, packageFilePath: string, applicationName: string, applicationVersion: string, ownerUri: string, taskExecutionMode: azdata.TaskExecutionMode): Thenable<DacFxResult>;
|
extractDacpac(databaseName: string, packageFilePath: string, applicationName: string, applicationVersion: string, ownerUri: string, taskExecutionMode: azdata.TaskExecutionMode): Thenable<DacFxResult>;
|
||||||
importDatabaseProject(databaseName: string, targetFilePath: string, applicationName: string, applicationVersion: string, ownerUri: string, extractTarget: ExtractTarget, taskExecutionMode: azdata.TaskExecutionMode): Thenable<DacFxResult>;
|
importDatabaseProject(databaseName: string, targetFilePath: string, applicationName: string, applicationVersion: string, ownerUri: string, extractTarget: ExtractTarget, taskExecutionMode: azdata.TaskExecutionMode): Thenable<DacFxResult>;
|
||||||
deployDacpac(packageFilePath: string, databaseName: string, upgradeExisting: boolean, ownerUri: string, taskExecutionMode: azdata.TaskExecutionMode, sqlCommandVariableValues?: Record<string, string>): Thenable<DacFxResult>;
|
deployDacpac(packageFilePath: string, databaseName: string, upgradeExisting: boolean, ownerUri: string, taskExecutionMode: azdata.TaskExecutionMode, sqlCommandVariableValues?: Record<string, string>, deploymentOptions?: DeploymentOptions): Thenable<DacFxResult>;
|
||||||
generateDeployScript(packageFilePath: string, databaseName: string, ownerUri: string, taskExecutionMode: azdata.TaskExecutionMode, sqlCommandVariableValues?: Record<string, string>): Thenable<DacFxResult>;
|
generateDeployScript(packageFilePath: string, databaseName: string, ownerUri: string, taskExecutionMode: azdata.TaskExecutionMode, sqlCommandVariableValues?: Record<string, string>, deploymentOptions?: DeploymentOptions): Thenable<DacFxResult>;
|
||||||
generateDeployPlan(packageFilePath: string, databaseName: string, ownerUri: string, taskExecutionMode: azdata.TaskExecutionMode): Thenable<GenerateDeployPlanResult>;
|
generateDeployPlan(packageFilePath: string, databaseName: string, ownerUri: string, taskExecutionMode: azdata.TaskExecutionMode): Thenable<GenerateDeployPlanResult>;
|
||||||
|
getOptionsFromProfile(profilePath: string): Thenable<DacFxOptionsResult>;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface DacFxResult extends azdata.ResultStatus {
|
export interface DacFxResult extends azdata.ResultStatus {
|
||||||
@@ -346,6 +347,10 @@ export interface GenerateDeployPlanResult extends DacFxResult {
|
|||||||
report: string;
|
report: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface DacFxOptionsResult extends azdata.ResultStatus {
|
||||||
|
deploymentOptions: DeploymentOptions;
|
||||||
|
}
|
||||||
|
|
||||||
export interface ExportParams {
|
export interface ExportParams {
|
||||||
databaseName: string;
|
databaseName: string;
|
||||||
packageFilePath: string;
|
packageFilePath: string;
|
||||||
|
|||||||
@@ -77,7 +77,7 @@ export const selectConnectionRadioButtonsTitle = localize('selectconnectionRadio
|
|||||||
export const dataSourceDropdownTitle = localize('dataSourceDropdownTitle', "Data source");
|
export const dataSourceDropdownTitle = localize('dataSourceDropdownTitle', "Data source");
|
||||||
export const noDataSourcesText = localize('noDataSourcesText', "No data sources in this project");
|
export const noDataSourcesText = localize('noDataSourcesText', "No data sources in this project");
|
||||||
export const loadProfileButtonText = localize('loadProfileButtonText', "Load Profile...");
|
export const loadProfileButtonText = localize('loadProfileButtonText', "Load Profile...");
|
||||||
export const profileWarningText = localize('profileWarningText', "⚠ Warning: Only SQL Login and Integrated Authentication connection strings, database name, and SQLCMD variables are able to be loaded from a profile at this time");
|
export const profileWarningText = localize('profileWarningText', "⚠ Warning: Connection strings using AAD Authentication are not supported at this time");
|
||||||
export const sqlCmdTableLabel = localize('sqlCmdTableLabel', "SQLCMD Variables");
|
export const sqlCmdTableLabel = localize('sqlCmdTableLabel', "SQLCMD Variables");
|
||||||
export const sqlCmdVariableColumn = localize('sqlCmdVariableColumn', "Variable");
|
export const sqlCmdVariableColumn = localize('sqlCmdVariableColumn', "Variable");
|
||||||
export const sqlCmdValueColumn = localize('sqlCmdValueColumn', "Value");
|
export const sqlCmdValueColumn = localize('sqlCmdValueColumn', "Value");
|
||||||
|
|||||||
@@ -220,15 +220,16 @@ export class ProjectsController {
|
|||||||
const dacFxService = await this.getDaxFxService();
|
const dacFxService = await this.getDaxFxService();
|
||||||
|
|
||||||
if ((<IPublishSettings>settings).upgradeExisting) {
|
if ((<IPublishSettings>settings).upgradeExisting) {
|
||||||
return await dacFxService.deployDacpac(tempPath, settings.databaseName, (<IPublishSettings>settings).upgradeExisting, settings.connectionUri, azdata.TaskExecutionMode.execute, settings.sqlCmdVariables);
|
return await dacFxService.deployDacpac(tempPath, settings.databaseName, (<IPublishSettings>settings).upgradeExisting, settings.connectionUri, azdata.TaskExecutionMode.execute, settings.sqlCmdVariables, settings.deploymentOptions);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
return await dacFxService.generateDeployScript(tempPath, settings.databaseName, settings.connectionUri, azdata.TaskExecutionMode.script, settings.sqlCmdVariables);
|
return await dacFxService.generateDeployScript(tempPath, settings.databaseName, settings.connectionUri, azdata.TaskExecutionMode.script, settings.sqlCmdVariables, settings.deploymentOptions);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public async readPublishProfileCallback(profileUri: vscode.Uri): Promise<PublishProfile> {
|
public async readPublishProfileCallback(profileUri: vscode.Uri): Promise<PublishProfile> {
|
||||||
const profile = await load(profileUri);
|
const dacFxService = await this.getDaxFxService();
|
||||||
|
const profile = await load(profileUri, dacFxService);
|
||||||
return profile;
|
return profile;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ import * as utils from '../common/utils';
|
|||||||
import { Project } from '../models/project';
|
import { Project } from '../models/project';
|
||||||
import { SqlConnectionDataSource } from '../models/dataSources/sqlConnectionStringSource';
|
import { SqlConnectionDataSource } from '../models/dataSources/sqlConnectionStringSource';
|
||||||
import { IPublishSettings, IGenerateScriptSettings } from '../models/IPublishSettings';
|
import { IPublishSettings, IGenerateScriptSettings } from '../models/IPublishSettings';
|
||||||
|
import { DeploymentOptions } from '../../../mssql/src/mssql';
|
||||||
|
|
||||||
interface DataSourceDropdownValue extends azdata.CategoryValue {
|
interface DataSourceDropdownValue extends azdata.CategoryValue {
|
||||||
dataSource: SqlConnectionDataSource;
|
dataSource: SqlConnectionDataSource;
|
||||||
@@ -35,6 +36,7 @@ export class PublishDatabaseDialog {
|
|||||||
private connectionId: string | undefined;
|
private connectionId: string | undefined;
|
||||||
private connectionIsDataSource: boolean | undefined;
|
private connectionIsDataSource: boolean | undefined;
|
||||||
private profileSqlCmdVars: Record<string, string> | undefined;
|
private profileSqlCmdVars: Record<string, string> | undefined;
|
||||||
|
private deploymentOptions: DeploymentOptions | undefined;
|
||||||
|
|
||||||
private toDispose: vscode.Disposable[] = [];
|
private toDispose: vscode.Disposable[] = [];
|
||||||
|
|
||||||
@@ -191,7 +193,8 @@ export class PublishDatabaseDialog {
|
|||||||
databaseName: this.getTargetDatabaseName(),
|
databaseName: this.getTargetDatabaseName(),
|
||||||
upgradeExisting: true,
|
upgradeExisting: true,
|
||||||
connectionUri: await this.getConnectionUri(),
|
connectionUri: await this.getConnectionUri(),
|
||||||
sqlCmdVariables: sqlCmdVars
|
sqlCmdVariables: sqlCmdVars,
|
||||||
|
deploymentOptions: this.deploymentOptions
|
||||||
};
|
};
|
||||||
|
|
||||||
azdata.window.closeDialog(this.dialog);
|
azdata.window.closeDialog(this.dialog);
|
||||||
@@ -205,7 +208,8 @@ export class PublishDatabaseDialog {
|
|||||||
const settings: IGenerateScriptSettings = {
|
const settings: IGenerateScriptSettings = {
|
||||||
databaseName: this.getTargetDatabaseName(),
|
databaseName: this.getTargetDatabaseName(),
|
||||||
connectionUri: await this.getConnectionUri(),
|
connectionUri: await this.getConnectionUri(),
|
||||||
sqlCmdVariables: sqlCmdVars
|
sqlCmdVariables: sqlCmdVars,
|
||||||
|
deploymentOptions: this.deploymentOptions
|
||||||
};
|
};
|
||||||
|
|
||||||
azdata.window.closeDialog(this.dialog);
|
azdata.window.closeDialog(this.dialog);
|
||||||
@@ -399,7 +403,7 @@ export class PublishDatabaseDialog {
|
|||||||
canSelectFiles: true,
|
canSelectFiles: true,
|
||||||
canSelectFolders: false,
|
canSelectFolders: false,
|
||||||
canSelectMany: false,
|
canSelectMany: false,
|
||||||
defaultUri: vscode.Uri.parse(this.project.projectFolderPath),
|
defaultUri: vscode.workspace.workspaceFolders ? (vscode.workspace.workspaceFolders as vscode.WorkspaceFolder[])[0].uri : undefined,
|
||||||
filters: {
|
filters: {
|
||||||
[constants.publishSettingsFiles]: ['publish.xml']
|
[constants.publishSettingsFiles]: ['publish.xml']
|
||||||
}
|
}
|
||||||
@@ -417,6 +421,7 @@ export class PublishDatabaseDialog {
|
|||||||
this.connectionId = result.connectionId;
|
this.connectionId = result.connectionId;
|
||||||
(<azdata.InputBoxComponent>this.targetConnectionTextBox).value = result.connectionString;
|
(<azdata.InputBoxComponent>this.targetConnectionTextBox).value = result.connectionString;
|
||||||
|
|
||||||
|
this.deploymentOptions = result.options;
|
||||||
this.profileSqlCmdVars = result.sqlCmdVariables;
|
this.profileSqlCmdVars = result.sqlCmdVariables;
|
||||||
const data = this.convertSqlCmdVarsToTableFormat(this.getSqlCmdVariablesForPublish());
|
const data = this.convertSqlCmdVarsToTableFormat(this.getSqlCmdVariablesForPublish());
|
||||||
|
|
||||||
|
|||||||
@@ -3,15 +3,19 @@
|
|||||||
* 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 { DeploymentOptions } from '../../../mssql/src/mssql';
|
||||||
|
|
||||||
export interface IPublishSettings {
|
export interface IPublishSettings {
|
||||||
databaseName: string;
|
databaseName: string;
|
||||||
connectionUri: string;
|
connectionUri: string;
|
||||||
upgradeExisting: boolean;
|
upgradeExisting: boolean;
|
||||||
sqlCmdVariables?: Record<string, string>;
|
sqlCmdVariables?: Record<string, string>;
|
||||||
|
deploymentOptions?: DeploymentOptions;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface IGenerateScriptSettings {
|
export interface IGenerateScriptSettings {
|
||||||
databaseName: string;
|
databaseName: string;
|
||||||
connectionUri: string;
|
connectionUri: string;
|
||||||
sqlCmdVariables?: Record<string, string>;
|
sqlCmdVariables?: Record<string, string>;
|
||||||
|
deploymentOptions?: DeploymentOptions;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import * as azdata from 'azdata';
|
|||||||
import * as xmldom from 'xmldom';
|
import * as xmldom from 'xmldom';
|
||||||
import * as constants from '../../common/constants';
|
import * as constants from '../../common/constants';
|
||||||
import * as utils from '../../common/utils';
|
import * as utils from '../../common/utils';
|
||||||
|
import * as mssql from '../../../../mssql';
|
||||||
|
|
||||||
import { promises as fs } from 'fs';
|
import { promises as fs } from 'fs';
|
||||||
import { Uri } from 'vscode';
|
import { Uri } from 'vscode';
|
||||||
@@ -18,12 +19,13 @@ export interface PublishProfile {
|
|||||||
connectionId: string;
|
connectionId: string;
|
||||||
connectionString: string;
|
connectionString: string;
|
||||||
sqlCmdVariables: Record<string, string>;
|
sqlCmdVariables: Record<string, string>;
|
||||||
|
options?: mssql.DeploymentOptions;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* parses the specified file to load publish settings
|
* parses the specified file to load publish settings
|
||||||
*/
|
*/
|
||||||
export async function load(profileUri: Uri): Promise<PublishProfile> {
|
export async function load(profileUri: Uri, dacfxService: mssql.IDacFxService): Promise<PublishProfile> {
|
||||||
const profileText = await fs.readFile(profileUri.fsPath);
|
const profileText = await fs.readFile(profileUri.fsPath);
|
||||||
const profileXmlDoc = new xmldom.DOMParser().parseFromString(profileText.toString());
|
const profileXmlDoc = new xmldom.DOMParser().parseFromString(profileText.toString());
|
||||||
|
|
||||||
@@ -36,6 +38,7 @@ export async function load(profileUri: Uri): Promise<PublishProfile> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const connectionInfo = await readConnectionString(profileXmlDoc);
|
const connectionInfo = await readConnectionString(profileXmlDoc);
|
||||||
|
const optionsResult = await dacfxService.getOptionsFromProfile(profileUri.fsPath);
|
||||||
|
|
||||||
// get all SQLCMD variables to include from the profile
|
// get all SQLCMD variables to include from the profile
|
||||||
const sqlCmdVariables = readSqlCmdVariables(profileXmlDoc);
|
const sqlCmdVariables = readSqlCmdVariables(profileXmlDoc);
|
||||||
@@ -44,7 +47,8 @@ export async function load(profileUri: Uri): Promise<PublishProfile> {
|
|||||||
databaseName: targetDbName,
|
databaseName: targetDbName,
|
||||||
connectionId: connectionInfo.connectionId,
|
connectionId: connectionInfo.connectionId,
|
||||||
connectionString: connectionInfo.connectionString,
|
connectionString: connectionInfo.connectionString,
|
||||||
sqlCmdVariables: sqlCmdVariables
|
sqlCmdVariables: sqlCmdVariables,
|
||||||
|
options: optionsResult.deploymentOptions
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -54,7 +58,7 @@ export async function load(profileUri: Uri): Promise<PublishProfile> {
|
|||||||
*/
|
*/
|
||||||
export function readSqlCmdVariables(xmlDoc: any): Record<string, string> {
|
export function readSqlCmdVariables(xmlDoc: any): Record<string, string> {
|
||||||
let sqlCmdVariables: Record<string, string> = {};
|
let sqlCmdVariables: Record<string, string> = {};
|
||||||
for (let i = 0; i < xmlDoc.documentElement.getElementsByTagName(constants.SqlCmdVariable).length; i++) {
|
for (let i = 0; i < xmlDoc.documentElement.getElementsByTagName(constants.SqlCmdVariable)?.length; i++) {
|
||||||
const sqlCmdVar = xmlDoc.documentElement.getElementsByTagName(constants.SqlCmdVariable)[i];
|
const sqlCmdVar = xmlDoc.documentElement.getElementsByTagName(constants.SqlCmdVariable)[i];
|
||||||
const varName = sqlCmdVar.getAttribute(constants.Include);
|
const varName = sqlCmdVar.getAttribute(constants.Include);
|
||||||
|
|
||||||
|
|||||||
@@ -289,7 +289,7 @@ describe('ProjectsController', function (): void {
|
|||||||
let builtDacpacPath = '';
|
let builtDacpacPath = '';
|
||||||
let publishedDacpacPath = '';
|
let publishedDacpacPath = '';
|
||||||
|
|
||||||
testContext.dacFxService.setup(x => x.generateDeployScript(TypeMoq.It.isAny(), TypeMoq.It.isAny(), TypeMoq.It.isAny(), TypeMoq.It.isAny(), TypeMoq.It.isAny())).returns(async (p) => {
|
testContext.dacFxService.setup(x => x.generateDeployScript(TypeMoq.It.isAny(), TypeMoq.It.isAny(), TypeMoq.It.isAny(), TypeMoq.It.isAny(), TypeMoq.It.isAny(), TypeMoq.It.isAny())).returns(async (p) => {
|
||||||
publishedDacpacPath = p;
|
publishedDacpacPath = p;
|
||||||
postCopyContents = (await fs.readFile(publishedDacpacPath)).toString();
|
postCopyContents = (await fs.readFile(publishedDacpacPath)).toString();
|
||||||
return Promise.resolve(mockDacFxResult);
|
return Promise.resolve(mockDacFxResult);
|
||||||
|
|||||||
@@ -7,18 +7,26 @@ import * as should from 'should';
|
|||||||
import * as azdata from 'azdata';
|
import * as azdata from 'azdata';
|
||||||
import * as vscode from 'vscode';
|
import * as vscode from 'vscode';
|
||||||
import * as sinon from 'sinon';
|
import * as sinon from 'sinon';
|
||||||
|
import * as TypeMoq from 'typemoq';
|
||||||
import * as baselines from './baselines/baselines';
|
import * as baselines from './baselines/baselines';
|
||||||
import * as testUtils from './testUtils';
|
import * as testUtils from './testUtils';
|
||||||
import * as constants from '../common/constants';
|
import * as constants from '../common/constants';
|
||||||
import { ProjectsController } from '../controllers/projectController';
|
import { ProjectsController } from '../controllers/projectController';
|
||||||
import { SqlDatabaseProjectTreeViewProvider } from '../controllers/databaseProjectTreeViewProvider';
|
import { SqlDatabaseProjectTreeViewProvider } from '../controllers/databaseProjectTreeViewProvider';
|
||||||
|
import { TestContext, createContext, mockDacFxOptionsResult } from './testContext';
|
||||||
|
import { load } from '../models/publishProfile/publishProfile';
|
||||||
|
|
||||||
|
let testContext: TestContext;
|
||||||
|
|
||||||
describe('Publish profile tests', function (): void {
|
describe('Publish profile tests', function (): void {
|
||||||
before(async function (): Promise<void> {
|
before(async function (): Promise<void> {
|
||||||
await baselines.loadBaselines();
|
await baselines.loadBaselines();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
beforeEach(function (): void {
|
||||||
|
testContext = createContext();
|
||||||
|
});
|
||||||
|
|
||||||
afterEach(function (): void {
|
afterEach(function (): void {
|
||||||
sinon.restore();
|
sinon.restore();
|
||||||
});
|
});
|
||||||
@@ -26,44 +34,50 @@ describe('Publish profile tests', function (): void {
|
|||||||
it('Should read database name, integrated security connection string, and SQLCMD variables from publish profile', async function (): Promise<void> {
|
it('Should read database name, integrated security connection string, and SQLCMD variables from publish profile', async function (): Promise<void> {
|
||||||
await baselines.loadBaselines();
|
await baselines.loadBaselines();
|
||||||
let profilePath = await testUtils.createTestFile(baselines.publishProfileIntegratedSecurityBaseline, 'publishProfile.publish.xml');
|
let profilePath = await testUtils.createTestFile(baselines.publishProfileIntegratedSecurityBaseline, 'publishProfile.publish.xml');
|
||||||
const projController = new ProjectsController(new SqlDatabaseProjectTreeViewProvider());
|
|
||||||
const connectionResult = {
|
const connectionResult = {
|
||||||
connected: true,
|
connected: true,
|
||||||
connectionId: 'connId',
|
connectionId: 'connId',
|
||||||
errorMessage: '',
|
errorMessage: '',
|
||||||
errorCode: 0
|
errorCode: 0
|
||||||
};
|
};
|
||||||
|
testContext.dacFxService.setup(x => x.getOptionsFromProfile(TypeMoq.It.isAny())).returns(async () => {
|
||||||
|
return Promise.resolve(mockDacFxOptionsResult);
|
||||||
|
});
|
||||||
const connectionString = 'Data Source=testserver;Integrated Security=true;Persist Security Info=False;Pooling=False;MultipleActiveResultSets=False;Connect Timeout=60;Encrypt=False;TrustServerCertificate=True';
|
const connectionString = 'Data Source=testserver;Integrated Security=true;Persist Security Info=False;Pooling=False;MultipleActiveResultSets=False;Connect Timeout=60;Encrypt=False;TrustServerCertificate=True';
|
||||||
sinon.stub(azdata.connection, 'connect').resolves(connectionResult);
|
sinon.stub(azdata.connection, 'connect').resolves(connectionResult);
|
||||||
sinon.stub(azdata.connection, 'getConnectionString').resolves(connectionString);
|
sinon.stub(azdata.connection, 'getConnectionString').resolves(connectionString);
|
||||||
|
|
||||||
let result = await projController.readPublishProfileCallback(vscode.Uri.file(profilePath));
|
let result = await load(vscode.Uri.file(profilePath), testContext.dacFxService.object);
|
||||||
should(result.databaseName).equal('targetDb');
|
should(result.databaseName).equal('targetDb');
|
||||||
should(Object.keys(result.sqlCmdVariables).length).equal(1);
|
should(Object.keys(result.sqlCmdVariables).length).equal(1);
|
||||||
should(result.sqlCmdVariables['ProdDatabaseName']).equal('MyProdDatabase');
|
should(result.sqlCmdVariables['ProdDatabaseName']).equal('MyProdDatabase');
|
||||||
should(result.connectionId).equal('connId');
|
should(result.connectionId).equal('connId');
|
||||||
should(result.connectionString).equal('Data Source=testserver;Integrated Security=true;Persist Security Info=False;Pooling=False;MultipleActiveResultSets=False;Connect Timeout=60;Encrypt=False;TrustServerCertificate=True');
|
should(result.connectionString).equal('Data Source=testserver;Integrated Security=true;Persist Security Info=False;Pooling=False;MultipleActiveResultSets=False;Connect Timeout=60;Encrypt=False;TrustServerCertificate=True');
|
||||||
|
should(result.options).equal(mockDacFxOptionsResult.deploymentOptions);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('Should read database name, SQL login connection string, and SQLCMD variables from publish profile', async function (): Promise<void> {
|
it('Should read database name, SQL login connection string, and SQLCMD variables from publish profile', async function (): Promise<void> {
|
||||||
await baselines.loadBaselines();
|
await baselines.loadBaselines();
|
||||||
let profilePath = await testUtils.createTestFile(baselines.publishProfileSqlLoginBaseline, 'publishProfile.publish.xml');
|
let profilePath = await testUtils.createTestFile(baselines.publishProfileSqlLoginBaseline, 'publishProfile.publish.xml');
|
||||||
const projController = new ProjectsController(new SqlDatabaseProjectTreeViewProvider());
|
|
||||||
const connectionResult = {
|
const connectionResult = {
|
||||||
providerName: 'MSSQL',
|
providerName: 'MSSQL',
|
||||||
connectionId: 'connId',
|
connectionId: 'connId',
|
||||||
options: {}
|
options: {}
|
||||||
};
|
};
|
||||||
|
testContext.dacFxService.setup(x => x.getOptionsFromProfile(TypeMoq.It.isAny())).returns(async () => {
|
||||||
|
return Promise.resolve(mockDacFxOptionsResult);
|
||||||
|
});
|
||||||
const connectionString = 'Data Source=testserver;User Id=testUser;Password=******;Integrated Security=false;Persist Security Info=False;Pooling=False;MultipleActiveResultSets=False;Connect Timeout=60;Encrypt=False;TrustServerCertificate=True';
|
const connectionString = 'Data Source=testserver;User Id=testUser;Password=******;Integrated Security=false;Persist Security Info=False;Pooling=False;MultipleActiveResultSets=False;Connect Timeout=60;Encrypt=False;TrustServerCertificate=True';
|
||||||
sinon.stub(azdata.connection, 'openConnectionDialog').resolves(connectionResult);
|
sinon.stub(azdata.connection, 'openConnectionDialog').resolves(connectionResult);
|
||||||
sinon.stub(azdata.connection, 'getConnectionString').resolves(connectionString);
|
sinon.stub(azdata.connection, 'getConnectionString').resolves(connectionString);
|
||||||
|
|
||||||
let result = await projController.readPublishProfileCallback(vscode.Uri.file(profilePath));
|
let result = await load(vscode.Uri.file(profilePath), testContext.dacFxService.object);
|
||||||
should(result.databaseName).equal('targetDb');
|
should(result.databaseName).equal('targetDb');
|
||||||
should(Object.keys(result.sqlCmdVariables).length).equal(1);
|
should(Object.keys(result.sqlCmdVariables).length).equal(1);
|
||||||
should(result.sqlCmdVariables['ProdDatabaseName']).equal('MyProdDatabase');
|
should(result.sqlCmdVariables['ProdDatabaseName']).equal('MyProdDatabase');
|
||||||
should(result.connectionId).equal('connId');
|
should(result.connectionId).equal('connId');
|
||||||
should(result.connectionString).equal('Data Source=testserver;User Id=testUser;Password=******;Integrated Security=false;Persist Security Info=False;Pooling=False;MultipleActiveResultSets=False;Connect Timeout=60;Encrypt=False;TrustServerCertificate=True');
|
should(result.connectionString).equal('Data Source=testserver;User Id=testUser;Password=******;Integrated Security=false;Persist Security Info=False;Pooling=False;MultipleActiveResultSets=False;Connect Timeout=60;Encrypt=False;TrustServerCertificate=True');
|
||||||
|
should(result.options).equal(mockDacFxOptionsResult.deploymentOptions);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('Should throw error when connecting does not work', async function (): Promise<void> {
|
it('Should throw error when connecting does not work', async function (): Promise<void> {
|
||||||
|
|||||||
@@ -21,6 +21,91 @@ export const mockDacFxResult = {
|
|||||||
report: ''
|
report: ''
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const mockDacFxOptionsResult: mssql.DacFxOptionsResult = {
|
||||||
|
success: true,
|
||||||
|
errorMessage: '',
|
||||||
|
deploymentOptions: {
|
||||||
|
ignoreTableOptions: false,
|
||||||
|
ignoreSemicolonBetweenStatements: false,
|
||||||
|
ignoreRouteLifetime: false,
|
||||||
|
ignoreRoleMembership: false,
|
||||||
|
ignoreQuotedIdentifiers: false,
|
||||||
|
ignorePermissions: false,
|
||||||
|
ignorePartitionSchemes: false,
|
||||||
|
ignoreObjectPlacementOnPartitionScheme: false,
|
||||||
|
ignoreNotForReplication: false,
|
||||||
|
ignoreLoginSids: false,
|
||||||
|
ignoreLockHintsOnIndexes: false,
|
||||||
|
ignoreKeywordCasing: false,
|
||||||
|
ignoreIndexPadding: false,
|
||||||
|
ignoreIndexOptions: false,
|
||||||
|
ignoreIncrement: false,
|
||||||
|
ignoreIdentitySeed: false,
|
||||||
|
ignoreUserSettingsObjects: false,
|
||||||
|
ignoreFullTextCatalogFilePath: false,
|
||||||
|
ignoreWhitespace: false,
|
||||||
|
ignoreWithNocheckOnForeignKeys: false,
|
||||||
|
verifyCollationCompatibility: false,
|
||||||
|
unmodifiableObjectWarnings: false,
|
||||||
|
treatVerificationErrorsAsWarnings: false,
|
||||||
|
scriptRefreshModule: false,
|
||||||
|
scriptNewConstraintValidation: false,
|
||||||
|
scriptFileSize: false,
|
||||||
|
scriptDeployStateChecks: false,
|
||||||
|
scriptDatabaseOptions: false,
|
||||||
|
scriptDatabaseCompatibility: false,
|
||||||
|
scriptDatabaseCollation: false,
|
||||||
|
runDeploymentPlanExecutors: false,
|
||||||
|
registerDataTierApplication: false,
|
||||||
|
populateFilesOnFileGroups: false,
|
||||||
|
noAlterStatementsToChangeClrTypes: false,
|
||||||
|
includeTransactionalScripts: false,
|
||||||
|
includeCompositeObjects: false,
|
||||||
|
allowUnsafeRowLevelSecurityDataMovement: false,
|
||||||
|
ignoreWithNocheckOnCheckConstraints: false,
|
||||||
|
ignoreFillFactor: false,
|
||||||
|
ignoreFileSize: false,
|
||||||
|
ignoreFilegroupPlacement: false,
|
||||||
|
doNotAlterReplicatedObjects: false,
|
||||||
|
doNotAlterChangeDataCaptureObjects: false,
|
||||||
|
disableAndReenableDdlTriggers: false,
|
||||||
|
deployDatabaseInSingleUserMode: false,
|
||||||
|
createNewDatabase: false,
|
||||||
|
compareUsingTargetCollation: false,
|
||||||
|
commentOutSetVarDeclarations: false,
|
||||||
|
blockWhenDriftDetected: false,
|
||||||
|
blockOnPossibleDataLoss: false,
|
||||||
|
backupDatabaseBeforeChanges: false,
|
||||||
|
allowIncompatiblePlatform: false,
|
||||||
|
allowDropBlockingAssemblies: false,
|
||||||
|
dropConstraintsNotInSource: false,
|
||||||
|
dropDmlTriggersNotInSource: false,
|
||||||
|
dropExtendedPropertiesNotInSource: false,
|
||||||
|
dropIndexesNotInSource: false,
|
||||||
|
ignoreFileAndLogFilePath: false,
|
||||||
|
ignoreExtendedProperties: false,
|
||||||
|
ignoreDmlTriggerState: false,
|
||||||
|
ignoreDmlTriggerOrder: false,
|
||||||
|
ignoreDefaultSchema: false,
|
||||||
|
ignoreDdlTriggerState: false,
|
||||||
|
ignoreDdlTriggerOrder: false,
|
||||||
|
ignoreCryptographicProviderFilePath: false,
|
||||||
|
verifyDeployment: false,
|
||||||
|
ignoreComments: false,
|
||||||
|
ignoreColumnCollation: false,
|
||||||
|
ignoreAuthorizer: false,
|
||||||
|
ignoreAnsiNulls: false,
|
||||||
|
generateSmartDefaults: false,
|
||||||
|
dropStatisticsNotInSource: false,
|
||||||
|
dropRoleMembersNotInSource: false,
|
||||||
|
dropPermissionsNotInSource: false,
|
||||||
|
dropObjectsNotInSource: false,
|
||||||
|
ignoreColumnOrder: false,
|
||||||
|
doNotDropObjectTypes: [],
|
||||||
|
excludeObjectTypes: []
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
export class MockDacFxService implements mssql.IDacFxService {
|
export class MockDacFxService implements mssql.IDacFxService {
|
||||||
public exportBacpac(_: string, __: string, ___: string, ____: azdata.TaskExecutionMode): Thenable<mssql.DacFxResult> { return Promise.resolve(mockDacFxResult); }
|
public exportBacpac(_: string, __: string, ___: string, ____: azdata.TaskExecutionMode): Thenable<mssql.DacFxResult> { return Promise.resolve(mockDacFxResult); }
|
||||||
public importBacpac(_: string, __: string, ___: string, ____: azdata.TaskExecutionMode): Thenable<mssql.DacFxResult> { return Promise.resolve(mockDacFxResult); }
|
public importBacpac(_: string, __: string, ___: string, ____: azdata.TaskExecutionMode): Thenable<mssql.DacFxResult> { return Promise.resolve(mockDacFxResult); }
|
||||||
@@ -29,6 +114,7 @@ export class MockDacFxService implements mssql.IDacFxService {
|
|||||||
public deployDacpac(_: string, __: string, ___: boolean, ____: string, _____: azdata.TaskExecutionMode, ______?: Record<string, string>): Thenable<mssql.DacFxResult> { return Promise.resolve(mockDacFxResult); }
|
public deployDacpac(_: string, __: string, ___: boolean, ____: string, _____: azdata.TaskExecutionMode, ______?: Record<string, string>): Thenable<mssql.DacFxResult> { return Promise.resolve(mockDacFxResult); }
|
||||||
public generateDeployScript(_: string, __: string, ___: string, ____: azdata.TaskExecutionMode, ______?: Record<string, string>): Thenable<mssql.DacFxResult> { return Promise.resolve(mockDacFxResult); }
|
public generateDeployScript(_: string, __: string, ___: string, ____: azdata.TaskExecutionMode, ______?: Record<string, string>): Thenable<mssql.DacFxResult> { return Promise.resolve(mockDacFxResult); }
|
||||||
public generateDeployPlan(_: string, __: string, ___: string, ____: azdata.TaskExecutionMode): Thenable<mssql.GenerateDeployPlanResult> { return Promise.resolve(mockDacFxResult); }
|
public generateDeployPlan(_: string, __: string, ___: string, ____: azdata.TaskExecutionMode): Thenable<mssql.GenerateDeployPlanResult> { return Promise.resolve(mockDacFxResult); }
|
||||||
|
public getOptionsFromProfile(_: string): Thenable<mssql.DacFxOptionsResult> { return Promise.resolve(mockDacFxOptionsResult); }
|
||||||
}
|
}
|
||||||
|
|
||||||
export function createContext(): TestContext {
|
export function createContext(): TestContext {
|
||||||
|
|||||||
Reference in New Issue
Block a user