Skip to content

Commit

Permalink
Add v2 of the Hosting Service and build nuget packages for it (micros…
Browse files Browse the repository at this point in the history
…oft#675)

* Port v2 of Hosting service to SqlToolsService
- Renamed project to .v2 so that existing hosted service isn't impacted
- Copied over the CoreServices project which contains ConnectionServiceCore and other reusable services for anything interacting with MSSQL
- Ported unit test project across and verified tests run.

* Nuget package support for reusable DLLs

* Use 1.1 version per Karl's suggestion

* Use correct license URL and project URL

* Use new SMO packages
  • Loading branch information
kevcunnane authored Aug 7, 2018
1 parent 4ac02ea commit 7119586
Show file tree
Hide file tree
Showing 224 changed files with 63,367 additions and 2 deletions.
28 changes: 27 additions & 1 deletion build.cake
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ public class BuildPlan
public string[] Frameworks { get; set; }
public string[] Rids { get; set; }
public string[] MainProjects { get; set; }
public string[] PackageProjects { get; set; }
}

var buildPlan = JsonConvert.DeserializeObject<BuildPlan>(
Expand All @@ -65,6 +66,7 @@ var artifactFolder = System.IO.Path.Combine(workingDirectory, buildPlan.Artifact
var publishFolder = System.IO.Path.Combine(artifactFolder, "publish");
var logFolder = System.IO.Path.Combine(artifactFolder, "logs");
var packageFolder = System.IO.Path.Combine(artifactFolder, "package");
var nugetPackageFolder = System.IO.Path.Combine(artifactFolder, "nugetPackages");
var scriptFolder = System.IO.Path.Combine(artifactFolder, "scripts");

/// <summary>
Expand Down Expand Up @@ -226,7 +228,30 @@ Task("BuildTest")
}
}
});

