44using System ;
55using System . Collections . Generic ;
66using System . ComponentModel . Design ;
7- using System . Diagnostics . Tracing ;
7+ using System . Data . SqlClient ;
88using System . Linq ;
99using System . Threading . Tasks ;
10+ using Autofac ;
1011using Dapper ;
12+ using Microsoft . Extensions . Configuration ;
13+ using Microsoft . Extensions . DependencyInjection ;
14+ using Microsoft . Extensions . Options ;
1115using Microsoft . WindowsAzure . Storage ;
1216using Microsoft . WindowsAzure . Storage . Blob ;
1317using Newtonsoft . Json . Linq ;
1418using NuGet . Jobs ;
15- using NuGet . Services . KeyVault ;
16- using NuGet . Services . Sql ;
19+ using NuGet . Jobs . Configuration ;
1720
1821namespace ArchivePackages
1922{
20- public class Job : JobBase
23+ public class Job : JsonConfigurationJob
2124 {
2225 private readonly JobEventSource JobEventSourceLog = JobEventSource . Log ;
2326 private const string ContentTypeJson = "application/json" ;
@@ -27,6 +30,8 @@ public class Job : JobBase
2730 private const string DefaultPackagesArchiveContainerName = "ng-backups" ;
2831 private const string DefaultCursorBlobName = "cursor.json" ;
2932
33+ private InitializationConfiguration Configuration { get ; set ; }
34+
3035 /// <summary>
3136 /// Gets or sets an Azure Storage Uri referring to a container to use as the source for package blobs
3237 /// </summary>
@@ -44,6 +49,7 @@ public class Job : JobBase
4449 /// DestinationContainerName should be same as the primary destination
4550 /// </summary>
4651 public CloudStorageAccount SecondaryDestination { get ; set ; }
52+
4753 /// <summary>
4854 /// Destination Container name for both Primary and Secondary destinations. Also, for the cursor blob
4955 /// </summary>
@@ -53,8 +59,11 @@ public class Job : JobBase
5359 /// Blob containing the cursor data. Cursor data comprises of cursorDateTime
5460 /// </summary>
5561 public string CursorBlobName { get ; set ; }
56-
57- private ISqlConnectionFactory _packageDbConnectionFactory ;
62+
63+ /// <summary>
64+ /// Gallery database registration, for diagnostics.
65+ /// </summary>
66+ private SqlConnectionStringBuilder GalleryDatabase { get ; set ; }
5867
5968 protected CloudBlobContainer SourceContainer { get ; private set ; }
6069
@@ -66,33 +75,34 @@ public Job() : base(JobEventSource.Log) { }
6675
6776 public override void Init ( IServiceContainer serviceContainer , IDictionary < string , string > jobArgsDictionary )
6877 {
69- var secretInjector = ( ISecretInjector ) serviceContainer . GetService ( typeof ( ISecretInjector ) ) ;
70- var packageDbConnectionString = JobConfigurationManager . GetArgument ( jobArgsDictionary , JobArgumentNames . PackageDatabase ) ;
71- _packageDbConnectionFactory = new AzureSqlConnectionFactory ( packageDbConnectionString , secretInjector ) ;
78+ base . Init ( serviceContainer , jobArgsDictionary ) ;
7279
73- Source = CloudStorageAccount . Parse (
74- JobConfigurationManager . GetArgument ( jobArgsDictionary , JobArgumentNames . Source ) ) ;
80+ Configuration = _serviceProvider . GetRequiredService < IOptionsSnapshot < InitializationConfiguration > > ( ) . Value ;
7581
76- PrimaryDestination = CloudStorageAccount . Parse (
77- JobConfigurationManager . GetArgument ( jobArgsDictionary , JobArgumentNames . PrimaryDestination ) ) ;
82+ GalleryDatabase = GetDatabaseRegistration < GalleryDbConfiguration > ( ) ;
7883
79- var secondaryDestinationCstr = JobConfigurationManager . TryGetArgument ( jobArgsDictionary , JobArgumentNames . SecondaryDestination ) ;
80- SecondaryDestination = string . IsNullOrEmpty ( secondaryDestinationCstr ) ? null : CloudStorageAccount . Parse ( secondaryDestinationCstr ) ;
84+ Source = CloudStorageAccount . Parse ( Configuration . Source ) ;
8185
82- SourceContainerName = JobConfigurationManager . TryGetArgument ( jobArgsDictionary , JobArgumentNames . SourceContainerName ) ?? DefaultPackagesContainerName ;
86+ PrimaryDestination = CloudStorageAccount . Parse ( Configuration . PrimaryDestination ) ;
8387
84- DestinationContainerName = JobConfigurationManager . TryGetArgument ( jobArgsDictionary , JobArgumentNames . DestinationContainerName ) ?? DefaultPackagesArchiveContainerName ;
88+ if ( ! string . IsNullOrEmpty ( Configuration . SecondaryDestination ) )
89+ {
90+ SecondaryDestination = CloudStorageAccount . Parse ( Configuration . SecondaryDestination ) ;
91+ }
92+
93+ SourceContainerName = Configuration . SourceContainerName ?? DefaultPackagesContainerName ;
94+ DestinationContainerName = Configuration . DestinationContainerName ?? DefaultPackagesArchiveContainerName ;
8595
8696 SourceContainer = Source . CreateCloudBlobClient ( ) . GetContainerReference ( SourceContainerName ) ;
8797 PrimaryDestinationContainer = PrimaryDestination . CreateCloudBlobClient ( ) . GetContainerReference ( DestinationContainerName ) ;
8898 SecondaryDestinationContainer = SecondaryDestination ? . CreateCloudBlobClient ( ) . GetContainerReference ( DestinationContainerName ) ;
8999
90- CursorBlobName = JobConfigurationManager . TryGetArgument ( jobArgsDictionary , JobArgumentNames . CursorBlob ) ?? DefaultCursorBlobName ;
100+ CursorBlobName = Configuration . CursorBlob ?? DefaultCursorBlobName ;
91101 }
92102
93103 public override async Task Run ( )
94104 {
95- JobEventSourceLog . PreparingToArchive ( Source . Credentials . AccountName , SourceContainer . Name , PrimaryDestination . Credentials . AccountName , PrimaryDestinationContainer . Name , _packageDbConnectionFactory . DataSource , _packageDbConnectionFactory . InitialCatalog ) ;
105+ JobEventSourceLog . PreparingToArchive ( Source . Credentials . AccountName , SourceContainer . Name , PrimaryDestination . Credentials . AccountName , PrimaryDestinationContainer . Name , GalleryDatabase . DataSource , GalleryDatabase . InitialCatalog ) ;
96106 await Archive ( PrimaryDestinationContainer ) ;
97107
98108 // todo: consider reusing package query for primary and secondary archives
@@ -124,9 +134,9 @@ private async Task Archive(CloudBlobContainer destinationContainer)
124134
125135 JobEventSourceLog . CursorData ( cursorDateTime . ToString ( DateTimeFormatSpecifier ) ) ;
126136
127- JobEventSourceLog . GatheringPackagesToArchiveFromDb ( _packageDbConnectionFactory . DataSource , _packageDbConnectionFactory . InitialCatalog ) ;
137+ JobEventSourceLog . GatheringPackagesToArchiveFromDb ( GalleryDatabase . DataSource , GalleryDatabase . InitialCatalog ) ;
128138 List < PackageRef > packages ;
129- using ( var connection = await _packageDbConnectionFactory . CreateAsync ( ) )
139+ using ( var connection = await OpenSqlConnectionAsync < GalleryDbConfiguration > ( ) )
130140 {
131141 packages = ( await connection . QueryAsync < PackageRef > ( @"
132142 SELECT pr.Id, p.NormalizedVersion AS Version, p.Hash, p.LastEdited, p.Published
@@ -135,7 +145,7 @@ FROM Packages p
135145 WHERE Published > @cursorDateTime OR LastEdited > @cursorDateTime" , new { cursorDateTime = cursorDateTime } ) )
136146 . ToList ( ) ;
137147 }
138- JobEventSourceLog . GatheredPackagesToArchiveFromDb ( packages . Count , _packageDbConnectionFactory . DataSource , _packageDbConnectionFactory . InitialCatalog ) ;
148+ JobEventSourceLog . GatheredPackagesToArchiveFromDb ( packages . Count , GalleryDatabase . DataSource , GalleryDatabase . InitialCatalog ) ;
139149
140150 var archiveSet = packages
141151 . AsParallel ( )
@@ -193,129 +203,14 @@ private async Task ArchivePackage(string sourceBlobName, string destinationBlobN
193203 JobEventSourceLog . StartedCopy ( sourceBlob . Name , destBlob . Name ) ;
194204 }
195205 }
196- }
197206
198- [ EventSource ( Name = "Outercurve-NuGet-Jobs-ArchivePackages" ) ]
199- public class JobEventSource : EventSource
200- {
201- public static readonly JobEventSource Log = new JobEventSource ( ) ;
202-
203- private JobEventSource ( ) { }
204-
205- [ Event (
206- eventId : 1 ,
207- Level = EventLevel . Informational ,
208- Message = "Preparing to archive packages from {0}/{1} to primary destination {2}/{3} using package data from {4}/{5}" ) ]
209- public void PreparingToArchive ( string sourceAccount , string sourceContainer , string destAccount , string destContainer , string dbServer , string dbName ) { WriteEvent ( 1 , sourceAccount , sourceContainer , destAccount , destContainer , dbServer , dbName ) ; }
210-
211- [ Event (
212- eventId : 2 ,
213- Level = EventLevel . Informational ,
214- Message = "Preparing to archive packages to secondary destination {0}/{1}" ) ]
215- public void PreparingToArchive2 ( string destAccount , string destContainer ) { WriteEvent ( 2 , destAccount , destContainer ) ; }
216-
217- [ Event (
218- eventId : 3 ,
219- Level = EventLevel . Informational ,
220- Message = "Cursor data: CursorDateTime is {0}" ) ]
221- public void CursorData ( string cursorDateTime ) { WriteEvent ( 3 , cursorDateTime ) ; }
222-
223- [ Event (
224- eventId : 4 ,
225- Level = EventLevel . Informational ,
226- Task = Tasks . GatheringDbPackages ,
227- Opcode = EventOpcode . Start ,
228- Message = "Gathering list of packages to archive from {0}/{1}" ) ]
229- public void GatheringPackagesToArchiveFromDb ( string dbServer , string dbName ) { WriteEvent ( 4 , dbServer , dbName ) ; }
230-
231- [ Event (
232- eventId : 5 ,
233- Level = EventLevel . Informational ,
234- Task = Tasks . GatheringDbPackages ,
235- Opcode = EventOpcode . Stop ,
236- Message = "Gathered {0} packages to archive from {1}/{2}" ) ]
237- public void GatheredPackagesToArchiveFromDb ( int gathered , string dbServer , string dbName ) { WriteEvent ( 5 , gathered , dbServer , dbName ) ; }
238-
239- [ Event (
240- eventId : 6 ,
241- Level = EventLevel . Informational ,
242- Task = Tasks . ArchivingPackages ,
243- Opcode = EventOpcode . Start ,
244- Message = "Starting archive of {0} packages." ) ]
245- public void StartingArchive ( int count ) { WriteEvent ( 6 , count ) ; }
246-
247- [ Event (
248- eventId : 7 ,
249- Level = EventLevel . Informational ,
250- Task = Tasks . ArchivingPackages ,
251- Opcode = EventOpcode . Stop ,
252- Message = "Started archive." ) ]
253- public void StartedArchive ( ) { WriteEvent ( 7 ) ; }
254-
255- [ Event (
256- eventId : 8 ,
257- Level = EventLevel . Informational ,
258- Message = "Archive already exists: {0}" ) ]
259- public void ArchiveExists ( string blobName ) { WriteEvent ( 8 , blobName ) ; }
260-
261- [ Event (
262- eventId : 9 ,
263- Level = EventLevel . Warning ,
264- Message = "Source Blob does not exist: {0}" ) ]
265- public void SourceBlobMissing ( string blobName ) { WriteEvent ( 9 , blobName ) ; }
266-
267- [ Event (
268- eventId : 12 ,
269- Level = EventLevel . Informational ,
270- Task = Tasks . StartingPackageCopy ,
271- Opcode = EventOpcode . Start ,
272- Message = "Starting copy of {0} to {1}." ) ]
273- public void StartingCopy ( string source , string dest ) { WriteEvent ( 12 , source , dest ) ; }
274-
275- [ Event (
276- eventId : 13 ,
277- Level = EventLevel . Informational ,
278- Task = Tasks . StartingPackageCopy ,
279- Opcode = EventOpcode . Stop ,
280- Message = "Started copy of {0} to {1}." ) ]
281- public void StartedCopy ( string source , string dest ) { WriteEvent ( 13 , source , dest ) ; }
282-
283- [ Event (
284- eventId : 14 ,
285- Level = EventLevel . Informational ,
286- Message = "NewCursor data: CursorDateTime is {0}" ) ]
287- public void NewCursorData ( string cursorDateTime ) { WriteEvent ( 14 , cursorDateTime ) ; }
288- }
289-
290- public static class Tasks
291- {
292- public const EventTask GatheringDbPackages = ( EventTask ) 0x1 ;
293- public const EventTask ArchivingPackages = ( EventTask ) 0x2 ;
294- public const EventTask StartingPackageCopy = ( EventTask ) 0x3 ;
295- }
296-
297- public class PackageRef
298- {
299- public PackageRef ( string id , string version , string hash )
300- {
301- Id = id ;
302- Version = version ;
303- Hash = hash ;
304- }
305- public PackageRef ( string id , string version , string hash , DateTime lastEdited )
306- : this ( id , version , hash )
207+ protected override void ConfigureAutofacServices ( ContainerBuilder containerBuilder )
307208 {
308- LastEdited = lastEdited ;
309209 }
310- public PackageRef ( string id , string version , string hash , DateTime lastEdited , DateTime published )
311- : this ( id , version , hash , lastEdited )
210+
211+ protected override void ConfigureJobServices ( IServiceCollection services , IConfigurationRoot configurationRoot )
312212 {
313- Published = published ;
213+ ConfigureInitializationSection < InitializationConfiguration > ( services , configurationRoot ) ;
314214 }
315- public string Id { get ; set ; }
316- public string Version { get ; set ; }
317- public string Hash { get ; set ; }
318- public DateTime ? LastEdited { get ; set ; }
319- public DateTime ? Published { get ; set ; }
320215 }
321216}
0 commit comments