@@ -193,6 +193,97 @@ public async Task Success_SimpleTest_TokenAuth()
193193 }
194194 }
195195
196+ [ Fact ]
197+ public async Task Success_SimpleTestWithKeyPrefix_TokenAuth ( )
198+ {
199+ // arrange
200+ var values =
201+ new Dictionary < string , IEnumerable < KeyValuePair < string , object > > >
202+ {
203+ {
204+ "test" , new [ ]
205+ {
206+ new KeyValuePair < string , object > ( "option1" , "value1" ) ,
207+ new KeyValuePair < string , object > ( "option3" , 5 ) ,
208+ new KeyValuePair < string , object > ( "option4" , true ) ,
209+ new KeyValuePair < string , object > ( "option5" , new [ ] { "v1" , "v2" , "v3" } ) ,
210+ new KeyValuePair < string , object > (
211+ "option6" ,
212+ new [ ]
213+ {
214+ new TestConfigObject ( ) { OptionA = "a1" , OptionB = "b1" } ,
215+ new TestConfigObject ( ) { OptionA = "a2" , OptionB = "b2" } ,
216+ } ) ,
217+ }
218+ } ,
219+ {
220+ "test/subsection" , new [ ]
221+ {
222+ new KeyValuePair < string , object > ( "option2" , "value2" ) ,
223+ }
224+ } ,
225+ {
226+ "test/otherSubsection.otherSubsection2/otherSubsection3.otherSubsection4.otherSubsection5" , new [ ]
227+ {
228+ new KeyValuePair < string , object > ( "option7" , "value7" ) ,
229+ }
230+ } ,
231+ {
232+ "test/subsection/testsection" , new [ ]
233+ {
234+ new KeyValuePair < string , object > ( "option8" , "value8" ) ,
235+ }
236+ } ,
237+ } ;
238+
239+ var container = this . PrepareVaultContainer ( ) ;
240+ try
241+ {
242+ await container . StartAsync ( ) . ConfigureAwait ( false ) ;
243+ await this . LoadDataAsync ( "http://localhost:8200" , values ) . ConfigureAwait ( false ) ;
244+
245+ // act
246+ var builder = new ConfigurationBuilder ( ) ;
247+
248+ var keyPrefix = "MyConfig" ;
249+ builder . AddVaultConfiguration (
250+ ( ) => new VaultOptions ( "http://localhost:8200" , "root" , additionalCharactersForConfigurationPath : new [ ] { '.' } , keyPrefix : keyPrefix ) ,
251+ "test" ,
252+ "secret" ,
253+ this . logger ) ;
254+ var configurationRoot = builder . Build ( ) ;
255+
256+ // assert
257+ configurationRoot . GetValue < string > ( $ "{ keyPrefix } :option1") . Should ( ) . Be ( "value1" ) ;
258+ configurationRoot . GetValue < int > ( $ "{ keyPrefix } :option3") . Should ( ) . Be ( 5 ) ;
259+ configurationRoot . GetValue < bool > ( $ "{ keyPrefix } :option4") . Should ( ) . Be ( true ) ;
260+ configurationRoot . GetValue < string > ( $ "{ keyPrefix } :option5:0") . Should ( ) . Be ( "v1" ) ;
261+ configurationRoot . GetValue < string > ( $ "{ keyPrefix } :option5:1") . Should ( ) . Be ( "v2" ) ;
262+ configurationRoot . GetValue < string > ( $ "{ keyPrefix } :option5:2") . Should ( ) . Be ( "v3" ) ;
263+ var t1 = new TestConfigObject ( ) ;
264+ configurationRoot . Bind ( $ "{ keyPrefix } :option6:0", t1 ) ;
265+ t1 . OptionA . Should ( ) . Be ( "a1" ) ;
266+ t1 . OptionB . Should ( ) . Be ( "b1" ) ;
267+ var t2 = new TestConfigObject ( ) ;
268+ configurationRoot . Bind ( $ "{ keyPrefix } :option6:1", t2 ) ;
269+ t2 . OptionA . Should ( ) . Be ( "a2" ) ;
270+ t2 . OptionB . Should ( ) . Be ( "b2" ) ;
271+ configurationRoot . GetSection ( $ "{ keyPrefix } :subsection") . GetValue < string > ( "option2" ) . Should ( ) . Be ( "value2" ) ;
272+ configurationRoot . GetSection ( $ "{ keyPrefix } :otherSubsection")
273+ . GetSection ( $ "otherSubsection2")
274+ . GetSection ( "otherSubsection3" )
275+ . GetSection ( "otherSubsection4" )
276+ . GetSection ( "otherSubsection5" )
277+ . GetValue < string > ( "option7" ) . Should ( ) . Be ( "value7" ) ;
278+ configurationRoot . GetSection ( $ "{ keyPrefix } :subsection") . GetSection ( "testsection" ) . GetValue < string > ( "option8" ) . Should ( ) . Be ( "value8" ) ;
279+ }
280+ finally
281+ {
282+ await container . DisposeAsync ( ) . ConfigureAwait ( false ) ;
283+ }
284+ }
285+
286+
196287 [ Fact ]
197288 public async Task Success_SimpleTestOmitVaultKey_TokenAuth ( )
198289 {
@@ -296,6 +387,70 @@ public async Task Success_WatcherTest_TokenAuth()
296387 }
297388 }
298389
390+ [ Fact ]
391+ public async Task Success_WatcherTestWithPrefix_TokenAuth ( )
392+ {
393+ // arrange
394+ using var cts = new CancellationTokenSource ( ) ;
395+
396+ var values =
397+ new Dictionary < string , IEnumerable < KeyValuePair < string , object > > >
398+ {
399+ { "test" , new [ ] { new KeyValuePair < string , object > ( "option1" , "value1" ) } } ,
400+ { "test/subsection" , new [ ] { new KeyValuePair < string , object > ( "option2" , "value2" ) } } ,
401+ } ;
402+
403+ var container = this . PrepareVaultContainer ( ) ;
404+ try
405+ {
406+ await container . StartAsync ( ) . ConfigureAwait ( false ) ;
407+ await this . LoadDataAsync ( "http://localhost:8200" , values ) . ConfigureAwait ( false ) ;
408+
409+ var testPrefix = "MyConfig" ;
410+
411+ // act
412+ var builder = new ConfigurationBuilder ( ) ;
413+ builder . AddVaultConfiguration (
414+ ( ) => new VaultOptions ( "http://localhost:8200" , "root" , reloadOnChange : true , reloadCheckIntervalSeconds : 10 , keyPrefix : testPrefix ) ,
415+ "test" ,
416+ "secret" ,
417+ this . logger ) ;
418+ var configurationRoot = builder . Build ( ) ;
419+ var changeWatcher = new VaultChangeWatcher ( configurationRoot , this . logger ) ;
420+ await changeWatcher . StartAsync ( cts . Token ) . ConfigureAwait ( false ) ;
421+ var reloadToken = configurationRoot . GetReloadToken ( ) ;
422+
423+ // assert
424+ configurationRoot . GetValue < string > ( $ "{ testPrefix } :option1") . Should ( ) . Be ( "value1" ) ;
425+ configurationRoot . GetSection ( $ "{ testPrefix } :subsection") . GetValue < string > ( "option2" ) . Should ( ) . Be ( "value2" ) ;
426+ reloadToken . HasChanged . Should ( ) . BeFalse ( ) ;
427+
428+ // load new data and wait for reload
429+ values = new Dictionary < string , IEnumerable < KeyValuePair < string , object > > >
430+ {
431+ { "test" , new [ ] { new KeyValuePair < string , object > ( "option1" , "value1_new" ) } } ,
432+ { "test/subsection" , new [ ] { new KeyValuePair < string , object > ( "option2" , "value2_new" ) } } ,
433+ { "test/subsection3" , new [ ] { new KeyValuePair < string , object > ( "option3" , "value3_new" ) } } ,
434+ { "test/testsection" , new [ ] { new KeyValuePair < string , object > ( "option4" , "value4_new" ) } } ,
435+ } ;
436+ await this . LoadDataAsync ( "http://localhost:8200" , values ) . ConfigureAwait ( false ) ;
437+ await Task . Delay ( TimeSpan . FromSeconds ( 15 ) , cts . Token ) . ConfigureAwait ( true ) ;
438+
439+ reloadToken . HasChanged . Should ( ) . BeTrue ( ) ;
440+ configurationRoot . GetValue < string > ( $ "{ testPrefix } :option1") . Should ( ) . Be ( "value1_new" ) ;
441+ configurationRoot . GetSection ( $ "{ testPrefix } :subsection") . GetValue < string > ( "option2" ) . Should ( ) . Be ( "value2_new" ) ;
442+ configurationRoot . GetSection ( $ "{ testPrefix } :subsection3") . GetValue < string > ( "option3" ) . Should ( ) . Be ( "value3_new" ) ;
443+ configurationRoot . GetSection ( $ "{ testPrefix } :testsection") . GetValue < string > ( "option4" ) . Should ( ) . Be ( "value4_new" ) ;
444+
445+ changeWatcher . Dispose ( ) ;
446+ }
447+ finally
448+ {
449+ await cts . CancelAsync ( ) ;
450+ await container . DisposeAsync ( ) . ConfigureAwait ( false ) ;
451+ }
452+ }
453+
299454 [ Fact ]
300455 public async Task Success_WatcherTest_NoChanges ( )
301456 {
0 commit comments