6
6
using System . ComponentModel ;
7
7
using System . Diagnostics . CodeAnalysis ;
8
8
using System . Diagnostics . ContractsLight ;
9
+ using System . Linq ;
9
10
using System . Threading . Tasks ;
10
11
using BuildXL . Cache . ContentStore . Distributed . Blob ;
12
+ using BuildXL . Cache . ContentStore . Interfaces . Auth ;
11
13
using BuildXL . Cache . Interfaces ;
12
14
using BuildXL . Cache . MemoizationStore . Distributed . Stores ;
13
- using BuildXL . Utilities . Core ;
15
+ using BuildXL . Utilities . Collections ;
14
16
using BuildXL . Utilities . Configuration ;
17
+ using BuildXL . Utilities . Core ;
15
18
using AbsolutePath = BuildXL . Cache . ContentStore . Interfaces . FileSystem . AbsolutePath ;
16
- using System . Security . Principal ;
17
- using BuildXL . Cache . ContentStore . Interfaces . Auth ;
18
19
19
20
namespace BuildXL . Cache . MemoizationStoreAdapter
20
21
{
@@ -28,7 +29,7 @@ namespace BuildXL.Cache.MemoizationStoreAdapter
28
29
/// Current limitations while we flesh things out:
29
30
/// 1) APIs around tracking named sessions are not implemented
30
31
/// </remarks>
31
- public partial class BlobCacheFactory : ICacheFactory
32
+ public class BlobCacheFactory : ICacheFactory
32
33
{
33
34
/// <summary>
34
35
/// Inheritable configuration settings for cache factories that wish to configure a connection to a blob cache
@@ -76,6 +77,15 @@ public abstract class BlobCacheConfig
76
77
/// </remarks>
77
78
[ DefaultValue ( 0 ) ]
78
79
public int RetentionPolicyInDays { get ; set ; }
80
+
81
+ /// <nodoc />
82
+ [ DefaultValue ( "default" ) ]
83
+ public string Universe { get ; set ; }
84
+
85
+ /// <nodoc />
86
+ [ DefaultValue ( "default" ) ]
87
+ public string Namespace { get ; set ; }
88
+
79
89
}
80
90
81
91
/// <summary>
@@ -89,14 +99,6 @@ public sealed class Config : BlobCacheConfig
89
99
[ DefaultValue ( typeof ( CacheId ) ) ]
90
100
public CacheId CacheId { get ; set ; }
91
101
92
- /// <nodoc />
93
- [ DefaultValue ( "default" ) ]
94
- public string Universe { get ; set ; }
95
-
96
- /// <nodoc />
97
- [ DefaultValue ( "default" ) ]
98
- public string Namespace { get ; set ; }
99
-
100
102
/// <summary>
101
103
/// Path to the log file for the cache.
102
104
/// </summary>
@@ -157,7 +159,7 @@ public async Task<Possible<ICache, Failure>> InitializeCacheAsync(Config configu
157
159
logger : new DisposeLogger ( ( ) => new EtwFileLog ( logPath . Path , configuration . CacheId ) , configuration . LogFlushIntervalSeconds ) ,
158
160
statsFile : new AbsolutePath ( logPath . Path + ".stats" ) ,
159
161
precedingStateDegradationFailures : failures ) ;
160
-
162
+
161
163
var startupResult = await cache . StartupAsync ( ) ;
162
164
if ( ! startupResult . Succeeded )
163
165
{
@@ -172,14 +174,12 @@ public async Task<Possible<ICache, Failure>> InitializeCacheAsync(Config configu
172
174
}
173
175
}
174
176
175
- private static MemoizationStore . Interfaces . Caches . ICache CreateCache ( Config configuration )
177
+ internal static MemoizationStore . Interfaces . Caches . IFullCache CreateCache ( BlobCacheConfig configuration )
176
178
{
177
- IAzureStorageCredentials credentials = GetAzureCredentialsFromBlobFactoryConfig ( configuration ) ;
178
-
179
- var accountName = BlobCacheStorageAccountName . Parse ( credentials . GetAccountName ( ) ) ;
179
+ var credentials = LoadAzureCredentials ( configuration ) ;
180
180
181
181
var factoryConfiguration = new AzureBlobStorageCacheFactory . Configuration (
182
- ShardingScheme : new ShardingScheme ( ShardingAlgorithm . SingleShard , new List < BlobCacheStorageAccountName > { accountName } ) ,
182
+ ShardingScheme : new ShardingScheme ( ShardingAlgorithm . JumpHash , credentials . Keys . ToList ( ) ) ,
183
183
Universe : configuration . Universe ,
184
184
Namespace : configuration . Namespace ,
185
185
RetentionPolicyInDays : configuration . RetentionPolicyInDays ) ;
@@ -188,14 +188,22 @@ private static MemoizationStore.Interfaces.Caches.ICache CreateCache(Config conf
188
188
}
189
189
190
190
/// <nodoc />
191
- internal static IAzureStorageCredentials GetAzureCredentialsFromBlobFactoryConfig ( BlobCacheConfig configuration )
191
+ internal static Dictionary < BlobCacheStorageAccountName , IAzureStorageCredentials > LoadAzureCredentials ( BlobCacheConfig configuration )
192
192
{
193
- IAzureStorageCredentials credentials ;
193
+ var credentials = new Dictionary < BlobCacheStorageAccountName , IAzureStorageCredentials > ( ) ;
194
194
var connectionString = Environment . GetEnvironmentVariable ( configuration . ConnectionStringEnvironmentVariableName ) ;
195
195
196
196
if ( ! string . IsNullOrEmpty ( connectionString ) )
197
197
{
198
- credentials = new SecretBasedAzureStorageCredentials ( connectionString ) ;
198
+ credentials . AddRange (
199
+ connectionString . Split ( ' ' )
200
+ . Select (
201
+ secret =>
202
+ {
203
+ var credential = new SecretBasedAzureStorageCredentials ( secret . Trim ( ) ) ;
204
+ var accountName = BlobCacheStorageAccountName . Parse ( credential . GetAccountName ( ) ) ;
205
+ return new KeyValuePair < BlobCacheStorageAccountName , IAzureStorageCredentials > ( accountName , credential ) ;
206
+ } ) ) ;
199
207
}
200
208
else if ( configuration . ManagedIdentityId is not null && configuration . StorageAccountEndpoint is not null )
201
209
{
@@ -207,7 +215,8 @@ internal static IAzureStorageCredentials GetAzureCredentialsFromBlobFactoryConfi
207
215
throw new InvalidOperationException ( $ "'{ configuration . StorageAccountEndpoint } ' does not represent a valid URI.") ;
208
216
}
209
217
210
- credentials = new ManagedIdentityAzureStorageCredentials ( configuration . ManagedIdentityId , uri ) ;
218
+ var credential = new ManagedIdentityAzureStorageCredentials ( configuration . ManagedIdentityId , uri ) ;
219
+ credentials . Add ( BlobCacheStorageAccountName . Parse ( credential . GetAccountName ( ) ) , credential ) ;
211
220
}
212
221
else
213
222
{
0 commit comments