duracloud-client 0.8.0 → 0.9.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (36) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +14 -1
  3. data/lib/duracloud.rb +5 -1
  4. data/lib/duracloud/cli.rb +29 -107
  5. data/lib/duracloud/command_options.rb +120 -0
  6. data/lib/duracloud/commands.rb +40 -0
  7. data/lib/duracloud/commands/command.rb +6 -2
  8. data/lib/duracloud/commands/count.rb +15 -0
  9. data/lib/duracloud/commands/download_manifest.rb +0 -2
  10. data/lib/duracloud/commands/find.rb +16 -0
  11. data/lib/duracloud/commands/find_item.rb +16 -0
  12. data/lib/duracloud/commands/find_items.rb +22 -0
  13. data/lib/duracloud/commands/find_missing_items.rb +15 -0
  14. data/lib/duracloud/commands/find_space.rb +12 -0
  15. data/lib/duracloud/commands/get_storage_report.rb +16 -0
  16. data/lib/duracloud/commands/get_storage_report_for_all_spaces.rb +12 -0
  17. data/lib/duracloud/commands/get_storage_report_for_space.rb +10 -0
  18. data/lib/duracloud/commands/get_storage_report_for_store.rb +10 -0
  19. data/lib/duracloud/commands/list_content_ids.rb +11 -0
  20. data/lib/duracloud/commands/list_items.rb +17 -0
  21. data/lib/duracloud/commands/sync.rb +0 -2
  22. data/lib/duracloud/commands/validate.rb +2 -3
  23. data/lib/duracloud/content.rb +12 -3
  24. data/lib/duracloud/fast_sync_validation.rb +42 -0
  25. data/lib/duracloud/rest_methods.rb +15 -0
  26. data/lib/duracloud/storage_report.rb +33 -0
  27. data/lib/duracloud/storage_reports.rb +52 -0
  28. data/lib/duracloud/sync_validation.rb +122 -39
  29. data/lib/duracloud/version.rb +1 -1
  30. data/spec/unit/cli_spec.rb +59 -15
  31. data/spec/unit/client_spec.rb +24 -0
  32. data/spec/unit/content_spec.rb +17 -7
  33. data/spec/unit/storage_report_spec.rb +15 -0
  34. data/spec/unit/storage_reports_spec.rb +45 -0
  35. metadata +23 -3
  36. data/lib/duracloud/commands/get_properties.rb +0 -27
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 935b71b6483353f2dee2f6919df2844e31f51ba7
4
- data.tar.gz: 369ec0668fbc416e23978241668a983e2bd92caa
3
+ metadata.gz: a80c928604f4871e81e40df21497f669d57dce14
4
+ data.tar.gz: bb0f71e139c0fff9e5634a56c205106daed5a0d5
5
5
  SHA512:
6
- metadata.gz: 6f8717da6c2ef7515e7bf791456d923c6156a445c541a3a5c21bd7b8d73730881ba4bd681ffc7539ca5717c9b2b25a887cd6de50107ad5c4149c4806aed553d4
7
- data.tar.gz: 351a64019bdea2b4426d9288df4ac5c7f7fa166dfe89ee25d3cecd14930a8c20ae71f01a29a34a1d9118431eb8df1d173e72d055b583b5359639e5d30ec6dbca
6
+ metadata.gz: 39311c8c6a74b5100779f0f32e3aa0b08c8c27d406492d3b4a3cf477736b75b8b8a9028a5935b9b6724f3922284bd4972ee4247a5f394cc7e8a58295e9b1cfb3
7
+ data.tar.gz: 266f141ab9f3d0d87759411ba76d63816498ea4980354eb6e9824cc89ac9c93fa802a7edb132bcf5b6535c90fff96d0a1f0ba76e528233f210eda0d6bb9fab43
data/README.md CHANGED
@@ -140,12 +140,25 @@ Assumptions:
140
140
  Process:
141
141
  - The space manifest is downloaded from DuraCloud and converted to the expected input format for `md5deep` (two columns: md5 hash and file path, separated by two spaces).
142
142
  - `md5deep` is run against the content directory in "non-matching" mode (-X) with the converted manifest as the list of "known hashes".
143
- - Non-matching files from the `md5deep` run are re-checked individually by calling `Duracloud::Content.exist?`. This pass will account for content sync after `md5deep` started as well as files that have been chunked in DuraCloud.
143
+ - Non-matching files from the `md5deep` run are re-checked individually by calling `Duracloud::Content.exist?`.
144
+ This pass will account for content sync after `md5deep` started as well as files that have been chunked in DuraCloud.
145
+ Results of this re-check are printed to STDOUT (or, if using the `:work_dir` option, below, to a file).
144
146
 
