duracloud-client 0.8.0 → 0.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +14 -1
- data/lib/duracloud.rb +5 -1
- data/lib/duracloud/cli.rb +29 -107
- data/lib/duracloud/command_options.rb +120 -0
- data/lib/duracloud/commands.rb +40 -0
- data/lib/duracloud/commands/command.rb +6 -2
- data/lib/duracloud/commands/count.rb +15 -0
- data/lib/duracloud/commands/download_manifest.rb +0 -2
- data/lib/duracloud/commands/find.rb +16 -0
- data/lib/duracloud/commands/find_item.rb +16 -0
- data/lib/duracloud/commands/find_items.rb +22 -0
- data/lib/duracloud/commands/find_missing_items.rb +15 -0
- data/lib/duracloud/commands/find_space.rb +12 -0
- data/lib/duracloud/commands/get_storage_report.rb +16 -0
- data/lib/duracloud/commands/get_storage_report_for_all_spaces.rb +12 -0
- data/lib/duracloud/commands/get_storage_report_for_space.rb +10 -0
- data/lib/duracloud/commands/get_storage_report_for_store.rb +10 -0
- data/lib/duracloud/commands/list_content_ids.rb +11 -0
- data/lib/duracloud/commands/list_items.rb +17 -0
- data/lib/duracloud/commands/sync.rb +0 -2
- data/lib/duracloud/commands/validate.rb +2 -3
- data/lib/duracloud/content.rb +12 -3
- data/lib/duracloud/fast_sync_validation.rb +42 -0
- data/lib/duracloud/rest_methods.rb +15 -0
- data/lib/duracloud/storage_report.rb +33 -0
- data/lib/duracloud/storage_reports.rb +52 -0
- data/lib/duracloud/sync_validation.rb +122 -39
- data/lib/duracloud/version.rb +1 -1
- data/spec/unit/cli_spec.rb +59 -15
- data/spec/unit/client_spec.rb +24 -0
- data/spec/unit/content_spec.rb +17 -7
- data/spec/unit/storage_report_spec.rb +15 -0
- data/spec/unit/storage_reports_spec.rb +45 -0
- metadata +23 -3
- data/lib/duracloud/commands/get_properties.rb +0 -27
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a80c928604f4871e81e40df21497f669d57dce14
|
4
|
+
data.tar.gz: bb0f71e139c0fff9e5634a56c205106daed5a0d5
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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?`.
|
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 :
|
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 =
|
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 :
|
21
|
-
:
|
22
|
-
:
|
23
|
-
:
|
24
|
-
:
|
25
|
-
|
26
|
-
|
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
|
59
|
+
cli.execute
|
118
60
|
rescue => e
|
119
61
|
error!(e)
|
120
62
|
end
|
121
63
|
|
122
|
-
def execute
|
64
|
+
def execute
|
123
65
|
configure_client
|
124
|
-
send(command
|
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 }
|
@@ -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
|