@@ -193,13 +193,13 @@ func (r Runner) ArchiveSnapshot(out io.Writer, args []string) error {
193193 for {
194194 for _ , item := range objs .Contents {
195195 fmt .Fprintf (out , "%s\n " , * item .Key )
196- if * item .StorageClass != "GLACIER" {
196+ if * item .StorageClass != constants . GlacierType {
197197 if r .Flag .Force {
198198 color .Green ("Change Storage Class to %s -> GLACIER" , * item .StorageClass )
199199 wait .Add (1 )
200200 go func (key string ) {
201201 defer wait .Done ()
202- _ , err := r .Client .TransitObject (aws .String (repository .Settings .Bucket ), aws .String (key ), "GLACIER" )
202+ _ , err := r .Client .TransitObject (aws .String (repository .Settings .Bucket ), aws .String (key ), constants . GlacierType )
203203 if err != nil {
204204 panic (err )
205205 }
@@ -212,7 +212,7 @@ func (r Runner) ArchiveSnapshot(out io.Writer, args []string) error {
212212
213213 color .Green ("Change Storage Class to %s -> GLACIER" , * item .StorageClass )
214214 wait .Add (1 )
215- _ , err := r .Client .TransitObject (aws .String (repository .Settings .Bucket ), item .Key , "GLACIER" )
215+ _ , err := r .Client .TransitObject (aws .String (repository .Settings .Bucket ), item .Key , constants . GlacierType )
216216 if err != nil {
217217 panic (err )
218218 }
@@ -266,25 +266,24 @@ func (r Runner) getIndexIDFromS3(bucket *string, prefix *string) (*snapshotSchem
266266 return & snapshotsIndicesS3 , nil
267267}
268268
269- func (r Runner ) RestoreSnapshot (out io.Writer , args []string ) error {
270- maxSemaphore := r .Flag .MaxConcurrentJob
271- if maxSemaphore == 0 {
272- maxSemaphore = constants .DefaultMaxConcurrentJob
273- }
274-
269+ // RestoreSnapshot is main function of restoring snapshot process
270+ func (r * Runner ) RestoreSnapshot (out io.Writer , args []string ) error {
275271 repositoryID := args [0 ]
276272 snapshotID := args [1 ]
277273 indexName := args [2 ]
278274 areAllObjectsStandard := true
279275
280276 repository := r .Client .GetRepository (repositoryID )
281277
278+ if err := checkRepositoryType (repository .Type ); err != nil {
279+ return err
280+ }
281+
282282 if repository .Type == "s3" {
283283 fmt .Fprintf (out , "bucket name : %s\n " , util .StringWithColor (repository .Settings .Bucket ))
284284 fmt .Fprintf (out , "base path : %s\n " , util .StringWithColor (repository .Settings .BasePath ))
285285
286286 var basePath string
287- var result []SegmentError
288287
289288 if repository .Settings .BasePath == constants .EmptyString {
290289 basePath = constants .EmptyString
@@ -304,78 +303,33 @@ func (r Runner) RestoreSnapshot(out io.Writer, args []string) error {
304303 metaData := snapshotsIndicesS3 .Indices [indexName ]
305304 prefix := repository .Settings .BasePath + "/indices/" + metaData .ID + "/"
306305
306+ // add all objects in segments
307307 segments := r .AddObjectSegments (repository .Settings .Bucket , prefix , nil )
308- bar := pb .New (len (segments ))
309- bar .SetRefreshRate (time .Second )
310- bar .SetWriter (out )
311-
312- var wg sync.WaitGroup
313- semaphore := make (chan int , maxSemaphore )
314- output := make (chan []SegmentError )
315- input := make (chan SegmentError )
316- defer close (output )
317-
318- go func (input chan SegmentError , output chan []SegmentError , wg * sync.WaitGroup , bar * pb.ProgressBar ) {
319- var ret []SegmentError
320- for se := range input {
321- ret = append (ret , se )
322- bar .Add (1 )
323- wg .Done ()
324- }
325- output <- ret
326- }(input , output , & wg , bar )
327-
328- f := func (out io.Writer , bucket string , segment SnapshotSegment , force bool , ch chan SegmentError , sem chan int ) {
329- sem <- 1
330- time .Sleep (1 * time .Second )
331- if force {
332- //color.Green("Restore Storage Class to %s -> STANDARD", segment.StorageClass)
333- err := r .restoreObject (out , aws .String (bucket ), aws .String (segment .Key ))
334- ch <- SegmentError {
335- Key : segment .Key ,
336- Error : err ,
337- }
338- } else {
339- reader := bufio .NewReader (os .Stdin )
340-
341- color .Blue ("Change Storage Class to STANDARD [y/n]: " )
342-
343- resp , _ := reader .ReadString ('\n' )
344- if strings .ToLower (strings .TrimSpace (resp )) == "y" {
345- color .Green ("Change Storage Class to %s -> STANDARD" , segment .StorageClass )
346- err := r .restoreObject (out , aws .String (bucket ), aws .String (segment .Key ))
347- ch <- SegmentError {
348- Key : segment .Key ,
349- Error : err ,
350- }
351- } else {
352- color .Red ("Don't change storage class %s" , segment .Key )
353- }
354- }
355- <- sem
356- }
357308
358- bar .Start ()
359- for _ , s := range segments {
360- if s .StorageClass == "GLACIER" {
361- areAllObjectsStandard = false
362- wg .Add (1 )
363- go f (out , repository .Settings .Bucket , s , r .Flag .Force , input , semaphore )
364- } else {
365- bar .Add (1 )
309+ if r .Flag .Force {
310+ // if --force is enabled by user, then run it concurrently
311+ areAllObjectsStandard , err = r .RunConcurrentRestore (out , repository .Settings .Bucket , segments , r .Flag .MaxConcurrentJob )
312+ if err != nil {
313+ return err
366314 }
367- }
368- wg . Wait ()
369- close ( input )
370-
371- bar . Finish ( )
315+ } else {
316+ for _ , s := range segments {
317+ if s . StorageClass == "GLACIER" {
318+ areAllObjectsStandard = false
319+ reader := bufio . NewReader ( os . Stdin )
372320
373- result = <- output
321+ color . Blue ( "Change Storage Class to STANDARD [y/n]: " )
374322
375- if len (result ) > 0 {
376- for _ , s := range result {
377- if s .Error != nil {
378- s .PrintError ()
323+ resp , _ := reader .ReadString ('\n' )
324+ if strings .ToLower (strings .TrimSpace (resp )) == "y" {
325+ color .Green ("Change Storage Class to %s -> STANDARD" , s .StorageClass )
326+ err := r .restoreObject (out , aws .String (repository .Settings .Bucket ), aws .String (s .Key ))
327+ if err != nil {
328+ return err
329+ }
330+ } else {
331+ color .Red ("Don't change storage class %s" , s .Key )
332+ }
379333 }
380334 }
381335 }
@@ -395,7 +349,8 @@ func (r Runner) RestoreSnapshot(out io.Writer, args []string) error {
395349 return nil
396350}
397351
398- func (r Runner ) restoreObject (_ io.Writer , bucket * string , key * string ) error {
352+ // restoreObject restores object
353+ func (r * Runner ) restoreObject (_ io.Writer , bucket * string , key * string ) error {
399354 resp , err := r .Client .HeadObject (bucket , key )
400355
401356 if err != nil {
@@ -435,3 +390,84 @@ func (r *Runner) AddObjectSegments(bucket, prefix string, token *string) []Snaps
435390
436391 return segments
437392}
393+
394+ // RunConcurrentRestore runs restore process concurrently
395+ // This only runs if user uses --force option
396+ func (r * Runner ) RunConcurrentRestore (out io.Writer , bucket string , segments []SnapshotSegment , maxSemaphore int64 ) (bool , error ) {
397+ var result []SegmentError
398+ var areAllObjectsStandard bool
399+
400+ // maxSemaphore limits the number of go routines
401+ if maxSemaphore == 0 {
402+ maxSemaphore = constants .DefaultMaxConcurrentJob
403+ }
404+
405+ bar := pb .New (len (segments ))
406+ bar .SetRefreshRate (time .Second )
407+ bar .SetWriter (out )
408+
409+ var wg sync.WaitGroup
410+ semaphore := make (chan int , maxSemaphore )
411+ output := make (chan []SegmentError )
412+ input := make (chan SegmentError )
413+ defer close (output )
414+
415+ go func (input chan SegmentError , output chan []SegmentError , wg * sync.WaitGroup , bar * pb.ProgressBar ) {
416+ var ret []SegmentError
417+ for se := range input {
418+ ret = append (ret , se )
419+ bar .Add (1 )
420+ wg .Done ()
421+ }
422+ output <- ret
423+ }(input , output , & wg , bar )
424+
425+ f := func (out io.Writer , bucket string , segment SnapshotSegment , ch chan SegmentError , sem chan int ) {
426+ sem <- 1
427+ time .Sleep (1 * time .Second )
428+
429+ //color.Green("Restore Storage Class to %s -> STANDARD", segment.StorageClass)
430+ err := r .restoreObject (out , aws .String (bucket ), aws .String (segment .Key ))
431+ ch <- SegmentError {
432+ Key : segment .Key ,
433+ Error : err ,
434+ }
435+
436+ <- sem
437+ }
438+
439+ bar .Start ()
440+ for _ , s := range segments {
441+ if s .StorageClass == "GLACIER" {
442+ areAllObjectsStandard = false
443+ wg .Add (1 )
444+ go f (out , bucket , s , input , semaphore )
445+ } else {
446+ bar .Add (1 )
447+ }
448+ }
449+ wg .Wait ()
450+ close (input )
451+
452+ bar .Finish ()
453+
454+ result = <- output
455+
456+ if len (result ) > 0 {
457+ for _ , s := range result {
458+ if s .Error != nil {
459+ s .PrintError ()
460+ }
461+ }
462+ }
463+
464+ return areAllObjectsStandard , nil
465+ }
466+
467+ // checkRepositoryType checks if repository type is supported by escli
468+ func checkRepositoryType (repositoryType string ) error {
469+ if ! util .IsStringInArray (strings .ToLower (repositoryType ), constants .SupportedRepositoryType ) {
470+ return fmt .Errorf ("unsupported repository type: %s" , repositoryType )
471+ }
472+ return nil
473+ }
0 commit comments