145
147
  ```ruby
146
148
  Duracloud::SyncValidation.call(space_id: 'foo', content_dir: '/var/foo/bar')
147
149
  ```
148
150
 
151
+ *Added in version 0.9.0* - `:work_dir` option to specify existing directory in which to write validation files. The default behavior is to
152
+ create a temporary directory which is deleted on completion of the process. If `:work_dir` is specified, no cleanup is performed.
153
+
154
+ Files created in work directory:
155
+ - `{SPACE_ID}-manifest.tsv` (DuraCloud manifest as downloaded)
156
+ - `{SPACE_ID}-md5.txt` (Munged manifest for md5deep)
157
+ - `{SPACE_ID}-audit.txt` (Output of md5deep, empty if all files match)
158
+ - `{SPACE_ID}-recheck.txt` (Out of audit recheck, if necessary)
159
+
160
+ *Added in version 0.9.0* - `Duracloud::FastSyncValidation`. This variant of sync validation does not compute local hashes but instead compares the local file list (generated with `find`) to the list of content IDs in the space manifest. Local misses are rechecked as in `SyncValidation` (but without MD5 comparison).
161
+
149
162
  ### Content
150
163
 
151
164
  #### Create a new content item and store it in DuraCloud
data/lib/duracloud.rb CHANGED
@@ -8,13 +8,15 @@ module Duracloud
8
8
  autoload :ChunkedContent, "duracloud/chunked_content"
9
9
  autoload :Client, "duracloud/client"
10
10
  autoload :CLI, "duracloud/cli"
11
+ autoload :CommandOptions, "duracloud/command_options"
12
+ autoload :Commands, "duracloud/commands"
11
13
  autoload :Configuration, "duracloud/configuration"
12
14
  autoload :Connection, "duracloud/connection"
13
15
  autoload :Content, "duracloud/content"
14
16
  autoload :ContentManifest, "duracloud/content_manifest"
15
17
  autoload :DurastoreRequest, "duracloud/durastore_request"
16
18
  autoload :ErrorHandler, "duracloud/error_handler"
17
- autoload :HasProperties, "duracloud/has_properties"
19
+ autoload :FastSyncValidation, "duracloud/fast_sync_validation"
18
20
  autoload :Manifest, "duracloud/manifest"
19
21
  autoload :Persistence, "duracloud/persistence"
20
22
  autoload :Properties, "duracloud/properties"
@@ -24,6 +26,8 @@ module Duracloud
24
26
  autoload :Space, "duracloud/space"
25
27
  autoload :SpaceAcls, "duracloud/space_acls"
26
28
  autoload :Store, "duracloud/store"
29
+ autoload :StorageReport, "duracloud/storage_report"
30
+ autoload :StorageReports, "duracloud/storage_reports"
27
31
  autoload :SyncValidation, "duracloud/sync_validation"
28
32
  autoload :TSV, "duracloud/tsv"
29
33
  end
data/lib/duracloud/cli.rb CHANGED
@@ -4,8 +4,9 @@ require 'active_model'
4
4
  module Duracloud
5
5
  class CLI
6
6
  include ActiveModel::Model
7
+ include Commands
7
8
 
8
- COMMANDS = %w( sync validate manifest properties )
9
+ COMMANDS = Commands.public_instance_methods.map(&:to_s)
9
10
 
10
11
  USAGE = <<-EOS
11
12
  Usage: duracloud [COMMAND] [options]
@@ -17,13 +18,28 @@ Options:
17
18
  EOS
18
19
  HELP = "Type 'duracloud -h/--help' for usage."
19
20
 
20
- attr_accessor :command, :user, :password, :host, :port,
21
- :space_id, :store_id, :content_id,
22
- :content_type, :md5,
23
- :content_dir, :format, :infile,
24
- :logging
25
-
26
- validates_presence_of :space_id, message: "-s/--space-id option is required."
21
+ attr_accessor :all_spaces,
22
+ :command,
23
+ :content_dir,
24
+ :content_id,
25
+ :content_type,
26
+ :fast,
27
+ :format,
28
+ :host,
29
+ :infile,
30
+ :logging,
31
+ :md5,
32
+ :missing,
33
+ :password,
34
+ :port,
35
+ :prefix,
36
+ :space_id,
37
+ :store_id,
38
+ :user,
39
+ :work_dir
40
+
41
+ validates_presence_of :space_id, message: "-s/--space-id option is required.", unless: "command == 'get_storage_report'"
42
+ validates_inclusion_of :command, in: COMMANDS
27
43
 
28
44
  def self.error!(exception)
29
45
  $stderr.puts exception.message
@@ -34,112 +50,20 @@ EOS
34
50
  end
35
51
 
36
52
  def self.call(*args)
