Skip to content

Commit

Permalink
Enforce a minimum version for Kusto and SQL Service dotnet tools. (#2689
Browse files Browse the repository at this point in the history
)

* Enforce a minimum version for Kusto and SQL Service dotnet tools.

* Update name.

* Specify nuget package name.

* Refactor install code and add update

* Add quotes around provided arguments

* Make classes internal

* Remove internal Utils class from API compatibility tests.
  • Loading branch information
corivera authored Feb 7, 2023
1 parent a7154c9 commit 208167e
Show file tree
Hide file tree
Showing 5 changed files with 82 additions and 33 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -276,9 +276,6 @@ Microsoft.DotNet.Interactive.SqlServer
public System.Threading.Tasks.Task HandleAsync(Microsoft.DotNet.Interactive.Commands.SendValue command, Microsoft.DotNet.Interactive.KernelInvocationContext context)
protected System.Void StoreQueryResults(System.Collections.Generic.IReadOnlyCollection<Microsoft.DotNet.Interactive.Formatting.TabularData.TabularDataResource> results, System.CommandLine.Parsing.ParseResult commandKernelChooserParseResult)
public System.Boolean TryGetValue<T>(System.String name, ref T& value)
public static class Utils
public static System.String AsDoubleQuotedString()
public static System.String AsSingleQuotedString()
public class VersionedTextDocumentIdentifier : TextDocumentIdentifier
.ctor()
public System.Int32 Version { get; set;}
Original file line number Diff line number Diff line change
Expand Up @@ -268,9 +268,6 @@ Microsoft.DotNet.Interactive.SqlServer
public System.Threading.Tasks.Task HandleAsync(Microsoft.DotNet.Interactive.Commands.SendValue command, Microsoft.DotNet.Interactive.KernelInvocationContext context)
protected System.Void StoreQueryResults(System.Collections.Generic.IReadOnlyCollection<Microsoft.DotNet.Interactive.Formatting.TabularData.TabularDataResource> results, System.CommandLine.Parsing.ParseResult commandKernelChooserParseResult)
public System.Boolean TryGetValue<T>(System.String name, ref T& value)
public static class Utils
public static System.String AsDoubleQuotedString()
public static System.String AsSingleQuotedString()
public class VersionedTextDocumentIdentifier : TextDocumentIdentifier
.ctor()
public System.Int32 Version { get; set;}
16 changes: 3 additions & 13 deletions src/Microsoft.DotNet.Interactive.Kql/KqlKernelExtension.cs
Original file line number Diff line number Diff line change
@@ -1,11 +1,9 @@
// Copyright (c) .NET Foundation and contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

using System;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Html;
using Microsoft.DotNet.Interactive.Utility;
using Microsoft.DotNet.Interactive.SqlServer;

namespace Microsoft.DotNet.Interactive.Kql;

