diff --git a/src/Microsoft.SqlTools.ServiceLayer/DacFx/Contracts/GetOptionsFromProfileRequest.cs b/src/Microsoft.SqlTools.ServiceLayer/DacFx/Contracts/GetOptionsFromProfileRequest.cs
new file mode 100644
index 00000000..809b11e6
--- /dev/null
+++ b/src/Microsoft.SqlTools.ServiceLayer/DacFx/Contracts/GetOptionsFromProfileRequest.cs
@@ -0,0 +1,39 @@
+//
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+//
+using System.Collections.Generic;
+using Microsoft.SqlTools.Hosting.Protocol.Contracts;
+using Microsoft.SqlTools.ServiceLayer.SchemaCompare.Contracts;
+using Microsoft.SqlTools.ServiceLayer.Utility;
+
+namespace Microsoft.SqlTools.ServiceLayer.DacFx.Contracts
+{
+ ///
+ /// Parameters for a DacFx get options from profile request.
+ ///
+ public class GetOptionsFromProfileParams
+ {
+ ///
+ /// Gets or sets the profile path
+ ///
+ public string ProfilePath { get; set; }
+ }
+
+ ///
+ /// Parameters returned from a DacFx get options from profile request.
+ ///
+ public class DacFxOptionsResult : ResultStatus
+ {
+ public DeploymentOptions DeploymentOptions { get; set; }
+ }
+
+ ///
+ /// Defines the DacFx get options from profile request type
+ ///
+ class GetOptionsFromProfileRequest
+ {
+ public static readonly RequestType Type =
+ RequestType.Create("dacfx/getOptionsFromProfile");
+ }
+}
diff --git a/src/Microsoft.SqlTools.ServiceLayer/DacFx/DacFxService.cs b/src/Microsoft.SqlTools.ServiceLayer/DacFx/DacFxService.cs
index 954427df..a4717ba3 100644
--- a/src/Microsoft.SqlTools.ServiceLayer/DacFx/DacFxService.cs
+++ b/src/Microsoft.SqlTools.ServiceLayer/DacFx/DacFxService.cs
@@ -2,16 +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 System;
+using System.Collections.Concurrent;
+using System.Threading.Tasks;
using Microsoft.SqlServer.Dac;
using Microsoft.SqlTools.Hosting.Protocol;
using Microsoft.SqlTools.ServiceLayer.Connection;
using Microsoft.SqlTools.ServiceLayer.DacFx.Contracts;
using Microsoft.SqlTools.ServiceLayer.Hosting;
+using Microsoft.SqlTools.ServiceLayer.SchemaCompare.Contracts;
using Microsoft.SqlTools.ServiceLayer.TaskServices;
-using System;
-using System.Collections.Concurrent;
-using Microsoft.Data.SqlClient;
-using System.Threading.Tasks;
namespace Microsoft.SqlTools.ServiceLayer.DacFx
{
@@ -46,6 +46,7 @@ namespace Microsoft.SqlTools.ServiceLayer.DacFx
serviceHost.SetRequestHandler(DeployRequest.Type, this.HandleDeployRequest);
serviceHost.SetRequestHandler(GenerateDeployScriptRequest.Type, this.HandleGenerateDeployScriptRequest);
serviceHost.SetRequestHandler(GenerateDeployPlanRequest.Type, this.HandleGenerateDeployPlanRequest);
+ serviceHost.SetRequestHandler(GetOptionsFromProfileRequest.Type, this.HandleGetOptionsFromProfileRequest);
}
///
@@ -223,6 +224,38 @@ namespace Microsoft.SqlTools.ServiceLayer.DacFx
}
}
+ ///
+ /// Handles request to get the options from a publish profile
+ ///
+ ///
+ public async Task HandleGetOptionsFromProfileRequest(GetOptionsFromProfileParams parameters, RequestContext requestContext)
+ {
+ try
+ {
+ DeploymentOptions options = null;
+ if (parameters.ProfilePath != null)
+ {
+ DacProfile profile = DacProfile.Load(parameters.ProfilePath);
+ if (profile.DeployOptions != null)
+ {
+ options = new DeploymentOptions();
+ await options.InitializeFromProfile(profile.DeployOptions, parameters.ProfilePath);
+ }
+ }
+
+ await requestContext.SendResult(new DacFxOptionsResult()
+ {
+ DeploymentOptions = options,
+ Success = true,
+ ErrorMessage = string.Empty,
+ });
+ }
+ catch (Exception e)
+ {
+ await requestContext.SendError(e);
+ }
+ }
+
private void ExecuteOperation(DacFxOperation operation, DacFxParams parameters, string taskName, RequestContext requestContext)
{
Task.Run(async () =>
diff --git a/src/Microsoft.SqlTools.ServiceLayer/SchemaCompare/Contracts/DeploymentOptions.cs b/src/Microsoft.SqlTools.ServiceLayer/SchemaCompare/Contracts/DeploymentOptions.cs
index c6283447..33f1e89d 100644
--- a/src/Microsoft.SqlTools.ServiceLayer/SchemaCompare/Contracts/DeploymentOptions.cs
+++ b/src/Microsoft.SqlTools.ServiceLayer/SchemaCompare/Contracts/DeploymentOptions.cs
@@ -2,12 +2,9 @@
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
//
-
+using System.IO;
+using System.Threading.Tasks;
using Microsoft.SqlServer.Dac;
-using System;
-using System.Collections.Generic;
-using System.ComponentModel;
-using System.Text;
namespace Microsoft.SqlTools.ServiceLayer.SchemaCompare.Contracts
{
@@ -241,6 +238,52 @@ namespace Microsoft.SqlTools.ServiceLayer.SchemaCompare.Contracts
}
public DeploymentOptions(DacDeployOptions options)
+ {
+ SetOptions(options);
+ }
+
+ ///
+ /// initialize deployment options from the options in a publish profile.xml
+ ///
+ /// options created from the profile
+ ///
+ public async Task InitializeFromProfile(DacDeployOptions options, string profilePath)
+ {
+ // check if defaults need to be set if they aren't specified in the profile
+ string contents = await File.ReadAllTextAsync(profilePath);
+ if (!contents.Contains(""))
+ {
+ options.AllowDropBlockingAssemblies = true;
+ }
+ if (!contents.Contains(""))
+ {
+ options.AllowIncompatiblePlatform = true;
+ }
+ if (!contents.Contains(""))
+ {
+ options.DropObjectsNotInSource = true;
+ }
+ if (!contents.Contains(""))
+ {
+ options.DropPermissionsNotInSource = true;
+ }
+ if (!contents.Contains(""))
+ {
+ options.DropRoleMembersNotInSource = true;
+ }
+ if (!contents.Contains(""))
+ {
+ options.IgnoreKeywordCasing = false;
+ }
+ if (!contents.Contains(""))
+ {
+ options.IgnoreSemicolonBetweenStatements = false;
+ }
+
+ SetOptions(options);
+ }
+
+ public void SetOptions(DacDeployOptions options)
{
System.Reflection.PropertyInfo[] deploymentOptionsProperties = this.GetType().GetProperties();
diff --git a/test/Microsoft.SqlTools.ServiceLayer.IntegrationTests/DacFx/DacFxserviceTests.cs b/test/Microsoft.SqlTools.ServiceLayer.IntegrationTests/DacFx/DacFxserviceTests.cs
index fa771ba3..5a8b7eba 100644
--- a/test/Microsoft.SqlTools.ServiceLayer.IntegrationTests/DacFx/DacFxserviceTests.cs
+++ b/test/Microsoft.SqlTools.ServiceLayer.IntegrationTests/DacFx/DacFxserviceTests.cs
@@ -5,20 +5,25 @@
using System;
using System.Collections.Generic;
using System.IO;
+using System.Threading.Tasks;
using Microsoft.Data.SqlClient;
using Microsoft.SqlServer.Dac;
+using Microsoft.SqlTools.Hosting.Protocol;
using Microsoft.SqlTools.ServiceLayer.Connection.ReliableConnection;
using Microsoft.SqlTools.ServiceLayer.DacFx;
using Microsoft.SqlTools.ServiceLayer.DacFx.Contracts;
using Microsoft.SqlTools.ServiceLayer.IntegrationTests.Utility;
+using Microsoft.SqlTools.ServiceLayer.SchemaCompare.Contracts;
using Microsoft.SqlTools.ServiceLayer.TaskServices;
using Microsoft.SqlTools.ServiceLayer.Test.Common;
+using Moq;
using Xunit;
namespace Microsoft.SqlTools.ServiceLayer.IntegrationTests.DacFx
{
public class DacFxServiceTests
{
+ private string publishProfileFolder = Path.Combine("..", "..", "..", "DacFx", "PublishProfiles");
private const string SourceScript = @"CREATE TABLE [dbo].[table1]
(
[ID] INT NOT NULL PRIMARY KEY,
@@ -532,6 +537,80 @@ RETURN 0
}
}
+ //
+ /// Verify that options can get retrieved from publish profile
+ ///
+ [Fact]
+ public async void GetOptionsFromProfile()
+ {
+ DeploymentOptions expectedResults = new DeploymentOptions()
+ {
+ ExcludeObjectTypes = null,
+ IncludeCompositeObjects = true,
+ BlockOnPossibleDataLoss = true,
+ AllowIncompatiblePlatform = true
+ };
+
+ var dacfxRequestContext = new Mock>();
+ dacfxRequestContext.Setup((RequestContext x) => x.SendResult(It.Is((result) => ValidateOptions(expectedResults, result.DeploymentOptions) == true))).Returns(Task.FromResult(new object()));
+
+ DacFxService service = new DacFxService();
+ string file = Path.Combine(publishProfileFolder, "profileWithOptions.publish.xml");
+
+ var getOptionsFromProfileParams = new GetOptionsFromProfileParams
+ {
+ ProfilePath = file
+ };
+
+ await service.HandleGetOptionsFromProfileRequest(getOptionsFromProfileParams, dacfxRequestContext.Object);
+ dacfxRequestContext.VerifyAll();
+ }
+
+ //
+ /// Verify that default options are returned if a profile doesn't specify any options
+ ///
+ [Fact]
+ public async void GetOptionsFromProfileWithoutOptions()
+ {
+ DeploymentOptions expectedResults = new DeploymentOptions();
+ expectedResults.ExcludeObjectTypes = null;
+
+ var dacfxRequestContext = new Mock>();
+ dacfxRequestContext.Setup((RequestContext x) => x.SendResult(It.Is((result) => ValidateOptions(expectedResults, result.DeploymentOptions) == true))).Returns(Task.FromResult(new object()));
+
+ DacFxService service = new DacFxService();
+ string file = Path.Combine(publishProfileFolder, "profileNoOptions.publish.xml");
+
+ var getOptionsFromProfileParams = new GetOptionsFromProfileParams
+ {
+ ProfilePath = file
+ };
+
+ await service.HandleGetOptionsFromProfileRequest(getOptionsFromProfileParams, dacfxRequestContext.Object);
+ dacfxRequestContext.VerifyAll();
+ }
+
+ private bool ValidateOptions(DeploymentOptions expected, DeploymentOptions actual)
+ {
+ System.Reflection.PropertyInfo[] deploymentOptionsProperties = expected.GetType().GetProperties();
+ foreach (var v in deploymentOptionsProperties)
+ {
+ var defaultP = v.GetValue(expected);
+ var actualP = v.GetValue(actual);
+
+ if (v.Name == "ExcludeObjectTypes")
+ {
+ Assert.True((defaultP as ObjectType[])?.Length == (actualP as ObjectType[])?.Length, "Number of excluded objects is different not equal");
+ }
+ else
+ {
+ Assert.True((defaultP == null && actualP == null) || (defaultP == null && (actualP as string) == string.Empty) || defaultP.Equals(actualP), $"Actual Property from Service is not equal to default property for {v.Name}, Actual value: {actualP} and Default value: {defaultP}");
+ }
+ }
+
+ return true;
+ }
+
private string InitialExtract(DacFxService service, SqlTestDb sourceDb, LiveConnectionHelper.TestConnectionResult result)
{
string folderPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "DacFxTest");
diff --git a/test/Microsoft.SqlTools.ServiceLayer.IntegrationTests/DacFx/PublishProfiles/profileNoOptions.publish.xml b/test/Microsoft.SqlTools.ServiceLayer.IntegrationTests/DacFx/PublishProfiles/profileNoOptions.publish.xml
new file mode 100644
index 00000000..50ac3a6e
--- /dev/null
+++ b/test/Microsoft.SqlTools.ServiceLayer.IntegrationTests/DacFx/PublishProfiles/profileNoOptions.publish.xml
@@ -0,0 +1,14 @@
+
+
+
+ testdb
+ DatabaseProjectTestdb.sql
+ 1
+
+
+
+ prodname
+ $(SqlCmdVar__1)
+
+
+
\ No newline at end of file
diff --git a/test/Microsoft.SqlTools.ServiceLayer.IntegrationTests/DacFx/PublishProfiles/profileWithOptions.publish.xml b/test/Microsoft.SqlTools.ServiceLayer.IntegrationTests/DacFx/PublishProfiles/profileWithOptions.publish.xml
new file mode 100644
index 00000000..1f9843c9
--- /dev/null
+++ b/test/Microsoft.SqlTools.ServiceLayer.IntegrationTests/DacFx/PublishProfiles/profileWithOptions.publish.xml
@@ -0,0 +1,17 @@
+
+
+
+ True
+ testdb
+ DatabaseProjectTestdb.sql
+ 1
+ True
+ True
+
+
+
+ prodname
+ $(SqlCmdVar__1)
+
+
+
\ No newline at end of file