33
44using Aspire . Hosting . ApplicationModel ;
55using Microsoft . Extensions . DependencyInjection ;
6- using Microsoft . Extensions . Hosting ;
76using SurrealDb . Net ;
7+ using System . Text ;
88using System . Text . Json ;
99
1010namespace Aspire . Hosting ;
@@ -284,108 +284,125 @@ public static IResourceBuilder<T> WithSurrealist<T>(
284284
285285 containerName ??= $ "{ builder . Resource . Name } -surrealist";
286286
287- const string CONNECTIONS_FILE_PATH = "/usr/share/nginx/html/instance.json" ;
288-
289287 var surrealistContainer = new SurrealistContainerResource ( containerName ) ;
290288 var surrealistContainerBuilder = builder . ApplicationBuilder . AddResource ( surrealistContainer )
291289 . WithImage ( SurrealDbContainerImageTags . SurrealistImage , SurrealDbContainerImageTags . SurrealistTag )
292290 . WithImageRegistry ( SurrealDbContainerImageTags . SurrealistRegistry )
293291 . WithHttpEndpoint ( targetPort : 8080 , name : "http" )
294- . WithBindMount ( Path . GetTempFileName ( ) , CONNECTIONS_FILE_PATH )
295292 . WithRelationship ( builder . Resource , "Surrealist" )
296293 . ExcludeFromManifest ( ) ;
294+
295+ surrealistContainerBuilder . WithContainerFiles (
296+ destinationPath : "/usr/share/nginx/html" ,
297+ callback : async ( _ , cancellationToken ) =>
298+ {
299+ var surrealDbServerInstances =
300+ builder . ApplicationBuilder . Resources . OfType < SurrealDbServerResource > ( ) . ToList ( ) ;
301+ var surrealDbNamespaceResources =
302+ builder . ApplicationBuilder . Resources . OfType < SurrealDbNamespaceResource > ( ) . ToList ( ) ;
303+ var surrealDbDatabaseResources =
304+ builder . ApplicationBuilder . Resources . OfType < SurrealDbDatabaseResource > ( ) . ToList ( ) ;
305+
306+ return [
307+ new ContainerFile
308+ {
309+ Name = "instance.json" ,
310+ Contents = await WriteSurrealistInstanceJson (
311+ surrealDbServerInstances ,
312+ surrealDbNamespaceResources ,
313+ surrealDbDatabaseResources ,
314+ cancellationToken
315+ ) . ConfigureAwait ( false ) ,
316+ } ,
317+ ] ;
318+ } ) ;
297319
298- builder . ApplicationBuilder . Eventing . Subscribe < AfterEndpointsAllocatedEvent > ( ( e , ct ) =>
320+ configureContainer ? . Invoke ( surrealistContainerBuilder ) ;
321+
322+ return builder ;
323+ }
324+
325+ private static async Task < string > WriteSurrealistInstanceJson (
326+ IList < SurrealDbServerResource > surrealDbServerInstances ,
327+ IList < SurrealDbNamespaceResource > surrealDbNamespaceResources ,
328+ IList < SurrealDbDatabaseResource > surrealDbDatabaseResources ,
329+ CancellationToken cancellationToken
330+ )
331+ {
332+ using var stream = new MemoryStream ( ) ;
333+ await using var writer = new Utf8JsonWriter ( stream , new JsonWriterOptions { Indented = true } ) ;
334+
335+ writer . WriteStartObject ( ) ;
336+
337+ writer . WriteStartArray ( "connections" ) ;
338+
339+ foreach ( var surrealInstance in surrealDbServerInstances )
340+ {
341+ if ( surrealInstance . PrimaryEndpoint . IsAllocated )
299342 {
300- var serverFileMount = surrealistContainer . Annotations . OfType < ContainerMountAnnotation > ( ) . Single ( v => v . Target == CONNECTIONS_FILE_PATH ) ;
301- var surrealDbServerResources = builder . ApplicationBuilder . Resources . OfType < SurrealDbServerResource > ( ) . ToList ( ) ;
343+ SurrealDbNamespaceResource ? uniqueNamespace = null ;
344+ SurrealDbDatabaseResource ? uniqueDatabase = null ;
302345
303- using var stream = new FileStream ( serverFileMount . Source ! , FileMode . Create ) ;
304- using var writer = new Utf8JsonWriter ( stream ) ;
346+ var serverNamespaces = surrealDbNamespaceResources
347+ . Where ( ns => ns . Parent == surrealInstance )
348+ . ToList ( ) ;
305349
306- // Need to grant read access to the config file on unix like systems.
307- if ( ! OperatingSystem . IsWindows ( ) )
350+ if ( serverNamespaces . Count == 1 )
308351 {
309- File . SetUnixFileMode ( serverFileMount . Source ! , UnixFileMode . UserRead | UnixFileMode . UserWrite | UnixFileMode . GroupRead | UnixFileMode . OtherRead ) ;
352+ uniqueNamespace = serverNamespaces . First ( ) ;
353+
354+ var nsDatabases = surrealDbDatabaseResources
355+ . Where ( db => db . Parent == uniqueNamespace )
356+ . ToList ( ) ;
357+
358+ if ( nsDatabases . Count == 1 )
359+ {
360+ uniqueDatabase = nsDatabases . First ( ) ;
361+ }
310362 }
311363
312- writer . WriteStartObject ( ) ;
364+ var endpoint = surrealInstance . PrimaryEndpoint ;
313365
314- writer . WriteStartArray ( "connections" ) ;
366+ writer . WriteStartObject ( ) ;
315367
316- var surrealDbNamespaceResources = builder . ApplicationBuilder . Resources . OfType < SurrealDbNamespaceResource > ( ) . ToList ( ) ;
317- var surrealDbDatabaseResources = builder . ApplicationBuilder . Resources . OfType < SurrealDbDatabaseResource > ( ) . ToList ( ) ;
368+ writer . WriteString ( "id" , surrealInstance . Name ) ;
369+ writer . WriteString ( "name" , surrealInstance . Name ) ;
318370
319- foreach ( var surrealInstance in surrealDbServerResources )
371+ if ( uniqueNamespace is not null )
320372 {
321- if ( surrealInstance . PrimaryEndpoint . IsAllocated )
322- {
323- SurrealDbNamespaceResource ? uniqueNamespace = null ;
324- SurrealDbDatabaseResource ? uniqueDatabase = null ;
325-
326- var serverNamespaces = surrealDbNamespaceResources
327- . Where ( ns => ns . Parent == surrealInstance )
328- . ToList ( ) ;
329-
330- if ( serverNamespaces . Count == 1 )
331- {
332- uniqueNamespace = serverNamespaces . First ( ) ;
333-
334- var nsDatabases = surrealDbDatabaseResources
335- . Where ( db => db . Parent == uniqueNamespace )
336- . ToList ( ) ;
337-
338- if ( nsDatabases . Count == 1 )
339- {
340- uniqueDatabase = nsDatabases . First ( ) ;
341- }
342- }
343-
344- var endpoint = surrealInstance . PrimaryEndpoint ;
345-
346- writer . WriteStartObject ( ) ;
347-
348- writer . WriteString ( "id" , surrealInstance . Name ) ;
349- writer . WriteString ( "name" , surrealInstance . Name ) ;
350-
351- if ( uniqueNamespace is not null )
352- {
353- writer . WriteString ( "defaultNamespace" , uniqueNamespace . NamespaceName ) ;
354- }
355- if ( uniqueDatabase is not null )
356- {
357- writer . WriteString ( "defaultDatabase" , uniqueDatabase . DatabaseName ) ;
358- }
359-
360- writer . WriteStartObject ( "authentication" ) ;
361- writer . WriteString ( "protocol" , "ws" ) ;
362- // How to do host resolution?
363- writer . WriteString ( "hostname" , $ "localhost:{ endpoint . Port } ") ;
364- writer . WriteString ( "mode" , "root" ) ;
365- if ( uniqueNamespace is not null )
366- {
367- writer . WriteString ( "namespace" , uniqueNamespace . NamespaceName ) ;
368- }
369- if ( uniqueDatabase is not null )
370- {
371- writer . WriteString ( "database" , uniqueDatabase . DatabaseName ) ;
372- }
373-
374- writer . WriteEndObject ( ) ;
375-
376- writer . WriteEndObject ( ) ;
377- }
373+ writer . WriteString ( "defaultNamespace" , uniqueNamespace . NamespaceName ) ;
374+ }
375+ if ( uniqueDatabase is not null )
376+ {
377+ writer . WriteString ( "defaultDatabase" , uniqueDatabase . DatabaseName ) ;
378378 }
379379
380- writer . WriteEndArray ( ) ;
380+ writer . WriteStartObject ( "authentication" ) ;
381+ writer . WriteString ( "protocol" , "ws" ) ;
382+ // How to do host resolution?
383+ writer . WriteString ( "hostname" , $ "localhost:{ endpoint . Port } ") ;
384+ writer . WriteString ( "mode" , "root" ) ;
385+ if ( uniqueNamespace is not null )
386+ {
387+ writer . WriteString ( "namespace" , uniqueNamespace . NamespaceName ) ;
388+ }
389+ if ( uniqueDatabase is not null )
390+ {
391+ writer . WriteString ( "database" , uniqueDatabase . DatabaseName ) ;
392+ }
381393
382394 writer . WriteEndObject ( ) ;
383395
384- return Task . CompletedTask ;
385- } ) ;
396+ writer . WriteEndObject ( ) ;
397+ }
398+ }
386399
387- configureContainer ? . Invoke ( surrealistContainerBuilder ) ;
400+ writer . WriteEndArray ( ) ;
388401
389- return builder ;
402+ writer . WriteEndObject ( ) ;
403+
404+ await writer . FlushAsync ( cancellationToken ) ;
405+
406+ return Encoding . UTF8 . GetString ( stream . ToArray ( ) ) ;
390407 }
391408}
0 commit comments