Expand All @@ -15,16 +13,8 @@ public async Task OnLoadAsync(Kernel kernel)
{
if (kernel is CompositeKernel compositeKernel)
{
// Check if the required Sql Tools Service tool is installed, and then install it if necessary
var dotnet = new Dotnet();
var installedGlobalTools = await dotnet.ToolList();
const string kqlToolName = "MicrosoftKustoServiceLayer";
bool kqlToolInstalled = installedGlobalTools.Any(tool => string.Equals(tool, kqlToolName, StringComparison.InvariantCultureIgnoreCase));
if (!kqlToolInstalled)
{
var commandLineResult = await dotnet.ToolInstall("Microsoft.SqlServer.KustoServiceLayer.Tool", null, null, "1.1.0");
commandLineResult.ThrowOnFailure();
}
var kqlToolName = "MicrosoftKustoServiceLayer";
await Utils.CheckAndInstallGlobalToolAsync(kqlToolName, "1.1.0", "Microsoft.SqlServer.KustoServiceLayer.Tool");

compositeKernel
.AddKernelConnector(new ConnectKqlCommand(kqlToolName));
Expand Down
15 changes: 2 additions & 13 deletions src/Microsoft.DotNet.Interactive.SqlServer/MsSqlKernelExtension.cs
Original file line number Diff line number Diff line change
@@ -1,11 +1,8 @@
// Copyright (c) .NET Foundation and contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

using System;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Html;
using Microsoft.DotNet.Interactive.Utility;

namespace Microsoft.DotNet.Interactive.SqlServer;

Expand All @@ -15,16 +12,8 @@ public async Task OnLoadAsync(Kernel kernel)
{
if (kernel is CompositeKernel compositeKernel)
{
// Check if the required Sql Tools Service tool is installed, and then install it if necessary
var dotnet = new Dotnet();
var installedGlobalTools = await dotnet.ToolList();
const string sqlToolName = "MicrosoftSqlToolsServiceLayer";
bool sqlToolInstalled = installedGlobalTools.Any(tool => string.Equals(tool, sqlToolName, StringComparison.InvariantCultureIgnoreCase));
if (!sqlToolInstalled)
{
var commandLineResult = await dotnet.ToolInstall("Microsoft.SqlServer.SqlToolsServiceLayer.Tool", null, null, "1.1.0");
commandLineResult.ThrowOnFailure();
}
var sqlToolName = "MicrosoftSqlToolsServiceLayer";
await Utils.CheckAndInstallGlobalToolAsync(sqlToolName, "1.1.0", "Microsoft.SqlServer.SqlToolsServiceLayer.Tool");

compositeKernel
.AddKernelConnector(new ConnectMsSqlCommand(sqlToolName));
Expand Down
78 changes: 77 additions & 1 deletion src/Microsoft.DotNet.Interactive.SqlServer/Utils.cs
Original file line number Diff line number Diff line change
@@ -1,9 +1,22 @@
// Copyright (c) .NET Foundation and contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.DotNet.Interactive.Utility;

namespace Microsoft.DotNet.Interactive.SqlServer;

public static class Utils
internal class DotnetToolInfo {
public string PackageId { get; set; }
public string PackageVersion { get; set; }
public string CommandName { get; set; }

}

internal static class Utils
{
/// <summary>
/// Returns a version of the string quoted with single quotes. Any single quotes in the string are escaped as ''
Expand All @@ -24,4 +37,67 @@ public static string AsDoubleQuotedString(this string str)
{
return $"\"{str.Replace("\"", "\\\"")}\"";
}

public static async Task<IEnumerable<DotnetToolInfo>> GetGlobalToolListAsync()
{
var dotnet = new Dotnet();
var result = await dotnet.Execute("tool list --global");
if (result.ExitCode != 0)
{
return new DotnetToolInfo[0];
}

// Output of dotnet tool list is:
// Package Id Version Commands
// -------------------------------------------
// dotnettry.p1 1.0.0 dotnettry.p1

string[] separator = new[] { " " };
return result.Output
.Skip(2)
.Where(s => !string.IsNullOrWhiteSpace(s))
.Select(s =>
{
var parts = s.Split(separator, StringSplitOptions.RemoveEmptyEntries);
return new DotnetToolInfo()
{
PackageId = parts[0],
PackageVersion = parts[1],
CommandName = parts[2]
};
});
}

public static async Task CheckAndInstallGlobalToolAsync(string toolName, string minimumVersion, string nugetPackage)
{
var installedGlobalTools = await Utils.GetGlobalToolListAsync();
var expectedVersion = Version.Parse(minimumVersion);
var installNeeded = true;
var updateNeeded = false;
foreach (var tool in installedGlobalTools)
{
if (string.Equals(tool.CommandName, toolName, StringComparison.InvariantCultureIgnoreCase))
{
installNeeded = false;
var installedVersion = Version.Parse(tool.PackageVersion);
if (installedVersion < expectedVersion)
{
updateNeeded = true;
}
break;
}
}

var dotnet = new Dotnet();
if (updateNeeded)
{
var commandLineResult = await dotnet.Execute($"tool update --global \"{nugetPackage}\" --version \"{minimumVersion}\"");
commandLineResult.ThrowOnFailure();
}
else if (installNeeded)
{
var commandLineResult = await dotnet.Execute($"tool install --global \"{nugetPackage}\" --version \"{minimumVersion}\"");
commandLineResult.ThrowOnFailure();
}
}
}

0 comments on commit 208167e

Please sign in to comment.