From cb479a1cad81bfbd542a171e2f3e19571bd31890 Mon Sep 17 00:00:00 2001 From: Simon Jones Date: Thu, 22 Jul 2021 12:27:40 +0100 Subject: [PATCH 1/4] Disable command line check on non-Windows --- src/Man.Dapr.Sidekick/Native/NativeProcess.cs | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/Man.Dapr.Sidekick/Native/NativeProcess.cs b/src/Man.Dapr.Sidekick/Native/NativeProcess.cs index 6706a46..9bcab91 100644 --- a/src/Man.Dapr.Sidekick/Native/NativeProcess.cs +++ b/src/Man.Dapr.Sidekick/Native/NativeProcess.cs @@ -84,6 +84,13 @@ public static extern IntPtr OpenProcess( public static int GetCommandLine(System.Diagnostics.Process process, out string commandLine) { + if (!DaprConstants.IsWindows) + { + // Return an empty command-line on non-Windows platforms + commandLine = string.Empty; + return 0; + } + var rc = 0; commandLine = null; var hProcess = OpenProcess( @@ -174,7 +181,7 @@ public static int GetCommandLine(System.Diagnostics.Process process, out string public static IEnumerable CommandLineToArgs(string commandLine) { - if (string.IsNullOrEmpty(commandLine)) + if (string.IsNullOrEmpty(commandLine) || !DaprConstants.IsWindows) { return new string[0]; } From e82cd2584d57db1c0a438c9f47bc3e13addcf0da Mon Sep 17 00:00:00 2001 From: Simon Jones Date: Thu, 22 Jul 2021 16:16:03 +0100 Subject: [PATCH 2/4] Disable port assignment checker on Mac OS, unit tests --- README.md | 9 +++++++ src/Man.Dapr.Sidekick/DaprConstants.cs | 2 ++ .../Process/PortAvailabilityChecker.cs | 7 +++++ .../Man.Dapr.Sidekick.Tests.csproj | 15 +++++++++++ .../Process/DaprProcessTests.cs | 4 +-- .../Process/ProcessCommandLineTests.cs | 15 ++++++++--- .../TestResourceHelper.cs | 27 ++++++++++++++++--- 7 files changed, 70 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index 7c67518..1e16d63 100644 --- a/README.md +++ b/README.md @@ -104,6 +104,15 @@ In order to target as many possible .NET platforms as possible with minimal exte Dapr Sidekick also includes a package reference to [Newtonsoft Json.NET](https://github.com/JamesNK/Newtonsoft.Json) for parsing JSON log messages from Dapr. +## Non-Windows Platforms + +On platforms other than Windows (such as Linux and Mac OS) some features of Dapr Sidekick may not be available due to the native API calls not being implemented. These include: + +| Feature | Platforms | Notes | +| --------------------------- | ------------ | ----------------------------------------------------------------- | +| Automatic Port Assignment | Mac OS | Non-default ports must be manually assigned via configuration | +| Attach to existing instance | Linux/Mac OS | Will not detect existing `daprd` instance for same AppId and Port | + ## Acknowledgements Dapr Sidekick has been under active development at [Man Group](http://www.man.com/) since 2020. diff --git a/src/Man.Dapr.Sidekick/DaprConstants.cs b/src/Man.Dapr.Sidekick/DaprConstants.cs index 523280a..f76273f 100644 --- a/src/Man.Dapr.Sidekick/DaprConstants.cs +++ b/src/Man.Dapr.Sidekick/DaprConstants.cs @@ -44,5 +44,7 @@ public class DaprConstants public const string DaprPlacementProcessName = "placement"; public static bool IsWindows => Environment.OSVersion.Platform == PlatformID.Win32NT; + + public static bool IsMacOs => Environment.OSVersion.Platform == PlatformID.MacOSX; } } diff --git a/src/Man.Dapr.Sidekick/Process/PortAvailabilityChecker.cs b/src/Man.Dapr.Sidekick/Process/PortAvailabilityChecker.cs index 2f269e5..e704bd2 100644 --- a/src/Man.Dapr.Sidekick/Process/PortAvailabilityChecker.cs +++ b/src/Man.Dapr.Sidekick/Process/PortAvailabilityChecker.cs @@ -14,6 +14,13 @@ public int GetAvailablePort(int startingPort, IEnumerable reservedPorts = n throw new ArgumentException($"Starting Port cannot be greater than {ushort.MaxValue}", nameof(startingPort)); } + if (DaprConstants.IsMacOs) + { + // IPGlobalProperties.GetIPGlobalProperties() is not implemented in Mac OS (throws System.NotImplementedException). + // Cannot do automatic port assignment. + return startingPort; + } + var ipGlobalProperties = IPGlobalProperties.GetIPGlobalProperties(); var connectionsEndpoints = ipGlobalProperties.GetActiveTcpConnections().Select(c => c.LocalEndPoint); diff --git a/tests/Man.Dapr.Sidekick.Tests/Man.Dapr.Sidekick.Tests.csproj b/tests/Man.Dapr.Sidekick.Tests/Man.Dapr.Sidekick.Tests.csproj index 7400fd3..511b6bf 100644 --- a/tests/Man.Dapr.Sidekick.Tests/Man.Dapr.Sidekick.Tests.csproj +++ b/tests/Man.Dapr.Sidekick.Tests/Man.Dapr.Sidekick.Tests.csproj @@ -8,6 +8,12 @@ + + 3.10.0 + + + 5.0.0 + @@ -23,4 +29,13 @@ + + + 3.10.0 + + + 5.0.0 + + + diff --git a/tests/Man.Dapr.Sidekick.Tests/Process/DaprProcessTests.cs b/tests/Man.Dapr.Sidekick.Tests/Process/DaprProcessTests.cs index 8aa3fc6..3351bd4 100644 --- a/tests/Man.Dapr.Sidekick.Tests/Process/DaprProcessTests.cs +++ b/tests/Man.Dapr.Sidekick.Tests/Process/DaprProcessTests.cs @@ -1,5 +1,4 @@ -#if NETFRAMEWORK -using System.Linq; +using System.Linq; using Man.Dapr.Sidekick.Logging; using NSubstitute; using NUnit.Framework; @@ -273,4 +272,3 @@ public void Should_throw_exception_when_duplicate_process() } } } -#endif diff --git a/tests/Man.Dapr.Sidekick.Tests/Process/ProcessCommandLineTests.cs b/tests/Man.Dapr.Sidekick.Tests/Process/ProcessCommandLineTests.cs index 4b45439..441d65d 100644 --- a/tests/Man.Dapr.Sidekick.Tests/Process/ProcessCommandLineTests.cs +++ b/tests/Man.Dapr.Sidekick.Tests/Process/ProcessCommandLineTests.cs @@ -15,9 +15,18 @@ public void Should_retrieve_commandline() Assert.That(cmd, Is.Not.Null); Assert.That(cmd.Process, Is.SameAs(process)); - // Command line should always contain process EXE name - Assert.That(cmd.CommandLine, Is.Not.Null); - Assert.That(cmd.Arguments, Is.Not.Empty); + if (DaprConstants.IsWindows) + { + // Command line should always contain process EXE name + Assert.That(cmd.CommandLine, Is.Not.Null); + Assert.That(cmd.Arguments, Is.Not.Empty); + } + else + { + // On non-windows platforms everything is empty + Assert.That(cmd.CommandLine, Is.Empty); + Assert.That(cmd.Arguments, Is.Empty); + } var arguments = cmd.GetArgumentsAsDictionary(); Assert.That(arguments, Is.Not.Null); diff --git a/tests/Man.Dapr.Sidekick.Tests/TestResourceHelper.cs b/tests/Man.Dapr.Sidekick.Tests/TestResourceHelper.cs index 497bd34..db3728e 100644 --- a/tests/Man.Dapr.Sidekick.Tests/TestResourceHelper.cs +++ b/tests/Man.Dapr.Sidekick.Tests/TestResourceHelper.cs @@ -1,4 +1,8 @@ using System.IO; +#if !NETFRAMEWORK +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp; +#endif namespace Man.Dapr.Sidekick { @@ -25,12 +29,17 @@ public static string GetResourceFileText(string resourceFile) using var streamReader = new StreamReader(stream); return streamReader.ReadToEnd(); } -#if NETFRAMEWORK public static string CompileTestSystemProcessExe() { - var filename = Path.ChangeExtension(Path.GetTempFileName(), ".exe"); var source = GetResourceFileText("ProcessProgram.cs"); + var filename = Path.GetTempFileName(); + if (DaprConstants.IsWindows) + { + filename = Path.ChangeExtension(filename, "exe"); + } + +#if NETFRAMEWORK var provider = System.CodeDom.Compiler.CodeDomProvider.CreateProvider("CSharp"); var cp = new System.CodeDom.Compiler.CompilerParameters { @@ -39,10 +48,22 @@ public static string CompileTestSystemProcessExe() GenerateInMemory = false }; provider.CompileAssemblyFromSource(cp, source); +#else + var assemblyPath = Path.GetDirectoryName(typeof(object).Assembly.Location); + var syntaxTree = CSharpSyntaxTree.ParseText(source); + var compilation = CSharpCompilation + .Create(Path.GetFileName(filename)) + .WithOptions(new CSharpCompilationOptions(OutputKind.ConsoleApplication)) + .AddReferences( + MetadataReference.CreateFromFile(Path.Combine(assemblyPath, "System.Private.CoreLib.dll")), + MetadataReference.CreateFromFile(Path.Combine(assemblyPath, "System.Console.dll")), + MetadataReference.CreateFromFile(Path.Combine(assemblyPath, "System.Runtime.dll"))) + .AddSyntaxTrees(syntaxTree); + var result = compilation.Emit(filename); +#endif return filename; } -#endif public static void DeleteTestProcess(string filename, int waitMilliseconds = 2000) { From 8b8d44289e7c42bea160b92b7efee18fbb5fd528 Mon Sep 17 00:00:00 2001 From: Simon Jones Date: Thu, 22 Jul 2021 17:04:19 +0100 Subject: [PATCH 3/4] Improve error handling in port checker --- README.md | 3 +- all.sln | 1 + src/Man.Dapr.Sidekick/DaprConstants.cs | 2 - .../Process/PortAvailabilityChecker.cs | 38 ++++++++++--------- 4 files changed, 22 insertions(+), 22 deletions(-) diff --git a/README.md b/README.md index 1e16d63..0d32e2a 100644 --- a/README.md +++ b/README.md @@ -106,11 +106,10 @@ Dapr Sidekick also includes a package reference to [Newtonsoft Json.NET](https:/ ## Non-Windows Platforms -On platforms other than Windows (such as Linux and Mac OS) some features of Dapr Sidekick may not be available due to the native API calls not being implemented. These include: +On platforms other than Windows (such as Linux and Mac OS) some features of Dapr Sidekick may not be available due to the required native API calls not being available. These include: | Feature | Platforms | Notes | | --------------------------- | ------------ | ----------------------------------------------------------------- | -| Automatic Port Assignment | Mac OS | Non-default ports must be manually assigned via configuration | | Attach to existing instance | Linux/Mac OS | Will not detect existing `daprd` instance for same AppId and Port | ## Acknowledgements diff --git a/all.sln b/all.sln index c76a28c..686436a 100644 --- a/all.sln +++ b/all.sln @@ -39,6 +39,7 @@ EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{A321995D-B530-4CAD-B467-16A9A7F36C67}" ProjectSection(SolutionItems) = preProject .editorconfig = .editorconfig + README.md = README.md EndProjectSection EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "ConsulSample", "ConsulSample", "{2DD56FCA-D5C3-4340-B5C5-27E284887A5F}" diff --git a/src/Man.Dapr.Sidekick/DaprConstants.cs b/src/Man.Dapr.Sidekick/DaprConstants.cs index f76273f..523280a 100644 --- a/src/Man.Dapr.Sidekick/DaprConstants.cs +++ b/src/Man.Dapr.Sidekick/DaprConstants.cs @@ -44,7 +44,5 @@ public class DaprConstants public const string DaprPlacementProcessName = "placement"; public static bool IsWindows => Environment.OSVersion.Platform == PlatformID.Win32NT; - - public static bool IsMacOs => Environment.OSVersion.Platform == PlatformID.MacOSX; } } diff --git a/src/Man.Dapr.Sidekick/Process/PortAvailabilityChecker.cs b/src/Man.Dapr.Sidekick/Process/PortAvailabilityChecker.cs index e704bd2..c0dad51 100644 --- a/src/Man.Dapr.Sidekick/Process/PortAvailabilityChecker.cs +++ b/src/Man.Dapr.Sidekick/Process/PortAvailabilityChecker.cs @@ -14,29 +14,31 @@ public int GetAvailablePort(int startingPort, IEnumerable reservedPorts = n throw new ArgumentException($"Starting Port cannot be greater than {ushort.MaxValue}", nameof(startingPort)); } - if (DaprConstants.IsMacOs) + try { - // IPGlobalProperties.GetIPGlobalProperties() is not implemented in Mac OS (throws System.NotImplementedException). - // Cannot do automatic port assignment. - return startingPort; - } + // IPGlobalProperties.GetIPGlobalProperties() is not implemented in some platforms (throws System.NotImplementedException). + // For those we cannot do automatic port assignment, so just return starting port. + var ipGlobalProperties = IPGlobalProperties.GetIPGlobalProperties(); - var ipGlobalProperties = IPGlobalProperties.GetIPGlobalProperties(); + var connectionsEndpoints = ipGlobalProperties.GetActiveTcpConnections().Select(c => c.LocalEndPoint); + var tcpListenersEndpoints = ipGlobalProperties.GetActiveTcpListeners(); + var udpListenersEndpoints = ipGlobalProperties.GetActiveUdpListeners(); + var portsInUse = connectionsEndpoints.Concat(tcpListenersEndpoints) + .Concat(udpListenersEndpoints) + .Select(e => e.Port) + .ToList(); + // Add any additional reserved ports + if (reservedPorts != null) + { + portsInUse.AddRange(reservedPorts); + } - var connectionsEndpoints = ipGlobalProperties.GetActiveTcpConnections().Select(c => c.LocalEndPoint); - var tcpListenersEndpoints = ipGlobalProperties.GetActiveTcpListeners(); - var udpListenersEndpoints = ipGlobalProperties.GetActiveUdpListeners(); - var portsInUse = connectionsEndpoints.Concat(tcpListenersEndpoints) - .Concat(udpListenersEndpoints) - .Select(e => e.Port) - .ToList(); - // Add any additional reserved ports - if (reservedPorts != null) + return Enumerable.Range(startingPort, ushort.MaxValue - startingPort + 1).Except(portsInUse).FirstOrDefault(); + } + catch { - portsInUse.AddRange(reservedPorts); + return startingPort; } - - return Enumerable.Range(startingPort, ushort.MaxValue - startingPort + 1).Except(portsInUse).FirstOrDefault(); } } } From c8e227aac3a2d1124e4ac39101b908098a88d80a Mon Sep 17 00:00:00 2001 From: Simon Jones Date: Thu, 22 Jul 2021 17:31:38 +0100 Subject: [PATCH 4/4] Tidy up test project file references --- .../Man.Dapr.Sidekick.Tests.csproj | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/tests/Man.Dapr.Sidekick.Tests/Man.Dapr.Sidekick.Tests.csproj b/tests/Man.Dapr.Sidekick.Tests/Man.Dapr.Sidekick.Tests.csproj index 511b6bf..1df72b3 100644 --- a/tests/Man.Dapr.Sidekick.Tests/Man.Dapr.Sidekick.Tests.csproj +++ b/tests/Man.Dapr.Sidekick.Tests/Man.Dapr.Sidekick.Tests.csproj @@ -8,12 +8,6 @@ - - 3.10.0 - - - 5.0.0 - @@ -30,12 +24,7 @@ - - 3.10.0 - - - 5.0.0 - +