37
- options = {}
38
-
39
- parser = OptionParser.new do |opts|
40
- opts.banner = USAGE
41
-
42
- opts.on("-h", "--help",
43
- "Prints help") do
44
- puts opts
45
- exit
46
- end
47
-
48
- opts.on("-H", "--host HOST",
49
- "DuraCloud host") do |v|
50
- options[:host] = v
51
- end
52
-
53
- opts.on("-P", "--port PORT",
54
- "DuraCloud port") do |v|
55
- options[:port] = v
56
- end
57
-
58
- opts.on("-u", "--user USER",
59
- "DuraCloud user") do |v|
60
- options[:user] = v
61
- end
62
-
63
- opts.on("-p", "--password PASSWORD",
64
- "DuraCloud password") do |v|
65
- options[:password] = v
66
- end
67
-
68
- opts.on("-l", "--[no-]logging",
69
- "Enable/disable logging to STDERR") do |v|
70
- options[:logging] = v
71
- end
72
-
73
- opts.on("-s", "--space-id SPACE_ID",
74
- "DuraCloud space ID") do |v|
75
- options[:space_id] = v
76
- end
77
-
78
- opts.on("-i", "--store-id STORE_ID",
79
- "DuraCloud store ID") do |v|
80
- options[:store_id] = v
81
- end
82
-
83
- opts.on("-c", "--content-id CONTENT_ID",
84
- "DuraCloud content ID") do |v|
85
- options[:content_id] = v
86
- end
87
-
88
- opts.on("-m", "--md5 MD5",
89
- "MD5 digest of content to store or retrieve") do |v|
90
- options[:md5] = v
91
- end
92
-
93
- opts.on("-b", "--bagit",
94
- "Get manifest in BAGIT format (default is TSV)") do
95
- options[:format] = Manifest::BAGIT_FORMAT
96
- end
97
-
98
- opts.on("-d", "--content-dir CONTENT_DIR",
99
- "Local content directory") do |v|
100
- options[:content_dir] = v
101
- end
102
-
103
- opts.on("-f", "--infile FILE",
104
- "Input file") do |v|
105
- options[:infile] = v
106
- end
107
- end
108
-
109
- command = args.shift if COMMANDS.include?(args.first)
110
- parser.parse!(args)
111
-
112
- cli = new(options)
53
+ options = CommandOptions.new(*args)
54
+ cli = new(options) # .merge(command: command))
113
55
  if cli.invalid?
114
56
  message = cli.errors.map { |k, v| "ERROR: #{v}" }.join("\n")
115
57
  raise CommandError, message
116
58
  end
117
- cli.execute(command)
59
+ cli.execute
118
60
  rescue => e
119
61
  error!(e)
120
62
  end
121
63
 
122
- def execute(command)
64
+ def execute
123
65
  configure_client
124
- send(command).call(self)
125
- end
126
-
127
- protected
128
-
129
- def sync
130
- Commands::Sync
131
- end
132
-
133
- def validate
134
- Commands::Validate
135
- end
136
-
137
- def manifest
138
- Commands::DownloadManifest
139
- end
140
-
141
- def properties
142
- Commands::GetProperties
66
+ send(command, self)
143
67
  end
144
68
 
145
69
  private
@@ -157,5 +81,3 @@ EOS
157
81
 
158
82
  end
159
83
  end
