deb-s3-lock-fix 0.11.8.fix0.1

Sign up to get free protection for your applications and to get access to all the features.
data/lib/deb/s3/cli.rb ADDED
@@ -0,0 +1,767 @@
1
+ # -*- encoding : utf-8 -*-
2
+ require "aws-sdk-s3"
3
+ require "thor"
4
+
5
+ # Hack: aws requires this!
6
+ require "json"
7
+
8
+ require "deb/s3"
9
+ require "deb/s3/utils"
10
+ require "deb/s3/manifest"
11
+ require "deb/s3/package"
12
+ require "deb/s3/release"
13
+ require "deb/s3/lock"
14
+
15
+ class Deb::S3::CLI < Thor
16
+ class_option :bucket,
17
+ :type => :string,
18
+ :aliases => "-b",
19
+ :desc => "The name of the S3 bucket to upload to."
20
+
21
+ class_option :prefix,
22
+ :type => :string,
23
+ :desc => "The path prefix to use when storing on S3."
24
+
25
+ class_option :origin,
26
+ :type => :string,
27
+ :aliases => "-o",
28
+ :desc => "The origin to use in the repository Release file."
29
+
30
+ class_option :suite,
31
+ :type => :string,
32
+ :desc => "The suite to use in the repository Release file."
33
+
34
+ class_option :codename,
35
+ :default => "stable",
36
+ :type => :string,
37
+ :aliases => "-c",
38
+ :desc => "The codename of the APT repository."
39
+
40
+ class_option :component,
41
+ :default => "main",
42
+ :type => :string,
43
+ :aliases => "-m",
44
+ :desc => "The component of the APT repository."
45
+
46
+ class_option :section,
47
+ :type => :string,
48
+ :aliases => "-s",
49
+ :hide => true
50
+
51
+ class_option :access_key_id,
52
+ :type => :string,
53
+ :desc => "The access key for connecting to S3."
54
+
55
+ class_option :secret_access_key,
56
+ :type => :string,
57
+ :desc => "The secret key for connecting to S3."
58
+
59
+ class_option :session_token,
60
+ :type => :string,
61
+ :desc => "The (optional) session token for connecting to S3."
62
+
63
+ class_option :endpoint,
64
+ :type => :string,
65
+ :desc => "The URL endpoint to the S3 API."
66
+
67
+ class_option :s3_region,
68
+ :type => :string,
69
+ :desc => "The region for connecting to S3.",
70
+ :default => ENV["AWS_DEFAULT_REGION"] || "us-east-1"
71
+
72
+ class_option :force_path_style,
73
+ :default => false,
74
+ :type => :boolean,
75
+ :desc => "Use S3 path style instead of subdomains."
76
+
77
+ class_option :proxy_uri,
78
+ :type => :string,
79
+ :desc => "The URI of the proxy to send service requests through."
80
+
81
+ class_option :visibility,
82
+ :default => "public",
83
+ :type => :string,
84
+ :aliases => "-v",
85
+ :desc => "The access policy for the uploaded files. " +
86
+ "Can be public, private, or authenticated."
87
+
88
+ class_option :sign,
89
+ :repeatable => true,
90
+ :desc => "GPG Sign the Release file when uploading a package, " +
91
+ "or when verifying it after removing a package. " +
92
+ "Use --sign with your GPG key ID to use a specific key (--sign=6643C242C18FE05B)." +
93
+ "Can be specified multiple times for multiple singing keys."
94
+
95
+ class_option :gpg_options,
96
+ :default => "",
97
+ :type => :string,
98
+ :desc => "Additional command line options to pass to GPG when signing."
99
+
100
+ class_option :encryption,
101
+ :default => false,
102
+ :type => :boolean,
103
+ :aliases => "-e",
104
+ :desc => "Use S3 server side encryption."
105
+
106
+ class_option :quiet,
107
+ :type => :boolean,
108
+ :aliases => "-q",
109
+ :desc => "Doesn't output information, just returns status appropriately."
110
+
111
+ class_option :cache_control,
112
+ :type => :string,
113
+ :aliases => "-C",
114
+ :desc => "Add cache-control headers to S3 objects."
115
+
116
+ desc "upload FILES",
117
+ "Uploads the given files to a S3 bucket as an APT repository."
118
+
119
+ option :arch,
120
+ :type => :string,
121
+ :aliases => "-a",
122
+ :desc => "The architecture of the package in the APT repository."
123
+
124
+ option :preserve_versions,
125
+ :default => false,
126
+ :type => :boolean,
127
+ :aliases => "-p",
128
+ :desc => "Whether to preserve other versions of a package " +
129
+ "in the repository when uploading one."
130
+
131
+ option :lock,
132
+ :default => false,
133
+ :type => :boolean,
134
+ :aliases => "-l",
135
+ :desc => "Whether to check for an existing lock on the repository " +
136
+ "to prevent simultaneous updates "
137
+
138
+ option :fail_if_exists,
139
+ :default => false,
140
+ :type => :boolean,
141
+ :desc => "Whether to overwrite any existing package that has the same " +
142
+ "filename in the pool or the same name and version in the manifest but " +
143
+ "different contents."
144
+
145
+ option :skip_package_upload,
146
+ :default => false,
147
+ :type => :boolean,
148
+ :desc => "Whether to skip all package uploads." +
149
+ "This is useful when hosting .deb files outside of the bucket."
150
+
151
+ def upload(*files)
152
+ if files.nil? || files.empty?
153
+ error("You must specify at least one file to upload")
154
+ end
155
+
156
+ # make sure all the files exists
157
+ if missing_file = files.find { |pattern| Dir.glob(pattern).empty? }
158
+ error("File '#{missing_file}' doesn't exist")
159
+ end
160
+
161
+ # configure AWS::S3
162
+ configure_s3_client
163
+
164
+ begin
165
+ if options[:lock]
166
+ log("Checking for existing lock file")
167
+ log("Locking repository for updates")
168
+ Deb::S3::Lock.lock(options[:codename])
169
+ @lock_acquired = true
170
+ end
171
+
172
+ # retrieve the existing manifests
173
+ log("Retrieving existing manifests")
174
+ release = Deb::S3::Release.retrieve(options[:codename], options[:origin], options[:suite], options[:cache_control])
175
+ manifests = {}
176
+ release.architectures.each do |arch|
177
+ manifests[arch] = Deb::S3::Manifest.retrieve(options[:codename], component, arch, options[:cache_control], options[:fail_if_exists], options[:skip_package_upload])
178
+ end
179
+
180
+ packages_arch_all = []
181
+
182
+ # examine all the files
183
+ files.collect { |f| Dir.glob(f) }.flatten.each do |file|
184
+ log("Examining package file #{File.basename(file)}")
185
+ pkg = Deb::S3::Package.parse_file(file)
186
+
187
+ # copy over some options if they weren't given
188
+ arch = options[:arch] || pkg.architecture
189
+
190
+ # If they've specified an arch type that doesn't match the package let them know
191
+ if options.key?("arch") && options[:arch] != pkg.architecture
192
+ warn("You specified architecture #{options[:arch]} but package #{pkg.name} has architecture type of #{pkg.architecture}")
193
+ end
194
+
195
+ # validate we have them
196
+ error("No architcture given and unable to determine one for #{file}. " +
197
+ "Please specify one with --arch [i386|amd64|armhf].") unless arch
198
+
199
+ # If the arch is all and the list of existing manifests is none, then
200
+ # throw an error. This is mainly the case when initializing a brand new
201
+ # repository. With "all", we won't know which architectures they're using.
202
+ if arch == "all" && manifests.count == 0
203
+ manifests['amd64'] = Deb::S3::Manifest.retrieve(options[:codename], component,'amd64', options[:cache_control], options[:fail_if_exists], options[:skip_package_upload])
204
+ manifests['i386'] = Deb::S3::Manifest.retrieve(options[:codename], component,'i386', options[:cache_control], options[:fail_if_exists], options[:skip_package_upload])
205
+ manifests['armhf'] = Deb::S3::Manifest.retrieve(options[:codename], component,'armhf', options[:cache_control], options[:fail_if_exists], options[:skip_package_upload])
206
+
207
+ # error("Package #{File.basename(file)} had architecture \"all\", " +
208
+ # "however noexisting package lists exist. This can often happen " +
209
+ # "if the first package you are add to a new repository is an " +
210
+ # "\"all\" architecture file. Please use --arch [i386|amd64|armhf] or " +
211
+ # "another platform type to upload the file.")
212
+ end
213
+
214
+ # retrieve the manifest for the arch if we don't have it already
215
+ manifests[arch] ||= Deb::S3::Manifest.retrieve(options[:codename], component, arch, options[:cache_control], options[:fail_if_exists], options[:skip_package_upload])
216
+
217
+ # add package in manifests
218
+ begin
219
+ manifests[arch].add(pkg, options[:preserve_versions])
220
+ rescue Deb::S3::Utils::AlreadyExistsError => e
221
+ error("Preparing manifest failed because: #{e}")
222
+ end
223
+
224
+ # If arch is all, we must add this package in all arch available
225
+ if arch == 'all'
226
+ packages_arch_all << pkg
227
+ end
228
+ end
229
+
230
+ manifests.each do |arch, manifest|
231
+ next if arch == 'all'
232
+ packages_arch_all.each do |pkg|
233
+ begin
234
+ manifest.add(pkg, options[:preserve_versions], false)
235
+ rescue Deb::S3::Utils::AlreadyExistsError => e
236
+ error("Preparing manifest failed because: #{e}")
237
+ end
238
+ end
239
+ end
240
+
241
+ # upload the manifest
242
+ log("Uploading packages and new manifests to S3")
243
+ manifests.each_value do |manifest|
244
+ begin
245
+ manifest.write_to_s3 do |f|
246
+ sublog("Transferring #{f} at #{Time.now.strftime('%Y-%m-%d %H:%M:%S')}")
247
+ end
248
+ rescue Deb::S3::Utils::AlreadyExistsError => e
249
+ error("Uploading manifest failed because: #{e}")
250
+ end
251
+ release.update_manifest(manifest)
252
+ end
253
+ release.write_to_s3 do |f|
254
+ sublog("Transferring #{f} at #{Time.now.strftime('%Y-%m-%d %H:%M:%S')}")
255
+ end
256
+
257
+ log("Update complete.")
258
+ ensure
259
+ if options[:lock] && @lock_acquired
260
+ Deb::S3::Lock.unlock(options[:codename])
261
+ log("Lock released.")
262
+ end
263
+ end
264
+ end
265
+
266
+ desc "list", "Lists packages in given codename, component, and optionally architecture"
267
+
268
+ option :long,
269
+ :type => :boolean,
270
+ :aliases => '-l',
271
+ :desc => "Shows all package information in original format.",
272
+ :default => false
273
+
274
+ option :arch,
275
+ :type => :string,
276
+ :aliases => "-a",
277
+ :desc => "The architecture of the package in the APT repository."
278
+
279
+ def list
280
+ configure_s3_client
281
+
282
+ release = Deb::S3::Release.retrieve(options[:codename])
283
+ archs = release.architectures
284
+ archs &= [options[:arch]] if options[:arch] && options[:arch] != "all"
285
+ widths = [0, 0]
286
+ rows = archs.map { |arch|
287
+ manifest = Deb::S3::Manifest.retrieve(options[:codename], component,
288
+ arch, options[:cache_control],
289
+ false, false)
290
+ manifest.packages.map do |package|
291
+ if options[:long]
292
+ package.generate(options[:codename])
293
+ else
294
+ [package.name, package.full_version, package.architecture].tap do |row|
295
+ row.each_with_index do |col, i|
296
+ widths[i] = [widths[i], col.size].max if widths[i]
297
+ end
298
+ end
299
+ end
300
+ end
301
+ }.flatten(1)
302
+
303
+ if options[:long]
304
+ $stdout.puts rows.join("\n")
305
+ else
306
+ rows.each do |row|
307
+ $stdout.puts "% -#{widths[0]}s % -#{widths[1]}s %s" % row
308
+ end
309
+ end
310
+ end
311
+
312
+ desc "show PACKAGE VERSION ARCH", "Shows information about a package."
313
+
314
+ def show(package_name, version, arch)
315
+ if version.nil?
316
+ error "You must specify the name of the package to show."
317
+ end
318
+ if version.nil?
319
+ error "You must specify the version of the package to show."
320
+ end
321
+ if arch.nil?
322
+ error "You must specify the architecture of the package to show."
323
+ end
324
+
325
+ configure_s3_client
326
+
327
+ # retrieve the existing manifests
328
+ manifest = Deb::S3::Manifest.retrieve(options[:codename], component, arch,
329
+ options[:cache_control], false, false)
330
+ package = manifest.packages.detect { |p|
331
+ p.name == package_name && p.full_version == version
332
+ }
333
+ if package.nil?
334
+ error "No such package found."
335
+ end
336
+
337
+ puts package.generate(options[:codename])
338
+ end
339
+
340
+ desc "copy PACKAGE TO_CODENAME TO_COMPONENT ",
341
+ "Copy the package named PACKAGE to given codename and component. If --versions is not specified, copy all versions of PACKAGE. Otherwise, only the specified versions will be copied. Source codename and component is given by --codename and --component options."
342
+
343
+ option :cache_control,
344
+ :type => :string,
345
+ :aliases => "-C",
346
+ :desc => "Add cache-control headers to S3 objects."
347
+
348
+ option :arch,
349
+ :type => :string,
350
+ :aliases => "-a",
351
+ :desc => "The architecture of the package in the APT repository."
352
+
353
+ option :lock,
354
+ :default => false,
355
+ :type => :boolean,
356
+ :aliases => "-l",
357
+ :desc => "Whether to check for an existing lock on the repository " +
358
+ "to prevent simultaneous updates "
359
+
360
+ option :versions,
361
+ :default => nil,
362
+ :type => :array,
363
+ :desc => "The space-delimited versions of PACKAGE to delete. If not " +
364
+ "specified, ALL VERSIONS will be deleted. Fair warning. " +
365
+ "E.g. --versions \"0.1 0.2 0.3\""
366
+
367
+ option :preserve_versions,
368
+ :default => false,
369
+ :type => :boolean,
370
+ :aliases => "-p",
371
+ :desc => "Whether to preserve other versions of a package " +
372
+ "in the repository when uploading one."
373
+
374
+ option :fail_if_exists,
375
+ :default => true,
376
+ :type => :boolean,
377
+ :desc => "Whether to overwrite any existing package that has the same " +
378
+ "filename in the pool or the same name and version in the manifest."
379
+
380
+ def copy(package_name, to_codename, to_component)
381
+ if package_name.nil?
382
+ error "You must specify a package name."
383
+ end
384
+ if to_codename.nil?
385
+ error "You must specify a codename to copy to."
386
+ end
387
+ if to_component.nil?
388
+ error "You must specify a component to copy to."
389
+ end
390
+
391
+ arch = options[:arch]
392
+ if arch.nil?
393
+ error "You must specify the architecture of the package to copy."
394
+ end
395
+
396
+ versions = options[:versions]
397
+ if versions.nil?
398
+ warn "===> WARNING: Copying all versions of #{package_name}"
399
+ else
400
+ log "Versions to copy: #{versions.join(', ')}"
401
+ end
402
+
403
+ configure_s3_client
404
+
405
+ begin
406
+ if options[:lock]
407
+ log("Checking for existing lock file")
408
+ log("Locking repository for updates")
409
+ Deb::S3::Lock.lock(options[:codename])
410
+ @lock_acquired = true
411
+ end
412
+
413
+ # retrieve the existing manifests
414
+ log "Retrieving existing manifests"
415
+ from_manifest = Deb::S3::Manifest.retrieve(options[:codename],
416
+ component, arch,
417
+ options[:cache_control],
418
+ false, options[:skip_package_upload])
419
+ to_release = Deb::S3::Release.retrieve(to_codename)
420
+ to_manifest = Deb::S3::Manifest.retrieve(to_codename, to_component, arch,
421
+ options[:cache_control],
422
+ options[:fail_if_exists],
423
+ options[:skip_package_upload])
424
+ packages = from_manifest.packages.select { |p|
425
+ p.name == package_name &&
426
+ (versions.nil? || versions.include?(p.full_version))
427
+ }
428
+ if packages.size == 0
429
+ error "No packages found in repository."
430
+ end
431
+
432
+ packages.each do |package|
433
+ begin
434
+ to_manifest.add package, options[:preserve_versions], false
435
+ rescue Deb::S3::Utils::AlreadyExistsError => e
436
+ error("Preparing manifest failed because: #{e}")
437
+ end
438
+ end
439
+
440
+ begin
441
+ to_manifest.write_to_s3 { |f| sublog("Transferring #{f}") }
442
+ rescue Deb::S3::Utils::AlreadyExistsError => e
443
+ error("Copying manifest failed because: #{e}")
444
+ end
445
+ to_release.update_manifest(to_manifest)
446
+ to_release.write_to_s3 { |f| sublog("Transferring #{f}") }
447
+
448
+ log "Copy complete."
449
+ ensure
450
+ if options[:lock] && @lock_acquired
451
+ Deb::S3::Lock.unlock(options[:codename])
452
+ log("Lock released.")
453
+ end
454
+ end
455
+ end
456
+
457
+ desc "delete PACKAGE",
458
+ "Remove the package named PACKAGE. If --versions is not specified, delete" +
459
+ "all versions of PACKAGE. Otherwise, only the specified versions will be " +
460
+ "deleted."
461
+
462
+ option :arch,
463
+ :type => :string,
464
+ :aliases => "-a",
465
+ :desc => "The architecture of the package in the APT repository."
466
+
467
+ option :lock,
468
+ :default => false,
469
+ :type => :boolean,
470
+ :aliases => "-l",
471
+ :desc => "Whether to check for an existing lock on the repository " +
472
+ "to prevent simultaneous updates "
473
+
474
+ option :versions,
475
+ :default => nil,
476
+ :type => :array,
477
+ :desc => "The space-delimited versions of PACKAGE to delete. If not " +
478
+ "specified, ALL VERSIONS will be deleted. Fair warning. " +
479
+ "E.g. --versions \"0.1 0.2 0.3\""
480
+
481
+ def delete(package)
482
+ if package.nil?
483
+ error("You must specify a package name.")
484
+ end
485
+
486
+ versions = options[:versions]
487
+ if versions.nil?
488
+ warn("===> WARNING: Deleting all versions of #{package}")
489
+ else
490
+ log("Versions to delete: #{versions.join(', ')}")
491
+ end
492
+
493
+ arch = options[:arch]
494
+ if arch.nil?
495
+ error("You must specify the architecture of the package to remove.")
496
+ end
497
+
498
+ configure_s3_client
499
+
500
+ begin
501
+ if options[:lock]
502
+ log("Checking for existing lock file")
503
+ log("Locking repository for updates")
504
+ Deb::S3::Lock.lock(options[:codename])
505
+ @lock_acquired = true
506
+ end
507
+
508
+ # retrieve the existing manifests
509
+ log("Retrieving existing manifests")
510
+ release = Deb::S3::Release.retrieve(options[:codename], options[:origin], options[:suite])
511
+ if arch == 'all'
512
+ selected_arch = release.architectures
513
+ else
514
+ selected_arch = [arch]
515
+ end
516
+ all_found = 0
517
+ selected_arch.each { |ar|
518
+ manifest = Deb::S3::Manifest.retrieve(options[:codename], component, ar, options[:cache_control], false, options[:skip_package_upload])
519
+
520
+ deleted = manifest.delete_package(package, versions)
521
+ all_found += deleted.length
522
+ if deleted.length == 0
523
+ if versions.nil?
524
+ sublog("No packages were deleted. #{package} not found in arch #{ar}.")
525
+ next
526
+ else
527
+ sublog("No packages were deleted. #{package} versions #{versions.join(', ')} could not be found in arch #{ar}.")
528
+ next
529
+ end
530
+ else
531
+ deleted.each { |p|
532
+ sublog("Deleting #{p.name} version #{p.full_version} from arch #{ar}")
533
+ }
534
+ end
535
+
536
+ log("Uploading new manifests to S3")
537
+ manifest.write_to_s3 {|f| sublog("Transferring #{f}") }
538
+ release.update_manifest(manifest)
539
+ release.write_to_s3 {|f| sublog("Transferring #{f}") }
540
+
541
+ log("Update complete.")
542
+ }
543
+ if all_found == 0
544
+ if versions.nil?
545
+ error("No packages were deleted. #{package} not found.")
546
+ else
547
+ error("No packages were deleted. #{package} versions #{versions.join(', ')} could not be found.")
548
+ end
549
+ end
550
+ ensure
551
+ if options[:lock] && @lock_acquired
552
+ Deb::S3::Lock.unlock(options[:codename])
553
+ log("Lock released.")
554
+ end
555
+ end
556
+ end
557
+
558
+
559
+ desc "verify", "Verifies that the files in the package manifests exist"
560
+
561
+ option :fix_manifests,
562
+ :default => false,
563
+ :type => :boolean,
564
+ :aliases => "-f",
565
+ :desc => "Whether to fix problems in manifests when verifying."
566
+
567
+ def verify
568
+ configure_s3_client
569
+
570
+ log("Retrieving existing manifests")
571
+ release = Deb::S3::Release.retrieve(options[:codename], options[:origin], options[:suite])
572
+
573
+ release.architectures.each do |arch|
574
+ log("Checking for missing packages in: #{options[:codename]}/#{options[:component]} #{arch}")
575
+ manifest = Deb::S3::Manifest.retrieve(options[:codename], component,
576
+ arch, options[:cache_control], false,
577
+ options[:skip_package_upload])
578
+ missing_packages = []
579
+
580
+ manifest.packages.each do |p|
581
+ unless Deb::S3::Utils.s3_exists? p.url_filename(options[:codename])
582
+ sublog("The following packages are missing:\n\n") if missing_packages.empty?
583
+ puts(p.generate(options[:codename]))
584
+ puts("")
585
+
586
+ missing_packages << p
587
+ end
588
+ end
589
+
590
+ if options[:sign] || (options[:fix_manifests] && !missing_packages.empty?)
591
+ log("Removing #{missing_packages.length} package(s) from the manifest...")
592
+ missing_packages.each { |p| manifest.packages.delete(p) }
593
+ manifest.write_to_s3 { |f| sublog("Transferring #{f}") }
594
+ release.update_manifest(manifest)
595
+ release.write_to_s3 { |f| sublog("Transferring #{f}") }
596
+
597
+ log("Update complete.")
598
+ end
599
+ end
600
+ end
601
+
602
+ desc "clean", "Delete packages from the pool which are no longer referenced"
603
+
604
+ option :lock,
605
+ :default => false,
606
+ :type => :boolean,
607
+ :aliases => "-l",
608
+ :desc => "Whether to check for an existing lock on the repository " +
609
+ "to prevent simultaneous updates "
610
+
611
+ def clean
612
+ configure_s3_client
613
+
614
+ begin
615
+ if options[:lock]
616
+ log("Checking for existing lock file")
617
+ log("Locking repository for updates")
618
+ Deb::S3::Lock.lock(options[:codename])
619
+ @lock_acquired = true
620
+ end
621
+
622
+ log("Retrieving existing manifests")
623
+
624
+ # Enumerate objects under the dists/<codename>/ prefix to find any
625
+ # Packages files and load them....
626
+
627
+ req = Deb::S3::Utils.s3.list_objects_v2({
628
+ :bucket => Deb::S3::Utils.bucket,
629
+ :prefix => Deb::S3::Utils.s3_path("dists/#{ options[:codename] }/"),
630
+ })
631
+
632
+ manifests = []
633
+ req.contents.each do |object|
634
+ if match = object.key.match(/dists\/([^\/]+)\/([^\/]+)\/binary-([^\/]+)\/Packages$/)
635
+ codename, component, arch = match.captures
636
+ manifests.push(Deb::S3::Manifest.retrieve(codename, component, arch, options[:cache_control], options[:fail_if_exists], options[:skip_package_upload]))
637
+ end
638
+ end
639
+
640
+ # Iterate over the packages in each manifest and build a Set of all the
641
+ # referenced URLs (relative to bucket root)...
642
+
643
+ refd_urls = Set[]
644
+ manifests.each do |manifest|
645
+ manifest.packages.each do |package|
646
+ refd_urls.add(Deb::S3::Utils.s3_path(package.url_filename(manifest.codename)))
647
+ end
648
+ end
649
+
650
+ log("Searching for unreferenced packages")
651
+
652
+ # Enumerate objects under the pools/<codename> prefix and delete any that
653
+ # arent referenced by any of the manifests.
654
+
655
+ continuation_token = nil
656
+ while true
657
+ req = Deb::S3::Utils.s3.list_objects_v2({
658
+ :bucket => Deb::S3::Utils.bucket,
659
+ :prefix => Deb::S3::Utils.s3_path("pool/#{ options[:codename] }/"),
660
+ :continuation_token => continuation_token,
661
+ })
662
+
663
+ req.contents.each do |object|
664
+ if not refd_urls.include?(object.key)
665
+ sublog("Deleting #{ object.key }")
666
+
667
+ Deb::S3::Utils.s3.delete_object({
668
+ :bucket => Deb::S3::Utils.bucket,
669
+ :key => object.key,
670
+ })
671
+ end
672
+ end
673
+
674
+ if req.is_truncated
675
+ continuation_token = req.next_continuation_token
676
+ else
677
+ break
678
+ end
679
+ end
680
+ ensure
681
+ if options[:lock] && @lock_acquired
682
+ Deb::S3::Lock.unlock(options[:codename])
683
+ log("Lock released.")
684
+ end
685
+ end
686
+ end
687
+
688
+ private
689
+
690
+ def component
691
+ return @component if @component
692
+ @component = if (section = options[:section])
693
+ warn("===> WARNING: The --section/-s argument is " \
694
+ "deprecated, please use --component/-m.")
695
+ section
696
+ else
697
+ options[:component]
698
+ end
699
+ end
700
+
701
+ def puts(*args)
702
+ $stdout.puts(*args) unless options[:quiet]
703
+ end
704
+
705
+ def log(message)
706
+ puts ">> #{message}" unless options[:quiet]
707
+ end
708
+
709
+ def sublog(message)
710
+ puts " -- #{message}" unless options[:quiet]
711
+ end
712
+
713
+ def error(message)
714
+ $stderr.puts "!! #{message}" unless options[:quiet]
715
+ exit 1
716
+ end
717
+
718
+ def provider
719
+ access_key_id = options[:access_key_id]
720
+ secret_access_key = options[:secret_access_key]
721
+ session_token = options[:session_token]
722
+
723
+ if access_key_id.nil? ^ secret_access_key.nil?
724
+ error("If you specify one of --access-key-id or --secret-access-key, you must specify the other.")
725
+ end
726
+ static_credentials = {}
727
+ static_credentials[:access_key_id] = access_key_id if access_key_id
728
+ static_credentials[:secret_access_key] = secret_access_key if secret_access_key
729
+ static_credentials[:session_token] = session_token if session_token
730
+
731
+ static_credentials
732
+ end
733
+
734
+ def configure_s3_client
735
+ error("No value provided for required options '--bucket'") unless options[:bucket]
736
+
737
+ settings = {
738
+ :region => options[:s3_region],
739
+ :http_proxy => options[:proxy_uri],
740
+ :force_path_style => options[:force_path_style]
741
+ }
742
+ settings[:endpoint] = options[:endpoint] if options[:endpoint]
743
+ settings.merge!(provider)
744
+
745
+ Deb::S3::Utils.s3 = Aws::S3::Client.new(settings)
746
+ Deb::S3::Utils.bucket = options[:bucket]
747
+ Deb::S3::Utils.signing_key = options[:sign]
748
+ Deb::S3::Utils.gpg_options = options[:gpg_options]
749
+ Deb::S3::Utils.prefix = options[:prefix]
750
+ Deb::S3::Utils.encryption = options[:encryption]
751
+
752
+ # make sure we have a valid visibility setting
753
+ Deb::S3::Utils.access_policy =
754
+ case options[:visibility]
755
+ when "public"
756
+ "public-read"
757
+ when "private"
758
+ "private"
759
+ when "authenticated"
760
+ "authenticated-read"
761
+ when "bucket_owner"
762
+ "bucket-owner-full-control"
763
+ else
764
+ error("Invalid visibility setting given. Can be public, private, authenticated, or bucket_owner.")
765
+ end
766
+ end
767
+ end