1+ using Azure ;
12using common ;
23using Microsoft . Extensions . DependencyInjection ;
34using Microsoft . Extensions . Hosting ;
5+ using OpenTelemetry . Resources ;
46using System ;
57using System . Collections . Concurrent ;
68using System . Collections . Generic ;
@@ -287,59 +289,24 @@ await resources.Values
287289 // Process policies for named value references
288290 if ( key . Resource is IPolicyResource policyResource )
289291 {
290- var policyContentOption = await getPolicyFileContents ( policyResource , key . Name , key . Parents , operations . ReadFile , cancellationToken ) ;
291-
292- policyContentOption . Iter ( policyContent =>
293- {
294- // Get workspace associated with the policy (if any)
295- var workspaceOption = key . Parents . Head ( tuple => tuple . Resource is WorkspaceResource ) ;
296-
297- // Extract all named values from the policy
298- getPolicyNamedValues ( policyContent )
299- . Choose ( namedValueName =>
300- // Look for the named value in the same workspace
301- workspaceOption . Bind ( workspace => from workspaceNamedValues in resources . Find ( WorkspaceNamedValueResource . Instance )
302- from workspaceNamedValue in
303- workspaceNamedValues . Head ( key => key . Parents . Any ( parent => parent == workspace )
304- && key . Name == namedValueName )
305- select workspaceNamedValue )
306- // If not found, look for a service-level named value
307- . IfNone ( ( ) => from namedValues in resources . Find ( NamedValueResource . Instance )
308- from namedValue in
309- namedValues . Head ( key => key . Name == namedValueName )
310- select namedValue ) )
311- . Iter ( namedValue => pairs . Add ( ( namedValue , key ) ) , cancellationToken ) ;
312- } ) ;
292+ var namedValues = await getPolicyNamedValues ( policyResource , key . Name , key . Parents , operations . ReadFile , resources , cancellationToken ) ;
293+ namedValues . Iter ( namedValue => pairs . Add ( ( namedValue , key ) ) , cancellationToken ) ;
313294 }
314295
315296 // Process backend pools for individual backend references
316297 if ( key . Resource is BackendResource backendResource )
317298 {
318- var parents = key . Parents ;
319- var serializerOptions = ( ( IResourceWithDto ) backendResource ) . SerializerOptions ;
299+ dtoJsonOption . Map ( json => getBackendPoolBackends ( backendResource , key . Name , key . Parents , json , cancellationToken ) )
300+ . IfNone ( ( ) => [ ] )
301+ . Iter ( backend => pairs . Add ( ( backend , key ) ) , cancellationToken ) ;
302+ }
320303
321- dtoJsonOption . Bind ( json => JsonNodeModule . To < BackendDto > ( json , serializerOptions )
322- . ToOption ( ) )
323- // Get pool backends
324- . Map ( dto => dto . Properties . Pool ? . Services ?? [ ] )
304+ // Process workspace backend pools for individual backend references
305+ if ( key . Resource is WorkspaceBackendResource workspaceBackendResource )
306+ {
307+ dtoJsonOption . Map ( json => getWorkspaceBackendPoolBackends ( workspaceBackendResource , key . Name , key . Parents , json , cancellationToken ) )
325308 . IfNone ( ( ) => [ ] )
326- // Get backend names from their IDs
327- . Choose ( backend =>
328- {
329- var nameString = backend . Id ? . Split ( '/' ) . LastOrDefault ( ) ?? string . Empty ;
330-
331- return ResourceName . From ( nameString )
332- . ToOption ( ) ;
333- } )
334- // Create resource keys for each backend
335- . Select ( backendName => new ResourceKey
336- {
337- Resource = backendResource ,
338- Name = backendName ,
339- Parents = parents
340- } )
341- // Pair backends with the pool
342- . Iter ( backendPredecessor => pairs . Add ( ( backendPredecessor , key ) ) , cancellationToken ) ;
309+ . Iter ( backend => pairs . Add ( ( backend , key ) ) , cancellationToken ) ;
343310 }
344311
345312 // Process non-root API revisions
@@ -355,6 +322,7 @@ from namedValue in
355322 Name = rootName ,
356323 Parents = key . Parents
357324 } ;
325+
358326 pairs . Add ( ( currentRevision , key ) ) ;
359327 } ) ;
360328 }
@@ -372,6 +340,7 @@ from namedValue in
372340 Name = rootName ,
373341 Parents = key . Parents
374342 } ;
343+
375344 pairs . Add ( ( currentRevision , key ) ) ;
376345 } ) ;
377346 }
@@ -511,22 +480,89 @@ static Result<ResourceName> getResourceName(string id, IResource resource, Paren
511480 } ;
512481 }
513482
514- static ImmutableHashSet < ResourceName > getPolicyNamedValues ( BinaryData policyContent )
483+ async ValueTask < ImmutableHashSet < ResourceKey > > getPolicyNamedValues ( IPolicyResource resource , ResourceName name , ParentChain parents , ReadFile readFile , IDictionary < IResource , ImmutableHashSet < ResourceKey > > resources , CancellationToken cancellationToken )
515484 {
516- var policyContentText = policyContent . ToString ( ) ;
485+ var workspaceOption = parents . Head ( tuple => tuple . Resource is WorkspaceResource ) ;
517486
518- if ( string . IsNullOrWhiteSpace ( policyContentText ) )
487+ var namedValueNames = await getPolicyNamedValueNames ( resource , name , parents , readFile , resources , cancellationToken ) ;
488+
489+ return [ .. namedValueNames . Choose ( name => findNamedValue ( name , workspaceOption , resources ) ) ] ;
490+ }
491+
492+ async ValueTask < ImmutableHashSet < ResourceName > > getPolicyNamedValueNames ( IPolicyResource resource , ResourceName name , ParentChain parents , ReadFile readFile , IDictionary < IResource , ImmutableHashSet < ResourceKey > > resources , CancellationToken cancellationToken )
493+ {
494+ var contentsOption = from binaryData in await getPolicyFileContents ( resource , name , parents , readFile , cancellationToken )
495+ select binaryData . ToString ( ) ;
496+
497+ var contents = contentsOption . IfNoneNull ( ) ?? string . Empty ;
498+
499+ if ( string . IsNullOrWhiteSpace ( contents ) )
519500 {
520501 return [ ] ;
521502 }
522503
523504 var regex = new Regex ( "{{\\ s*(.*?)\\ s*}}" , RegexOptions . CultureInvariant ) ;
524505
525- return [ .. regex . Matches ( policyContentText )
506+ return [ .. regex . Matches ( contents )
526507 . Choose ( match => ResourceName . From ( match . Groups [ 1 ] . Value . Trim ( ) )
527508 . ToOption ( ) ) ] ;
528509 }
529510
511+ Option < ResourceKey > findNamedValue ( ResourceName name , Option < ( IResource , ResourceName ) > workspaceOption , IDictionary < IResource , ImmutableHashSet < ResourceKey > > resources ) =>
512+ // Look for the named value in the workspace
513+ workspaceOption . Bind ( workspace => from namedValues in resources . Find ( WorkspaceNamedValueResource . Instance )
514+ from namedValue in namedValues . Head ( key => key . Name == name
515+ && key . Parents . Any ( parent => parent == workspace ) )
516+ select namedValue )
517+ // If not found, look for a service-level named value
518+ . IfNone ( ( ) => from namedValues in resources . Find ( NamedValueResource . Instance )
519+ from namedValue in namedValues . Head ( key => key . Name == name )
520+ select namedValue ) ;
521+
522+ static ImmutableHashSet < ResourceKey > getBackendPoolBackends ( BackendResource resource , ResourceName name , ParentChain parents , JsonObject dto , CancellationToken cancellationToken )
523+ {
524+ var serializerOptions = ( ( IResourceWithDto ) resource ) . SerializerOptions ;
525+
526+ return [ .. JsonNodeModule . To < BackendDto > ( dto , serializerOptions )
527+ . Map ( backendDto => backendDto . Properties . Pool ? . Services ?? [ ] )
528+ . IfError ( _ => [ ] )
529+ . Choose ( backend =>
530+ {
531+ var nameString = backend . Id ? . Split ( '/' ) . LastOrDefault ( ) ?? string . Empty ;
532+
533+ return ResourceName . From ( nameString )
534+ . ToOption ( ) ;
535+ } )
536+ . Select ( backendName => new ResourceKey
537+ {
538+ Resource = resource ,
539+ Name = backendName ,
540+ Parents = parents
541+ } ) ] ;
542+ }
543+
544+ static ImmutableHashSet < ResourceKey > getWorkspaceBackendPoolBackends ( WorkspaceBackendResource resource , ResourceName name , ParentChain parents , JsonObject dto , CancellationToken cancellationToken )
545+ {
546+ var serializerOptions = ( ( IResourceWithDto ) resource ) . SerializerOptions ;
547+
548+ return [ .. JsonNodeModule . To < WorkspaceBackendDto > ( dto , serializerOptions )
549+ . Map ( backendDto => backendDto . Properties . Pool ? . Services ?? [ ] )
550+ . IfError ( _ => [ ] )
551+ . Choose ( backend =>
552+ {
553+ var nameString = backend . Id ? . Split ( '/' ) . LastOrDefault ( ) ?? string . Empty ;
554+
555+ return ResourceName . From ( nameString )
556+ . ToOption ( ) ;
557+ } )
558+ . Select ( backendName => new ResourceKey
559+ {
560+ Resource = resource ,
561+ Name = backendName ,
562+ Parents = parents
563+ } ) ] ;
564+ }
565+
530566 static bool isPredecessorWithOptionalArtifacts ( ResourceKey key ) =>
531567 key . Resource switch
532568 {
0 commit comments