From 565b7d3f7e90cdf076434a06730053bd6604e143 Mon Sep 17 00:00:00 2001 From: Phillip Hoff Date: Tue, 5 Oct 2021 14:02:15 -0700 Subject: [PATCH] Removes Dapr placement server management (#1191) * Try inverting default placement service behavior. * Eliminate placement service management. * Remove references to placement service options. * Try to determine Dapr status. * Update formatting. --- samples/dapr/pub-sub/tye.yaml | 19 ++-- samples/dapr/service-invocation/tye.yaml | 11 +-- src/Microsoft.Tye.Core/ProcessExtensions.cs | 4 +- .../Dapr/DaprExtension.cs | 98 +++++++++---------- 4 files changed, 57 insertions(+), 75 deletions(-) diff --git a/samples/dapr/pub-sub/tye.yaml b/samples/dapr/pub-sub/tye.yaml index 77d0683db..c9cacd02a 100644 --- a/samples/dapr/pub-sub/tye.yaml +++ b/samples/dapr/pub-sub/tye.yaml @@ -8,10 +8,6 @@ name: dapr extensions: - name: dapr - # If you want to use a different tag or container port - # placement-image: daprio/dapr - # placement-container-port: 50005 - # log-level configures the log level of the dapr sidecar log-level: debug @@ -24,11 +20,8 @@ extensions: # components-path configures the components path of the dapr sidecar components-path: "./components/" - # You can instruct Tye to not create the Dapr placement container on your behalf. This is required if you have Dapr running and want to use that container. - # Doing a `docker ps` can show if its already running. If it's running then you can set 'exclude-placement-container: true' with `placement-port: xxxx` set to the host port of that container. - # (i.e. In Windows + WSL2, Dapr uses 6050 as the host port) - - # exclude-placement-container: true + # If not using the default Dapr placement service or otherwise using a placement service on a nonstandard port, + # you can configure the Dapr sidecar to use an explicit port. # placement-port: 6050 services: - name: orders @@ -42,7 +35,7 @@ services: # # Doing a `docker ps` can show if its already running. If that's the case # then comment out out when running locally. -- name: redis - image: redis - bindings: - - port: 6379 +# - name: redis +# image: redis +# bindings: +# - port: 6379 diff --git a/samples/dapr/service-invocation/tye.yaml b/samples/dapr/service-invocation/tye.yaml index ee4c88f8f..d2b42a1b3 100644 --- a/samples/dapr/service-invocation/tye.yaml +++ b/samples/dapr/service-invocation/tye.yaml @@ -8,10 +8,6 @@ name: distributedtyedemo extensions: - name: dapr - # If you want to use a different tag or container port - # placement-image: daprio/dapr - # placement-container-port: 50005 - # log-level configures the log level of the dapr sidecar log-level: debug @@ -24,11 +20,8 @@ extensions: # components-path configures the components path of the dapr sidecard # components-path: "./components/" - # You can instruct Tye to not create the Dapr placement container on your behalf. This is required if you have Dapr running and want to use that container. - # Doing a `docker ps` can show if its already running. If it's running then you can set 'exclude-placement-container: true' with `placement-port: xxxx` set to the host port of that container. - # (i.e. In Windows + WSL2, Dapr uses 6050 as the host port) - - # exclude-placement-container: true + # If not using the default Dapr placement service or otherwise using a placement service on a nonstandard port, + # you can configure the Dapr sidecar to use an explicit port. # placement-port: 6050 services: # uppercase service is a node app and is run via a dockerfile diff --git a/src/Microsoft.Tye.Core/ProcessExtensions.cs b/src/Microsoft.Tye.Core/ProcessExtensions.cs index c1c328a8b..cd7826a67 100644 --- a/src/Microsoft.Tye.Core/ProcessExtensions.cs +++ b/src/Microsoft.Tye.Core/ProcessExtensions.cs @@ -11,7 +11,7 @@ namespace Microsoft.Tye { - internal static class ProcessExtensions + public static class ProcessExtensions { private static readonly bool _isWindows = RuntimeInformation.IsOSPlatform(OSPlatform.Windows); private static readonly TimeSpan _defaultTimeout = TimeSpan.FromSeconds(30); @@ -97,7 +97,7 @@ private static void KillProcessUnix(int processId, TimeSpan timeout) } } - private static void RunProcessAndWaitForExit(string fileName, string arguments, TimeSpan timeout, out string? stdout) + public static void RunProcessAndWaitForExit(string fileName, string arguments, TimeSpan timeout, out string? stdout) { var startInfo = new ProcessStartInfo { diff --git a/src/Microsoft.Tye.Extensions/Dapr/DaprExtension.cs b/src/Microsoft.Tye.Extensions/Dapr/DaprExtension.cs index 1d0be276c..6a00dd3be 100644 --- a/src/Microsoft.Tye.Extensions/Dapr/DaprExtension.cs +++ b/src/Microsoft.Tye.Extensions/Dapr/DaprExtension.cs @@ -7,73 +7,29 @@ using System.IO; using System.Linq; using System.Runtime.InteropServices; +using System.Text.RegularExpressions; using System.Threading.Tasks; namespace Microsoft.Tye.Extensions.Dapr { internal sealed class DaprExtension : Extension { - public override Task ProcessAsync(ExtensionContext context, ExtensionConfiguration config) + public override async Task ProcessAsync(ExtensionContext context, ExtensionConfiguration config) { // If we're getting called then the user configured dapr in their tye.yaml. // We don't have any of our own config. if (context.Operation == ExtensionContext.OperationKind.LocalRun) { - // default placement port number - var daprPlacementImage = "daprio/dapr"; - var daprPlacementContainerPort = 50005; - var daprPlacementPort = NextPortFinder.GetNextPort(); - var isCustomPlacementPortDefined = false; + await VerifyDaprInitialized(context); + + int? daprPlacementPort = null; // see if a placement port number has been defined if (config.Data.TryGetValue("placement-port", out var obj) && obj?.ToString() is string && int.TryParse(obj.ToString(), out var customPlacementPort)) { context.Output.WriteDebugLine($"Using Dapr placement service host port {customPlacementPort} from 'placement-port'"); daprPlacementPort = customPlacementPort; - isCustomPlacementPortDefined = true; - } - - // see if a placement image has been defined - if (config.Data.TryGetValue("placement-image", out obj) && obj?.ToString() is string customPlacementImage) - { - context.Output.WriteDebugLine($"Using Dapr placement service image {customPlacementImage} from 'placement-image'"); - daprPlacementImage = customPlacementImage; - } - - // see if a placement container port has been defined - if (config.Data.TryGetValue("placement-container-port", out obj) && obj?.ToString() is string && int.TryParse(obj.ToString(), out var customPlacementContainerPort)) - { - context.Output.WriteDebugLine($"Using Dapr placement service container port {customPlacementContainerPort} from 'placement-container-port'"); - daprPlacementContainerPort = customPlacementContainerPort; - } - - // We can only skip injecting a Dapr placement container if a 'placement-port' has been defined and 'exclude-placement-container=true' - if (!(isCustomPlacementPortDefined && config.Data.TryGetValue("exclude-placement-container", out obj) && - obj?.ToString() is string excludePlacementContainer && excludePlacementContainer == "true")) - { - if (!isCustomPlacementPortDefined) - { - context.Output.WriteDebugLine("A 'placement-port' has not been defined. So the 'exclude-placement-container' will default to 'false'."); - } - - context.Output.WriteDebugLine("Injecting Dapr placement service..."); - var daprPlacement = new ContainerServiceBuilder("placement", daprPlacementImage, ServiceSource.Extension) - { - Args = "./placement", - Bindings = { - new BindingBuilder() { - Port = daprPlacementPort, - ContainerPort = daprPlacementContainerPort, - Protocol = "http" - } - } - }; - context.Application.Services.Add(daprPlacement); - } - else - { - context.Output.WriteDebugLine("Skipping injecting Dapr placement service because 'exclude-placement-container=true'."); } // For local run, enumerate all projects, and add services for each dapr proxy. @@ -110,9 +66,14 @@ public override Task ProcessAsync(ExtensionContext context, ExtensionConfigurati // These environment variables are replaced with environment variables // defined for this service. - Args = $"run --app-id {project.Name} --app-port %APP_PORT% --dapr-grpc-port %DAPR_GRPC_PORT% --dapr-http-port %DAPR_HTTP_PORT% --metrics-port %METRICS_PORT% --placement-host-address localhost:{daprPlacementPort}", + Args = $"run --app-id {project.Name} --app-port %APP_PORT% --dapr-grpc-port %DAPR_GRPC_PORT% --dapr-http-port %DAPR_HTTP_PORT% --metrics-port %METRICS_PORT%", }; + if (daprPlacementPort.HasValue) + { + proxy.Args += $" --placement-host-address localhost:{daprPlacementPort.Value}"; + } + // When running locally `-config` specifies a filename, not a configuration name. By convention // we'll assume the filename and config name are the same. if (config.Data.TryGetValue("config", out obj) && obj?.ToString() is string daprConfig) @@ -265,8 +226,43 @@ public override Task ProcessAsync(ExtensionContext context, ExtensionConfigurati } } } + } + + private static Task VerifyDaprInitialized(ExtensionContext context) + { + return Task.Run( + () => + { + string? stdout = null; + + try + { + ProcessExtensions.RunProcessAndWaitForExit("dapr", "--version", TimeSpan.FromSeconds(10), out stdout); + } + catch + { + } + + if (stdout != null) + { + var match = Regex.Match(stdout, "^Runtime version: (?.+)$", RegexOptions.Multiline); + + if (match.Success) + { + if (match.Groups["version"].Value == "n/a") + { + throw new CommandException("Dapr has not been initialized (e.g. via `dapr init`)."); + } + else + { + // Some version of Dapr has been initialized... + return; + } + } + } - return Task.CompletedTask; + context.Output.WriteAlwaysLine($"Unable to determine whether Dapr has been installed and initialized (e.g. via `dapr init`)."); + }); } private string GetDaprExecutablePath()