/// <summary>
/// Build Test projects.
/// </summary>
Task("DotnetPack")
.IsDependentOn("Cleanup")
.IsDependentOn("Setup")
.IsDependentOn("Restore")
.Does(() =>
{
foreach (var project in buildPlan.PackageProjects)
{
// For now, putting all nugets in the 1 directory
var outputFolder = System.IO.Path.Combine(nugetPackageFolder);
var projectFolder = System.IO.Path.Combine(sourceFolder, project);
var runLog = new List<string>();
Run(dotnetcli, $"pack --configuration {configuration} --output {outputFolder} \"{projectFolder}\"",
new RunOptions
{
StandardOutputListing = runLog
})
.ExceptionOnError($"Packaging test {project} failed.");
System.IO.File.WriteAllLines(System.IO.Path.Combine(logFolder, $"{project}-pack.log"), runLog.ToArray());
}
});
/// <summary>
/// Run all tests for .NET Desktop and .NET Core
/// </summary>
Expand Down Expand Up @@ -477,6 +502,7 @@ Task("All")
.IsDependentOn("Restore")
.IsDependentOn("TestAll")
.IsDependentOn("AllPublish")
.IsDependentOn("DotnetPack")
//.IsDependentOn("TestPublished")
.Does(() =>
{
Expand Down
6 changes: 6 additions & 0 deletions build.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,5 +19,11 @@
"Microsoft.SqlTools.ServiceLayer",
"Microsoft.SqlTools.Credentials",
"Microsoft.SqlTools.ResourceProvider"
],
"PackageProjects": [
"Microsoft.SqlTools.CoreServices",
"Microsoft.SqlTools.DataProtocol.Contracts",
"Microsoft.SqlTools.Hosting.Contracts",
"Microsoft.SqlTools.Hosting.v2"
]
}
35 changes: 35 additions & 0 deletions sqltoolsservice.sln
Original file line number Diff line number Diff line change
Expand Up @@ -54,8 +54,18 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.SqlTools.Credenti
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.SqlTools.Hosting", "src\Microsoft.SqlTools.Hosting\Microsoft.SqlTools.Hosting.csproj", "{AAE1F8D1-F7AB-4ABE-A55B-D423393AB352}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.SqlTools.Hosting.v2", "src\Microsoft.SqlTools.Hosting.v2\Microsoft.SqlTools.Hosting.csproj", "{BBF1F8D1-F7AB-4ABE-A55B-D423393AB352}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.SqlTools.DataProtocol.Contracts", "src\Microsoft.SqlTools.DataProtocol.Contracts\Microsoft.SqlTools.DataProtocol.Contracts.csproj", "{220E1DEC-32EC-4B3B-A1DB-159ECFDD3A8D}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.SqlTools.CoreServices", "src\Microsoft.SqlTools.CoreServices\Microsoft.SqlTools.CoreServices.csproj", "{444E79F1-477A-481A-9BE6-6559B32CE177}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.SqlTools.Hosting.Contracts", "src\Microsoft.SqlTools.Hosting.Contracts\Microsoft.SqlTools.Hosting.Contracts.csproj", "{BE04C532-C9AE-4C32-9283-F6629112228B}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.SqlTools.ServiceLayer", "src\Microsoft.SqlTools.ServiceLayer\Microsoft.SqlTools.ServiceLayer.csproj", "{835EDEB4-289B-4D6D-A9A0-609E43A87D6E}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.SqlTools.Hosting.UnitTests", "test\Microsoft.SqlTools.Hosting.UnitTests\Microsoft.SqlTools.Hosting.UnitTests.csproj", "{BA3C9622-ABFF-45A2-91AA-CC5189083256}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.SqlTools.ServiceLayer.UnitTests", "test\Microsoft.SqlTools.ServiceLayer.UnitTests\Microsoft.SqlTools.ServiceLayer.UnitTests.csproj", "{F18471B5-2042-409D-BF2C-E5403C322DC9}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.SqlTools.ServiceLayer.TestDriver", "test\Microsoft.SqlTools.ServiceLayer.TestDriver\Microsoft.SqlTools.ServiceLayer.TestDriver.csproj", "{4F250E56-F8B4-4E69-AECC-4D31EDD891E7}"
Expand Down Expand Up @@ -161,6 +171,26 @@ Global
{EFB39C03-F7D2-4E8D-BE51-09121CD71973}.Integration|Any CPU.Build.0 = Debug|Any CPU
{EFB39C03-F7D2-4E8D-BE51-09121CD71973}.Release|Any CPU.ActiveCfg = Release|Any CPU
{EFB39C03-F7D2-4E8D-BE51-09121CD71973}.Release|Any CPU.Build.0 = Release|Any CPU
{BBF1F8D1-F7AB-4ABE-A55B-D423393AB352}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{BBF1F8D1-F7AB-4ABE-A55B-D423393AB352}.Debug|Any CPU.Build.0 = Debug|Any CPU
{BBF1F8D1-F7AB-4ABE-A55B-D423393AB352}.Release|Any CPU.ActiveCfg = Release|Any CPU
{BBF1F8D1-F7AB-4ABE-A55B-D423393AB352}.Release|Any CPU.Build.0 = Release|Any CPU
{220E1DEC-32EC-4B3B-A1DB-159ECFDD3A8D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{220E1DEC-32EC-4B3B-A1DB-159ECFDD3A8D}.Debug|Any CPU.Build.0 = Debug|Any CPU
{220E1DEC-32EC-4B3B-A1DB-159ECFDD3A8D}.Release|Any CPU.ActiveCfg = Release|Any CPU
{220E1DEC-32EC-4B3B-A1DB-159ECFDD3A8D}.Release|Any CPU.Build.0 = Release|Any CPU
{444E79F1-477A-481A-9BE6-6559B32CE177}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{444E79F1-477A-481A-9BE6-6559B32CE177}.Debug|Any CPU.Build.0 = Debug|Any CPU
{444E79F1-477A-481A-9BE6-6559B32CE177}.Release|Any CPU.ActiveCfg = Release|Any CPU
{444E79F1-477A-481A-9BE6-6559B32CE177}.Release|Any CPU.Build.0 = Release|Any CPU
{BE04C532-C9AE-4C32-9283-F6629112228B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{BE04C532-C9AE-4C32-9283-F6629112228B}.Debug|Any CPU.Build.0 = Debug|Any CPU
{BE04C532-C9AE-4C32-9283-F6629112228B}.Release|Any CPU.ActiveCfg = Release|Any CPU
{BE04C532-C9AE-4C32-9283-F6629112228B}.Release|Any CPU.Build.0 = Release|Any CPU
{BA3C9622-ABFF-45A2-91AA-CC5189083256}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{BA3C9622-ABFF-45A2-91AA-CC5189083256}.Debug|Any CPU.Build.0 = Debug|Any CPU
{BA3C9622-ABFF-45A2-91AA-CC5189083256}.Release|Any CPU.ActiveCfg = Release|Any CPU
{BA3C9622-ABFF-45A2-91AA-CC5189083256}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand All @@ -181,6 +211,11 @@ Global
{6FEE7E14-8A1D-454E-8F7C-B63597801787} = {2BBD7364-054F-4693-97CD-1C395E3E84A9}
{70E63BC1-2C82-41C0-89D6-272FD3C7B0C9} = {2BBD7364-054F-4693-97CD-1C395E3E84A9}
{EFB39C03-F7D2-4E8D-BE51-09121CD71973} = {2BBD7364-054F-4693-97CD-1C395E3E84A9}
{BBF1F8D1-F7AB-4ABE-A55B-D423393AB352} = {2BBD7364-054F-4693-97CD-1C395E3E84A9}
{220E1DEC-32EC-4B3B-A1DB-159ECFDD3A8D} = {2BBD7364-054F-4693-97CD-1C395E3E84A9}
{444E79F1-477A-481A-9BE6-6559B32CE177} = {2BBD7364-054F-4693-97CD-1C395E3E84A9}
{BE04C532-C9AE-4C32-9283-F6629112228B} = {2BBD7364-054F-4693-97CD-1C395E3E84A9}
{BA3C9622-ABFF-45A2-91AA-CC5189083256} = {AB9CA2B8-6F70-431C-8A1D-67479D8A7BE4}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {B31CDF4B-2851-45E5-8C5F-BE97125D9DD8}
Expand Down
36 changes: 36 additions & 0 deletions src/Microsoft.SqlTools.CoreServices/Connection/CancelTokenKey.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.SqlTools.DataProtocol.Contracts.Connection;

namespace Microsoft.SqlTools.CoreServices.Connection
{
/// <summary>
/// Used to uniquely identify a CancellationTokenSource associated with both
/// a string URI and a string connection type.
/// </summary>
public class CancelTokenKey : CancelConnectParams, IEquatable<CancelTokenKey>
{
public override bool Equals(object obj)
{
CancelTokenKey other = obj as CancelTokenKey;
if (other == null)
{
return false;
}

return other.OwnerUri == OwnerUri && other.Type == Type;
}

public bool Equals(CancelTokenKey obj)
{
return obj.OwnerUri == OwnerUri && obj.Type == Type;
}

public override int GetHashCode()
{
return OwnerUri.GetHashCode() ^ Type.GetHashCode();
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
//
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
//

using Microsoft.SqlTools.DataProtocol.Contracts.Connection;

namespace Microsoft.SqlTools.CoreServices.Connection
{
/// <summary>
/// Extension methods to ConnectParams
/// </summary>
public static class ConnectParamsExtensions
{
/// <summary>
/// Check that the fields in ConnectParams are all valid
/// </summary>
public static bool IsValid(this ConnectParams parameters, out string errorMessage)
{
errorMessage = string.Empty;
if (string.IsNullOrEmpty(parameters.OwnerUri))
{
errorMessage = SR.ConnectionParamsValidateNullOwnerUri;
}
else if (parameters.Connection == null)
{
errorMessage = SR.ConnectionParamsValidateNullConnection;
}
else if (!string.IsNullOrEmpty(parameters.Connection.ConnectionString))
{
// Do not check other connection parameters if a connection string is present
return string.IsNullOrEmpty(errorMessage);
}
else if (string.IsNullOrEmpty(parameters.Connection.ServerName))
{
errorMessage = SR.ConnectionParamsValidateNullServerName;
}
else if (string.IsNullOrEmpty(parameters.Connection.AuthenticationType) || parameters.Connection.AuthenticationType == "SqlLogin")
{
// For SqlLogin, username cannot be empty
if (string.IsNullOrEmpty(parameters.Connection.UserName))
{
errorMessage = SR.ConnectionParamsValidateNullSqlAuth("UserName");
}
}

return string.IsNullOrEmpty(errorMessage);
}
}
}
171 changes: 171 additions & 0 deletions src/Microsoft.SqlTools.CoreServices/Connection/ConnectionInfo.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,171 @@
//
// 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.Collections.Generic;
using System.Data.Common;
using Microsoft.SqlTools.DataProtocol.Contracts.Connection;
using Microsoft.SqlTools.Hosting.Utility;

namespace Microsoft.SqlTools.CoreServices.Connection
{
/// <summary>
/// Information pertaining to a unique connection instance.
/// </summary>
public class ConnectionInfo
{
/// <summary>
/// Constructor
/// </summary>
public ConnectionInfo(ISqlConnectionFactory factory, string ownerUri, ConnectionDetails details)
{
Factory = factory;
OwnerUri = ownerUri;
ConnectionDetails = details;
ConnectionId = Guid.NewGuid();
IntellisenseMetrics = new InteractionMetrics<double>(new int[] {50, 100, 200, 500, 1000, 2000});
}

/// <summary>
/// Unique Id, helpful to identify a connection info object
/// </summary>
public Guid ConnectionId { get; private set; }

/// <summary>
/// URI identifying the owner/user of the connection. Could be a file, service, resource, etc.
/// </summary>
public string OwnerUri { get; private set; }

/// <summary>
/// Factory used for creating the SQL connection associated with the connection info.
/// </summary>
public ISqlConnectionFactory Factory { get; private set; }

/// <summary>
/// Properties used for creating/opening the SQL connection.
/// </summary>
public ConnectionDetails ConnectionDetails { get; private set; }

/// <summary>
/// A map containing all connections to the database that are associated with
/// this ConnectionInfo's OwnerUri.
/// This is internal for testing access only
/// </summary>
internal readonly ConcurrentDictionary<string, DbConnection> ConnectionTypeToConnectionMap =
new ConcurrentDictionary<string, DbConnection>();

/// <summary>
/// Intellisense Metrics
/// </summary>
public InteractionMetrics<double> IntellisenseMetrics { get; private set; }

/// <summary>
/// Returns true if the db connection is to any cloud instance
/// </summary>
public bool IsCloud { get; set; }

/// <summary>
/// Returns true if the db connection is to a SQL db instance
/// </summary>
public bool IsSqlDb { get; set; }

/// Returns true if the sql connection is to a DW instance
/// </summary>
public bool IsSqlDW { get; set; }

/// <summary>
/// Returns the major version number of the db we are connected to
/// </summary>
public int MajorVersion { get; set; }

/// <summary>
/// All DbConnection instances held by this ConnectionInfo
/// </summary>
public ICollection<DbConnection> AllConnections
{
get
{
return ConnectionTypeToConnectionMap.Values;
}
}

/// <summary>
/// All connection type strings held by this ConnectionInfo
/// </summary>
/// <returns></returns>
public ICollection<string> AllConnectionTypes
{
get
{
return ConnectionTypeToConnectionMap.Keys;
}
}

public bool HasConnectionType(string connectionType)
{
connectionType = connectionType ?? ConnectionType.Default;
return ConnectionTypeToConnectionMap.ContainsKey(connectionType);
}

/// <summary>
/// The count of DbConnectioninstances held by this ConnectionInfo
/// </summary>
public int CountConnections
{
get
{
return ConnectionTypeToConnectionMap.Count;
}
}

/// <summary>
/// Try to get the DbConnection associated with the given connection type string.
/// </summary>
/// <returns>true if a connection with type connectionType was located and out connection was set,
/// false otherwise </returns>
/// <exception cref="ArgumentException">Thrown when connectionType is null or empty</exception>
public bool TryGetConnection(string connectionType, out DbConnection connection)
{
Validate.IsNotNullOrEmptyString("Connection Type", connectionType);
return ConnectionTypeToConnectionMap.TryGetValue(connectionType, out connection);
}

/// <summary>
/// Adds a DbConnection to this object and associates it with the given
/// connection type string. If a connection already exists with an identical
/// connection type string, it is not overwritten. Ignores calls where connectionType = null
/// </summary>
/// <exception cref="ArgumentException">Thrown when connectionType is null or empty</exception>
public void AddConnection(string connectionType, DbConnection connection)
{
Validate.IsNotNullOrEmptyString("Connection Type", connectionType);
ConnectionTypeToConnectionMap.TryAdd(connectionType, connection);
}

/// <summary>
/// Removes the single DbConnection instance associated with string connectionType
/// </summary>
/// <exception cref="ArgumentException">Thrown when connectionType is null or empty</exception>
public void RemoveConnection(string connectionType)
{
Validate.IsNotNullOrEmptyString("Connection Type", connectionType);
DbConnection connection;
ConnectionTypeToConnectionMap.TryRemove(connectionType, out connection);
}

/// <summary>
/// Removes all DbConnection instances held by this object
/// </summary>
public void RemoveAllConnections()
{
foreach (var type in AllConnectionTypes)
{
DbConnection connection;
ConnectionTypeToConnectionMap.TryRemove(type, out connection);
}
}
}
}
Loading

0 comments on commit 7119586

Please sign in to comment.