Update DacFx deploy and generate script with options (#998)

* update deploy and generate script to accept deployment options

* add tests

* add test with option set to true
This commit is contained in:
Kim Santiago
2020-07-29 13:43:38 -07:00
committed by GitHub
parent 9d52370df0
commit 788dc31081
5 changed files with 181 additions and 7 deletions

View File

@@ -4,6 +4,7 @@
//
using System.Collections.Generic;
using Microsoft.SqlTools.Hosting.Protocol.Contracts;
using Microsoft.SqlTools.ServiceLayer.SchemaCompare.Contracts;
namespace Microsoft.SqlTools.ServiceLayer.DacFx.Contracts
{
@@ -21,6 +22,11 @@ namespace Microsoft.SqlTools.ServiceLayer.DacFx.Contracts
/// Gets or sets SQLCMD variables for deployment
/// </summary>
public IDictionary<string, string> SqlCommandVariableValues { get; set; }
/// <summary>
/// Gets or sets the options for deployment
/// </summary>
public DeploymentOptions DeploymentOptions { get; set; }
}
/// <summary>

View File

@@ -4,6 +4,7 @@
//
using System.Collections.Generic;
using Microsoft.SqlTools.Hosting.Protocol.Contracts;
using Microsoft.SqlTools.ServiceLayer.SchemaCompare.Contracts;
namespace Microsoft.SqlTools.ServiceLayer.DacFx.Contracts
{
@@ -26,6 +27,11 @@ namespace Microsoft.SqlTools.ServiceLayer.DacFx.Contracts
/// Gets or sets SQLCMD variables for script generation
/// </summary>
public IDictionary<string, string> SqlCommandVariableValues { get; set; }
/// <summary>
/// Gets or sets the options for deployment
/// </summary>
public DeploymentOptions DeploymentOptions { get; set; }
}
/// <summary>

View File

@@ -5,6 +5,7 @@
using Microsoft.SqlServer.Dac;
using Microsoft.SqlTools.ServiceLayer.Connection;
using Microsoft.SqlTools.ServiceLayer.DacFx.Contracts;
using Microsoft.SqlTools.ServiceLayer.SchemaCompare;
using Microsoft.SqlTools.Utility;
namespace Microsoft.SqlTools.ServiceLayer.DacFx
@@ -25,7 +26,7 @@ namespace Microsoft.SqlTools.ServiceLayer.DacFx
public override void Execute()
{
DacPackage dacpac = DacPackage.Load(this.Parameters.PackageFilePath);
DacDeployOptions options = this.GetDefaultDeployOptions();
DacDeployOptions options = this.Parameters.DeploymentOptions != null ? SchemaCompareUtils.CreateSchemaCompareOptions(this.Parameters.DeploymentOptions) : this.GetDefaultDeployOptions();
if (this.Parameters.SqlCommandVariableValues != null)
{

View File

@@ -2,15 +2,16 @@
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
//
using Microsoft.SqlServer.Dac;
using Microsoft.SqlTools.ServiceLayer.Connection;
using Microsoft.SqlTools.ServiceLayer.DacFx.Contracts;
using Microsoft.SqlTools.ServiceLayer.TaskServices;
using Microsoft.SqlTools.Utility;
using System;
using Microsoft.Data.SqlClient;
using System.Diagnostics;
using System.IO;
using Microsoft.SqlServer.Dac;
using Microsoft.SqlTools.ServiceLayer.Connection;
using Microsoft.SqlTools.ServiceLayer.DacFx.Contracts;
using Microsoft.SqlTools.ServiceLayer.SchemaCompare;
using Microsoft.SqlTools.ServiceLayer.TaskServices;
using Microsoft.SqlTools.Utility;
namespace Microsoft.SqlTools.ServiceLayer.DacFx
{
@@ -35,7 +36,7 @@ namespace Microsoft.SqlTools.ServiceLayer.DacFx
PublishOptions publishOptions = new PublishOptions();
publishOptions.GenerateDeploymentReport = this.Parameters.GenerateDeploymentReport;
publishOptions.CancelToken = this.CancellationToken;
publishOptions.DeployOptions = this.GetDefaultDeployOptions();
publishOptions.DeployOptions = this.Parameters.DeploymentOptions != null ? SchemaCompareUtils.CreateSchemaCompareOptions(this.Parameters.DeploymentOptions) : this.GetDefaultDeployOptions();
if (this.Parameters.SqlCommandVariableValues != null)
{

View File

@@ -8,6 +8,7 @@ using System.IO;
using System.Threading.Tasks;
using Microsoft.Data.SqlClient;
using Microsoft.SqlServer.Dac;
using Microsoft.SqlTools.ServiceLayer.Connection;
using Microsoft.SqlTools.Hosting.Protocol;
using Microsoft.SqlTools.ServiceLayer.Connection.ReliableConnection;
using Microsoft.SqlTools.ServiceLayer.DacFx;
@@ -35,6 +36,8 @@ CREATE TABLE [dbo].[table2]
[col1] NCHAR(10) NULL
)";
private const string SourceViewScript = @"CREATE VIEW [dbo].[view1] AS SELECT dbo.table1.* FROM dbo.table1";
private const string TargetScript = @"CREATE TABLE [dbo].[table2]
(
[ID] INT NOT NULL PRIMARY KEY,
@@ -537,6 +540,163 @@ RETURN 0
}
}
///
/// Verify that options are set correctly for a deploy request
/// </summary>
[Fact]
public async void DeployWithOptions()
{
var result = GetLiveAutoCompleteTestObjects();
SqlTestDb sourceDb = await SqlTestDb.CreateNewAsync(TestServerType.OnPrem, query: SourceScript, dbNamePrefix: "DacFxDeployOptionsTestSource");
sourceDb.RunQuery(SourceViewScript);
SqlTestDb targetDb = await SqlTestDb.CreateNewAsync(TestServerType.OnPrem, query: TargetScript, dbNamePrefix: "DacFxDeployOptionsTestTarget");
try
{
DacFxService service = new DacFxService();
// First extract a db to have a dacpac to deploy later
string dacpacPath = InitialExtract(service, sourceDb, result);
// Deploy the created dacpac with options
var deployParams = new DeployParams
{
PackageFilePath = dacpacPath,
DatabaseName = targetDb.DatabaseName,
UpgradeExisting = true,
DeploymentOptions = new DeploymentOptions()
{
DropObjectsNotInSource = false,
ExcludeObjectTypes = new[] { ObjectType.Views }
}
};
// expect table3 to not have been dropped and view1 to not have been created
await VerifyDeployWithOptions(deployParams, targetDb, service, result.ConnectionInfo, expectedTableResult: "table3", expectedViewResult: null);
// Deploy the created dacpac with options
var deployNoOptionsParams = new DeployParams
{
PackageFilePath = dacpacPath,
DatabaseName = targetDb.DatabaseName,
UpgradeExisting = true
};
// expect table3 to be dropped and view1 created
await VerifyDeployWithOptions(deployNoOptionsParams, targetDb, service, result.ConnectionInfo, expectedTableResult: null, expectedViewResult: "view1");
VerifyAndCleanup(dacpacPath);
}
finally
{
sourceDb.Cleanup();
if (targetDb != null)
{
targetDb.Cleanup();
}
}
}
private async Task VerifyDeployWithOptions(DeployParams deployParams, SqlTestDb targetDb, DacFxService service, ConnectionInfo connInfo, string expectedTableResult, string expectedViewResult)
{
var deployOperation = new DeployOperation(deployParams, connInfo);
service.PerformOperation(deployOperation, TaskExecutionMode.Execute);
using (SqlConnection conn = new SqlConnection(targetDb.ConnectionString))
{
try
{
await conn.OpenAsync();
var deployedResult = (string)ReliableConnectionHelper.ExecuteScalar(conn, $"SELECT TABLE_NAME FROM {targetDb.DatabaseName}.INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 'table3'; ");
Assert.Equal(expectedTableResult, deployedResult);
deployedResult = (string)ReliableConnectionHelper.ExecuteScalar(conn, $"SELECT TABLE_NAME FROM {targetDb.DatabaseName}.INFORMATION_SCHEMA.VIEWS WHERE TABLE_NAME = 'view1'; ");
Assert.Equal(expectedViewResult, deployedResult);
}
finally
{
conn.Close();
}
}
}
// <summary>
/// Verify that options are set correctly for a generate script request
/// </summary>
[Fact]
public async void GenerateDeployScriptWithOptions()
{
var result = GetLiveAutoCompleteTestObjects();
SqlTestDb sourceDb = await SqlTestDb.CreateNewAsync(TestServerType.OnPrem, query: SourceScript, dbNamePrefix: "DacFxDeployOptionsTestSource");
sourceDb.RunQuery(SourceViewScript);
SqlTestDb targetDb = await SqlTestDb.CreateNewAsync(TestServerType.OnPrem, query: TargetScript, dbNamePrefix: "DacFxDeployOptionsTestTarget");
try
{
DacFxService service = new DacFxService();
// First extract a db to have a dacpac to deploy later
string dacpacPath = InitialExtract(service, sourceDb, result);
// generate script to deploy the created dacpac with options
var generateScriptFalseOptionParams = new GenerateDeployScriptParams
{
PackageFilePath = dacpacPath,
DatabaseName = targetDb.DatabaseName,
DeploymentOptions = new DeploymentOptions()
{
DropObjectsNotInSource = false,
ExcludeObjectTypes = new[] { ObjectType.Views }
}
};
var generateScriptFalseOptionOperation = new GenerateDeployScriptOperation(generateScriptFalseOptionParams, result.ConnectionInfo);
service.PerformOperation(generateScriptFalseOptionOperation, TaskExecutionMode.Execute);
Assert.DoesNotContain("table3", generateScriptFalseOptionOperation.Result.DatabaseScript);
Assert.DoesNotContain("CREATE VIEW", generateScriptFalseOptionOperation.Result.DatabaseScript);
// try to deploy with the option set to true to make sure it works
var generateScriptTrueOptionParams = new GenerateDeployScriptParams
{
PackageFilePath = dacpacPath,
DatabaseName = targetDb.DatabaseName,
DeploymentOptions = new DeploymentOptions()
{
DropObjectsNotInSource = true,
ExcludeObjectTypes = new[] { ObjectType.Views }
}
};
var generateScriptTrueOptionOperation = new GenerateDeployScriptOperation(generateScriptTrueOptionParams, result.ConnectionInfo);
service.PerformOperation(generateScriptTrueOptionOperation, TaskExecutionMode.Execute);
Assert.Contains("DROP TABLE [dbo].[table3]", generateScriptTrueOptionOperation.Result.DatabaseScript);
Assert.DoesNotContain("CREATE VIEW", generateScriptTrueOptionOperation.Result.DatabaseScript);
// now generate script without options
var generateScriptNoOptionsParams = new GenerateDeployScriptParams
{
PackageFilePath = dacpacPath,
DatabaseName = targetDb.DatabaseName,
};
var generateScriptNoOptionsOperation = new GenerateDeployScriptOperation(generateScriptNoOptionsParams, result.ConnectionInfo);
service.PerformOperation(generateScriptNoOptionsOperation, TaskExecutionMode.Execute);
Assert.Contains("table3", generateScriptNoOptionsOperation.Result.DatabaseScript);
Assert.Contains("CREATE VIEW", generateScriptNoOptionsOperation.Result.DatabaseScript);
VerifyAndCleanup(dacpacPath);
}
finally
{
sourceDb.Cleanup();
if (targetDb != null)
{
targetDb.Cleanup();
}
}
}
// <summary>
/// Verify that options can get retrieved from publish profile
/// </summary>