160
-
161
- Dir[File.expand_path("../commands/*.rb", __FILE__)].each { |m| require m }
@@ -0,0 +1,120 @@
1
+ require 'optparse'
2
+ require 'hashie'
3
+
4
+ module Duracloud
5
+ class CommandOptions < Hashie::Mash
6
+
7
+ def initialize(*args)
8
+ super()
9
+ self.command = args.shift if CLI::COMMANDS.include?(args.first)
10
+ parser.parse!(args)
11
+ end
12
+
13
+ def print_version
14
+ puts "duracloud-client #{Duracloud::VERSION}"
15
+ end
16
+
17
+ def parser
18
+ OptionParser.new do |opts|
19
+ opts.banner = CLI::USAGE
20
+
21
+ opts.on("-h", "--help",
22
+ "Prints help") do
23
+ print_version
24
+ puts opts
25
+ exit
26
+ end
27
+
28
+ opts.on("-H", "--host HOST",
29
+ "DuraCloud host") do |v|
30
+ self.host = v
31
+ end
32
+
33
+ opts.on("-P", "--port PORT",
34
+ "DuraCloud port") do |v|
35
+ self.port = v
36
+ end
37
+
38
+ opts.on("-u", "--user USER",
39
+ "DuraCloud user") do |v|
40
+ self.user = v
41
+ end
42
+
43
+ opts.on("-p", "--password PASSWORD",
44
+ "DuraCloud password") do |v|
45
+ self.password = v
46
+ end
47
+
48
+ opts.on("-l", "--[no-]logging",
49
+ "Enable/disable logging to STDERR") do |v|
50
+ self.logging = v
51
+ end
52
+
53
+ opts.on("-s", "--space-id SPACE_ID",
54
+ "DuraCloud space ID") do |v|
55
+ self.space_id = v
56
+ end
57
+
58
+ opts.on("-i", "--store-id STORE_ID",
59
+ "DuraCloud store ID") do |v|
60
+ self.store_id = v
61
+ end
62
+
63
+ opts.on("-c", "--content-id CONTENT_ID",
64
+ "DuraCloud content ID") do |v|
65
+ self.content_id = v
66
+ end
67
+
68
+ opts.on("-m", "--md5 MD5",
69
+ "MD5 digest of content to store or retrieve") do |v|
70
+ self.md5 = v
71
+ end
72
+
73
+ opts.on("-b", "--bagit",
74
+ "Get manifest in BAGIT format (default is TSV)") do
75
+ self.format = Manifest::BAGIT_FORMAT
76
+ end
77
+
78
+ opts.on("-d", "--content-dir DIR",
79
+ "Local content directory") do |v|
80
+ self.content_dir = v
81
+ end
82
+
83
+ opts.on("-f", "--infile FILE",
84
+ "Input file") do |v|
85
+ self.infile = v
86
+ end
87
+
88
+ opts.on("-v", "--version",
89
+ "Print version and exit") do |v|
90
+ print_version
91
+ exit
92
+ end
93
+
94
+ opts.on("-w", "--work-dir DIR",
95
+ "Working directory") do |v|
96
+ self.work_dir = v
97
+ end
98
+
99
+ opts.on("-F", "--[no-]fast-audit",
100
+ "Use fast audit for sync validation") do |v|
101
+ self.fast = v
102
+ end
103
+
104
+ opts.on("-a", "--prefix PREFIX",
105
+ "Content prefix") do |v|
106
+ self.prefix = v
107
+ end
108
+
109
+ opts.on("-M", "--[no-]missing", "Find missing items") do |v|
110
+ self.missing = v
111
+ end
112
+
113
+ opts.on("--[no-]all-spaces", "Get report for all spaces") do |v|
114
+ self.all_spaces = v
115
+ end
116
+ end
117
+ end
118
+
119
+ end
120
+ end
@@ -0,0 +1,40 @@
1
+ module Duracloud
2
+ module Commands
3
+
4
+ def find(cli)
5
+ Find.call(cli)
6
+ end
7
+
8
+ def count(cli)
9
+ Count.call(cli)
10
+ end
11
+
12
+ def get_storage_report(cli)
13
+ GetStorageReport.call(cli)
14
+ end
15
+
16
+ def sync(cli)
17
+ Sync.call(cli)
18
+ end
19
+
20
+ def validate(cli)
21
+ Validate.call(cli)
22
+ end
23
+
24
+ def download_manifest(cli)
25
+ DownloadManifest.call(cli)
26
+ end
27
+
28
+ def list_content_ids(cli)
29
+ ListContentIds.call(cli)
30
+ end
31
+
32
+ def list_items(cli)
33
+ ListItems.call(cli)
34
+ end
35
+
36
+ end
37
+ end
38
+
39
+ require 'duracloud/commands/command'
40
+ Dir[File.expand_path("../commands/*.rb", __FILE__)].each { |m| require m }
@@ -3,8 +3,12 @@ require 'delegate'
3
3
  module Duracloud::Commands
4
4
  class Command < SimpleDelegator
5
5
 
6
- def self.call(command)
7
- new(command).call
6
+ def self.call(cli)
7
+ new(cli).call
8
+ end
9
+
10
+ def cli
11
+ __getobj__
8
12
  end
9
13
 
10
14
  end
@@ -0,0 +1,15 @@
1
+ module Duracloud::Commands
2
+ class Count < Command
3
+
4
+ def call
5
+ space = Duracloud::Space.find(space_id, store_id)
6
+ count = if prefix || space.count == 1000
7
+ space.content_ids(prefix: prefix).to_a.length
8
+ else
9
+ space.count
10
+ end
11
+ puts count
12
+ end
13
+
14
+ end
15
+ end
@@ -1,5 +1,3 @@
1
- require_relative "command"
2
-
3
1
  module Duracloud::Commands
4
2
  class DownloadManifest < Command
5
3
 
@@ -0,0 +1,16 @@
1
+ module Duracloud::Commands
2
+ class Find < Command
3
+
4
+ def call
5
+ delegate_to = if content_id
6
+ FindItem
7
+ elsif infile
8
+ missing ? FindMissingItems : FindItems
9
+ else
10
+ FindSpace
11
+ end
12
+ delegate_to.call(cli)
13
+ end
14
+
15
+ end
16
+ end