From 277781bffc5273e4274e35f7bac0f06d6e7d99f0 Mon Sep 17 00:00:00 2001 From: Mitch Denny Date: Tue, 15 Oct 2024 19:00:48 +1100 Subject: [PATCH] WaitFor support for Dapr components. (#6240) * Dapr with wait support (WIP). * WIP * Copy WaitAnnotation to dapr cli resources. --- .../dapr/Dapr.AppHost/Dapr.AppHost.csproj | 1 + playground/dapr/Dapr.AppHost/Program.cs | 8 +- playground/dapr/Dapr.AppHost/pubsub.yaml | 17 ++++ .../Resources/Logs.Designer.cs | 81 +++++++++++++++++++ ...DaprDistributedApplicationLifecycleHook.cs | 14 ++++ .../IDaprComponentResource.cs | 2 +- ...DistributedApplicationBuilderExtensions.cs | 1 - 7 files changed, 121 insertions(+), 3 deletions(-) create mode 100644 playground/dapr/Dapr.AppHost/pubsub.yaml create mode 100644 src/Aspire.Dashboard/Resources/Logs.Designer.cs diff --git a/playground/dapr/Dapr.AppHost/Dapr.AppHost.csproj b/playground/dapr/Dapr.AppHost/Dapr.AppHost.csproj index 16402c3e77..63a9cb3244 100644 --- a/playground/dapr/Dapr.AppHost/Dapr.AppHost.csproj +++ b/playground/dapr/Dapr.AppHost/Dapr.AppHost.csproj @@ -15,6 +15,7 @@ + diff --git a/playground/dapr/Dapr.AppHost/Program.cs b/playground/dapr/Dapr.AppHost/Program.cs index 32216d54c0..dbdf683809 100644 --- a/playground/dapr/Dapr.AppHost/Program.cs +++ b/playground/dapr/Dapr.AppHost/Program.cs @@ -1,7 +1,13 @@ var builder = DistributedApplication.CreateBuilder(args); +var rmq = builder.AddRabbitMQ("rabbitMQ") + .WithManagementPlugin() + .WithEndpoint("tcp", e => e.Port = 5672) + .WithEndpoint("management", e => e.Port = 15672); + var stateStore = builder.AddDaprStateStore("statestore"); -var pubSub = builder.AddDaprPubSub("pubsub"); +var pubSub = builder.AddDaprPubSub("pubsub") + .WaitFor(rmq); builder.AddProject("servicea") .WithDaprSidecar() diff --git a/playground/dapr/Dapr.AppHost/pubsub.yaml b/playground/dapr/Dapr.AppHost/pubsub.yaml new file mode 100644 index 0000000000..419df9f0f3 --- /dev/null +++ b/playground/dapr/Dapr.AppHost/pubsub.yaml @@ -0,0 +1,17 @@ +apiVersion: dapr.io/v1alpha1 +kind: Component +metadata: + name: pubsub + namespace: default +spec: + type: pubsub.rabbitmq + version: v1 + metadata: + - name: protocol + value: amqp + - name: hostname + value: localhost + - name: username + value: guest + - name: password + value: guest diff --git a/src/Aspire.Dashboard/Resources/Logs.Designer.cs b/src/Aspire.Dashboard/Resources/Logs.Designer.cs new file mode 100644 index 0000000000..0e3cd707ba --- /dev/null +++ b/src/Aspire.Dashboard/Resources/Logs.Designer.cs @@ -0,0 +1,81 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.42000 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace Aspire.Dashboard.Resources { + using System; + + + /// + /// A strongly-typed resource class, for looking up localized strings, etc. + /// + // This class was auto-generated by the StronglyTypedResourceBuilder + // class via a tool like ResGen or Visual Studio. + // To add or remove a member, edit your .ResX file then rerun ResGen + // with the /str option, or rebuild your VS project. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + public class Logs { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Logs() { + } + + /// + /// Returns the cached ResourceManager instance used by this class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + public static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Aspire.Dashboard.Resources.Logs", typeof(Logs).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + public static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + + /// + /// Looks up a localized string similar to contains. + /// + public static string LogContains { + get { + return ResourceManager.GetString("LogContains", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to not contains. + /// + public static string LogNotContains { + get { + return ResourceManager.GetString("LogNotContains", resourceCulture); + } + } + } +} diff --git a/src/Aspire.Hosting.Dapr/DaprDistributedApplicationLifecycleHook.cs b/src/Aspire.Hosting.Dapr/DaprDistributedApplicationLifecycleHook.cs index 9e7c7ef4d0..087e2a1b51 100644 --- a/src/Aspire.Hosting.Dapr/DaprDistributedApplicationLifecycleHook.cs +++ b/src/Aspire.Hosting.Dapr/DaprDistributedApplicationLifecycleHook.cs @@ -72,8 +72,16 @@ public async Task BeforeStartAsync(DistributedApplicationModel appModel, Cancell var componentReferenceAnnotations = resource.Annotations.OfType(); + var waitAnnotationsToCopyToDaprCli = new List(); + foreach (var componentReferenceAnnotation in componentReferenceAnnotations) { + // Whilst we are passing over each component annotations collect the list of annotations to copy to the Dapr CLI. + if (componentReferenceAnnotation.Component.TryGetAnnotationsOfType(out var componentWaitAnnotations)) + { + waitAnnotationsToCopyToDaprCli.AddRange(componentWaitAnnotations); + } + if (componentReferenceAnnotation.Component.Options?.LocalPath is not null) { var localPathDirectory = Path.GetDirectoryName(NormalizePath(componentReferenceAnnotation.Component.Options.LocalPath)); @@ -94,6 +102,9 @@ public async Task BeforeStartAsync(DistributedApplicationModel appModel, Cancell } } + // It is possible that we have duplicate wate annotations so we just dedupe them here. + var distinctWaitAnnotationsToCopyToDaprCli = waitAnnotationsToCopyToDaprCli.DistinctBy(w => (w.Resource, w.WaitType)); + var daprAppPortArg = (int? port) => ModelNamedArg("--app-port", port); var daprGrpcPortArg = (object port) => ModelNamedObjectArg("--dapr-grpc-port", port); var daprHttpPortArg = (object port) => ModelNamedObjectArg("--dapr-http-port", port); @@ -137,6 +148,9 @@ public async Task BeforeStartAsync(DistributedApplicationModel appModel, Cancell var daprCliResourceName = $"{daprSidecar.Name}-cli"; var daprCli = new ExecutableResource(daprCliResourceName, fileName, appHostDirectory); + // Add all the unique wait annotations to the CLI. + daprCli.Annotations.AddRange(distinctWaitAnnotationsToCopyToDaprCli); + resource.Annotations.Add( new EnvironmentCallbackAnnotation( context => diff --git a/src/Aspire.Hosting.Dapr/IDaprComponentResource.cs b/src/Aspire.Hosting.Dapr/IDaprComponentResource.cs index dd650b9bba..bc49b8be61 100644 --- a/src/Aspire.Hosting.Dapr/IDaprComponentResource.cs +++ b/src/Aspire.Hosting.Dapr/IDaprComponentResource.cs @@ -8,7 +8,7 @@ namespace Aspire.Hosting.Dapr; /// /// Represents a Dapr component resource. /// -public interface IDaprComponentResource : IResource +public interface IDaprComponentResource : IResource, IResourceWithWaitSupport { /// /// Gets the type of the Dapr component. diff --git a/src/Aspire.Hosting.Dapr/IDistributedApplicationBuilderExtensions.cs b/src/Aspire.Hosting.Dapr/IDistributedApplicationBuilderExtensions.cs index 6266bb5c0c..c1eb5b2043 100644 --- a/src/Aspire.Hosting.Dapr/IDistributedApplicationBuilderExtensions.cs +++ b/src/Aspire.Hosting.Dapr/IDistributedApplicationBuilderExtensions.cs @@ -43,7 +43,6 @@ public static IDistributedApplicationBuilder AddDapr(this IDistributedApplicatio public static IResourceBuilder AddDaprComponent(this IDistributedApplicationBuilder builder, [ResourceName] string name, string type, DaprComponentOptions? options = null) { var resource = new DaprComponentResource(name, type) { Options = options }; - return builder .AddResource(resource) .WithInitialState(new()