sdr-client 0.72.0 → 0.75.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.rubocop_todo.yml +9 -8
- data/README.md +9 -0
- data/lib/sdr_client/cli.rb +10 -4
- data/lib/sdr_client/connection.rb +8 -2
- data/lib/sdr_client/deposit/upload_files.rb +11 -22
- data/lib/sdr_client/update.rb +57 -36
- data/lib/sdr_client/version.rb +1 -1
- data/sdr-client.gemspec +1 -1
- metadata +4 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: da8b0699691f353f0141796f1b687b167e47faf343e763b22e006afc7042d4b2
|
4
|
+
data.tar.gz: ac627e37ed720454c5569c7da728257b36988424af0c0f7acc365e63ee3e80e1
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 0357af1078af521bf1f3837e121dc844b1e0b1e39ec3c36678517dea2f0795da6e77f553f5e402c21c12e5c5bbe571d205643ce3fbf3e91e82dc99f9157ac7cd
|
7
|
+
data.tar.gz: 3edd8d027451deb5f90667decb7824062833c59bd35e15241238ef617082e33bee83e2a0219e4c6c2a6a000c2c09cd8bb0d5718ce1b58f37d7a22eec0167c790
|
data/.rubocop_todo.yml
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
# This configuration was generated by
|
2
2
|
# `rubocop --auto-gen-config --auto-gen-only-exclude`
|
3
|
-
# on 2022-03-
|
3
|
+
# on 2022-03-23 20:29:32 UTC using RuboCop version 1.25.1.
|
4
4
|
# The point is for the user to remove these configuration records
|
5
5
|
# one by one as the offenses are removed from the code base.
|
6
6
|
# Note that changes in the inspected code, or installation of new
|
@@ -26,21 +26,20 @@ Lint/UnusedMethodArgument:
|
|
26
26
|
- 'lib/sdr_client/deposit/file_type_file_set_strategy.rb'
|
27
27
|
- 'lib/sdr_client/deposit/image_file_set_strategy.rb'
|
28
28
|
|
29
|
-
# Offense count:
|
29
|
+
# Offense count: 4
|
30
30
|
# Configuration parameters: IgnoredMethods, CountRepeatedAttributes, Max.
|
31
31
|
Metrics/AbcSize:
|
32
32
|
Exclude:
|
33
33
|
- 'lib/sdr_client/cli.rb'
|
34
34
|
- 'lib/sdr_client/update.rb'
|
35
35
|
|
36
|
-
# Offense count:
|
36
|
+
# Offense count: 1
|
37
37
|
# Configuration parameters: IgnoredMethods, Max.
|
38
38
|
Metrics/CyclomaticComplexity:
|
39
39
|
Exclude:
|
40
|
-
- 'lib/sdr_client/cli.rb'
|
41
40
|
- 'lib/sdr_client/update.rb'
|
42
41
|
|
43
|
-
# Offense count:
|
42
|
+
# Offense count: 12
|
44
43
|
# Configuration parameters: CountComments, Max, CountAsOne, ExcludedMethods, IgnoredMethods.
|
45
44
|
Metrics/MethodLength:
|
46
45
|
Exclude:
|
@@ -52,7 +51,7 @@ Metrics/MethodLength:
|
|
52
51
|
- 'lib/sdr_client/login.rb'
|
53
52
|
- 'lib/sdr_client/update.rb'
|
54
53
|
|
55
|
-
# Offense count:
|
54
|
+
# Offense count: 11
|
56
55
|
# Configuration parameters: Max, CountAsOne.
|
57
56
|
RSpec/ExampleLength:
|
58
57
|
Exclude:
|
@@ -106,7 +105,7 @@ RSpec/NamedSubject:
|
|
106
105
|
- 'spec/sdr_client/deposit/process_spec.rb'
|
107
106
|
- 'spec/sdr_client/login_spec.rb'
|
108
107
|
|
109
|
-
# Offense count:
|
108
|
+
# Offense count: 16
|
110
109
|
# Configuration parameters: Max.
|
111
110
|
RSpec/NestedGroups:
|
112
111
|
Exclude:
|
@@ -114,6 +113,7 @@ RSpec/NestedGroups:
|
|
114
113
|
- 'spec/sdr_client/deposit/model_process_spec.rb'
|
115
114
|
- 'spec/sdr_client/deposit/process_spec.rb'
|
116
115
|
- 'spec/sdr_client/login_spec.rb'
|
116
|
+
- 'spec/sdr_client/update_spec.rb'
|
117
117
|
|
118
118
|
# Offense count: 19
|
119
119
|
# Cop supports --auto-correct.
|
@@ -136,7 +136,7 @@ Style/StringConcatenation:
|
|
136
136
|
- 'lib/sdr_client/deposit/create_resource.rb'
|
137
137
|
- 'spec/sdr_client/deposit_spec.rb'
|
138
138
|
|
139
|
-
# Offense count:
|
139
|
+
# Offense count: 26
|
140
140
|
# Cop supports --auto-correct.
|
141
141
|
# Configuration parameters: Max, AllowHeredoc, AllowURI, URISchemes, IgnoreCopDirectives, IgnoredPatterns.
|
142
142
|
# URISchemes: http, https
|
@@ -147,3 +147,4 @@ Layout/LineLength:
|
|
147
147
|
- 'lib/sdr_client/update.rb'
|
148
148
|
- 'spec/sdr_client/deposit/model_process_spec.rb'
|
149
149
|
- 'spec/sdr_client/deposit/process_spec.rb'
|
150
|
+
- 'spec/sdr_client/update_spec.rb'
|
data/README.md
CHANGED
@@ -79,16 +79,25 @@ Update an object:
|
|
79
79
|
```
|
80
80
|
# Change admin policy object (APO)
|
81
81
|
sdr update druid:bb408qn5061 --url https://sdr-api-server:3000 --admin-policy druid:bx911tp9024
|
82
|
+
|
82
83
|
# Change collection
|
83
84
|
sdr update druid:bb408qn5061 --url https://sdr-api-server:3000 --collection druid:pb756dt1672
|
85
|
+
|
84
86
|
# Change copyright
|
85
87
|
sdr update druid:bb408qn5061 --url https://sdr-api-server:3000 --copyright "Here is a new copyright statement"
|
88
|
+
|
86
89
|
# Change use and reproduction statement
|
87
90
|
sdr update druid:bb408qn5061 --url https://sdr-api-server:3000 --use-and-reproduction "Here are the terms of use..."
|
91
|
+
|
88
92
|
# Change license
|
89
93
|
sdr update druid:bb408qn5061 --url https://sdr-api-server:3000 --license "https://www.apache.org/licenses/LICENSE-2.0"
|
94
|
+
|
90
95
|
# Change access controls
|
91
96
|
sdr update druid:bb408qn5061 --url https://sdr-api-server:3000 --view "location-based" --download "none" --location "music" --cdl false
|
97
|
+
|
98
|
+
# Change Cocina wholesale from a file (note that you can use this flag with the
|
99
|
+
# others above, and the flags above will replace what's supplied in the cocina file)
|
100
|
+
sdr update druid:bb408qn5061 --url https://sdr-api-server:3000 --cocina-file bb408qn5061.json
|
92
101
|
```
|
93
102
|
|
94
103
|
## Testing
|
data/lib/sdr_client/cli.rb
CHANGED
@@ -69,7 +69,8 @@ module SdrClient
|
|
69
69
|
option :view, enum: %w[world stanford location-based citation-only dark], desc: 'Access view level for the object'
|
70
70
|
option :download, enum: %w[world stanford location-based none], desc: 'Access download level for the object'
|
71
71
|
option :location, enum: %w[spec music ars art hoover m&m], desc: 'Access location for the object'
|
72
|
-
option :cdl, type: :boolean, default: false
|
72
|
+
option :cdl, type: :boolean, default: false, desc: 'Controlled digital lending'
|
73
|
+
option :cocina_file, desc: 'Path to a file containing Cocina JSON'
|
73
74
|
def update(druid)
|
74
75
|
validate_druid!(druid)
|
75
76
|
job_id = SdrClient::Update.run(druid, **options)
|
@@ -153,7 +154,7 @@ module SdrClient
|
|
153
154
|
|
154
155
|
def poll_for_job_complete(job_id:, url:)
|
155
156
|
# the extra args to `say` prevent appending a newline
|
156
|
-
say('SDR is processing your request', nil, false)
|
157
|
+
say('SDR is processing your request.', nil, false)
|
157
158
|
result = nil
|
158
159
|
(1).upto(60) do
|
159
160
|
result = SdrClient::BackgroundJobResults.show(url: url, job_id: job_id)
|
@@ -163,10 +164,15 @@ module SdrClient
|
|
163
164
|
say('.', nil, false)
|
164
165
|
sleep 1
|
165
166
|
end
|
167
|
+
|
166
168
|
if result['status'] == 'complete'
|
167
|
-
|
169
|
+
if (errors = result.dig('output', 'errors'))
|
170
|
+
say_error " errored! #{errors}"
|
171
|
+
else
|
172
|
+
say " success! (druid: #{result.dig('output', 'druid')})"
|
173
|
+
end
|
168
174
|
else
|
169
|
-
say_error "
|
175
|
+
say_error " job #{job_id} did not complete\n#{result.inspect}"
|
170
176
|
end
|
171
177
|
end
|
172
178
|
end
|
@@ -6,10 +6,10 @@ module SdrClient
|
|
6
6
|
include Dry::Monads[:result]
|
7
7
|
|
8
8
|
# @param [Integer] read_timeout the value in seconds to set the read timeout
|
9
|
-
def initialize(url:, token: Credentials.read, read_timeout:
|
9
|
+
def initialize(url:, token: Credentials.read, read_timeout: default_timeout, timeout: default_timeout)
|
10
10
|
@url = url
|
11
11
|
@token = token
|
12
|
-
@request_options = { read_timeout: read_timeout }
|
12
|
+
@request_options = { read_timeout: read_timeout, timeout: timeout }
|
13
13
|
end
|
14
14
|
|
15
15
|
def connection
|
@@ -39,5 +39,11 @@ module SdrClient
|
|
39
39
|
private
|
40
40
|
|
41
41
|
attr_reader :url, :token, :request_options
|
42
|
+
|
43
|
+
# NOTE: This is the number of seconds it roughly takes for H2 to
|
44
|
+
# successfully shunt ~10GB files over to SDR API
|
45
|
+
def default_timeout
|
46
|
+
900
|
47
|
+
end
|
42
48
|
end
|
43
49
|
end
|
@@ -7,6 +7,7 @@ module SdrClient
|
|
7
7
|
# The file uploading part of a deposit
|
8
8
|
class UploadFiles
|
9
9
|
BLOB_PATH = '/v1/direct_uploads'
|
10
|
+
|
10
11
|
# @param [Hash<String,Files::DirectUploadRequest>] the metadata for uploading the files
|
11
12
|
# @param [Logger] logger the logger to use
|
12
13
|
# @param [Connection] connection
|
@@ -23,23 +24,23 @@ module SdrClient
|
|
23
24
|
@connection = connection
|
24
25
|
end
|
25
26
|
|
26
|
-
# @return [Array<
|
27
|
+
# @return [Array<Files::DirectUploadResponse>] the responses from the server for the uploads
|
27
28
|
def run
|
28
|
-
|
29
|
-
|
30
|
-
|
29
|
+
file_metadata.map do |filename, metadata|
|
30
|
+
direct_upload(metadata.to_json).tap do |response|
|
31
|
+
upload_file(filename: filename,
|
32
|
+
url: response.direct_upload.fetch('url'),
|
33
|
+
content_type: response.content_type,
|
34
|
+
content_length: response.byte_size)
|
35
|
+
logger.info("Upload of #{filename} complete")
|
36
|
+
end
|
37
|
+
end
|
31
38
|
end
|
32
39
|
|
33
40
|
private
|
34
41
|
|
35
42
|
attr_reader :logger, :connection, :file_metadata
|
36
43
|
|
37
|
-
def upload_file_metadata
|
38
|
-
file_metadata.transform_values { |metadata| direct_upload(metadata.to_json) }
|
39
|
-
end
|
40
|
-
|
41
|
-
# This creates a signed token that we can use to upload the file. This token has an expiration set in sdr-api,
|
42
|
-
# so we have to use it before it expires.
|
43
44
|
def direct_upload(metadata_json)
|
44
45
|
logger.info("Starting an upload request: #{metadata_json}")
|
45
46
|
response = connection.post(BLOB_PATH, metadata_json, 'Content-Type' => 'application/json')
|
@@ -56,18 +57,6 @@ module SdrClient
|
|
56
57
|
raise "unexpected response: #{response.inspect}"
|
57
58
|
end
|
58
59
|
|
59
|
-
# @param [Hash<String,Files::DirectUploadResponse>] upload_responses the filenames and their upload response
|
60
|
-
def upload_files(upload_responses)
|
61
|
-
upload_responses.each do |filename, response|
|
62
|
-
upload_file(filename: filename,
|
63
|
-
url: response.direct_upload.fetch('url'),
|
64
|
-
content_type: response.content_type,
|
65
|
-
content_length: response.byte_size)
|
66
|
-
|
67
|
-
logger.info('Upload complete')
|
68
|
-
end
|
69
|
-
end
|
70
|
-
|
71
60
|
def upload_file(filename:, url:, content_type:, content_length:)
|
72
61
|
logger.info("Uploading `#{filename}' to #{url}")
|
73
62
|
|
data/lib/sdr_client/update.rb
CHANGED
@@ -17,7 +17,7 @@ module SdrClient
|
|
17
17
|
# @return [String] job id for the background job result
|
18
18
|
def run
|
19
19
|
SdrClient::Deposit::UpdateResource.run(
|
20
|
-
metadata:
|
20
|
+
metadata: updated_cocina_object,
|
21
21
|
logger: options[:logger] || Logger.new($stdout),
|
22
22
|
connection: SdrClient::Connection.new(url: url)
|
23
23
|
)
|
@@ -27,17 +27,18 @@ module SdrClient
|
|
27
27
|
|
28
28
|
attr_reader :druid, :logger, :options, :url
|
29
29
|
|
30
|
-
def
|
31
|
-
@
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
30
|
+
def updated_cocina_object
|
31
|
+
@updated_cocina_object ||=
|
32
|
+
original_cocina_object.then { |cocina_object| update_cocina(cocina_object) }
|
33
|
+
.then { |cocina_object| update_apo(cocina_object) }
|
34
|
+
.then { |cocina_object| update_collection(cocina_object) }
|
35
|
+
.then { |cocina_object| update_copyright(cocina_object) }
|
36
|
+
.then { |cocina_object| update_use_and_reproduction(cocina_object) }
|
37
|
+
.then { |cocina_object| update_license(cocina_object) }
|
38
|
+
.then { |cocina_object| update_access(cocina_object) }
|
38
39
|
end
|
39
40
|
|
40
|
-
def
|
41
|
+
def original_cocina_object
|
41
42
|
Cocina::Models.build(
|
42
43
|
JSON.parse(
|
43
44
|
SdrClient::Find.run(druid, url: url)
|
@@ -45,56 +46,76 @@ module SdrClient
|
|
45
46
|
)
|
46
47
|
end
|
47
48
|
|
49
|
+
def cocina_hash_from_file
|
50
|
+
@cocina_hash_from_file ||= JSON.parse(File.read(options[:cocina_file]), symbolize_names: true)
|
51
|
+
end
|
52
|
+
|
53
|
+
# Update the Cocina in full
|
54
|
+
def update_cocina(cocina_object)
|
55
|
+
return cocina_object unless options[:cocina_file]
|
56
|
+
|
57
|
+
if !File.file?(options[:cocina_file]) || !File.readable?(options[:cocina_file])
|
58
|
+
raise "File not found: #{options[:cocina_file]}"
|
59
|
+
end
|
60
|
+
|
61
|
+
# NOTE: We may want to add more checks later. For now, make sure the identifiers match.
|
62
|
+
if cocina_object.externalIdentifier != cocina_hash_from_file[:externalIdentifier]
|
63
|
+
raise "Cocina in #{options[:cocina_file]} has a different external identifier than #{cocina_object.externalIdentifier}: #{cocina_hash_from_file[:externalIdentifier]}"
|
64
|
+
end
|
65
|
+
|
66
|
+
cocina_object.new(cocina_hash_from_file)
|
67
|
+
end
|
68
|
+
|
48
69
|
# Update the APO of a Cocina item if the options specify a new one, else return the original
|
49
|
-
def update_apo(
|
50
|
-
return
|
70
|
+
def update_apo(cocina_object)
|
71
|
+
return cocina_object unless options[:apo]
|
51
72
|
|
52
|
-
|
53
|
-
administrative:
|
73
|
+
cocina_object.new(
|
74
|
+
administrative: cocina_object.administrative.new(
|
54
75
|
hasAdminPolicy: options[:apo]
|
55
76
|
)
|
56
77
|
)
|
57
78
|
end
|
58
79
|
|
59
80
|
# Update the collection of a Cocina item if the options specify a new one, else return the original
|
60
|
-
def update_collection(
|
61
|
-
return
|
81
|
+
def update_collection(cocina_object)
|
82
|
+
return cocina_object unless options[:collection]
|
62
83
|
|
63
|
-
|
64
|
-
structural:
|
84
|
+
cocina_object.new(
|
85
|
+
structural: cocina_object.structural.new(
|
65
86
|
isMemberOf: Array(options[:collection])
|
66
87
|
)
|
67
88
|
)
|
68
89
|
end
|
69
90
|
|
70
91
|
# Update the copyright of a Cocina item if the options specify a new one, else return the original
|
71
|
-
def update_copyright(
|
72
|
-
return
|
92
|
+
def update_copyright(cocina_object)
|
93
|
+
return cocina_object unless options[:copyright]
|
73
94
|
|
74
|
-
|
75
|
-
access:
|
95
|
+
cocina_object.new(
|
96
|
+
access: cocina_object.access.new(
|
76
97
|
copyright: options[:copyright]
|
77
98
|
)
|
78
99
|
)
|
79
100
|
end
|
80
101
|
|
81
102
|
# Update the use and reproduction statement of a Cocina item if the options specify a new one, else return the original
|
82
|
-
def update_use_and_reproduction(
|
83
|
-
return
|
103
|
+
def update_use_and_reproduction(cocina_object)
|
104
|
+
return cocina_object unless options[:use_and_reproduction]
|
84
105
|
|
85
|
-
|
86
|
-
access:
|
106
|
+
cocina_object.new(
|
107
|
+
access: cocina_object.access.new(
|
87
108
|
useAndReproductionStatement: options[:use_and_reproduction]
|
88
109
|
)
|
89
110
|
)
|
90
111
|
end
|
91
112
|
|
92
113
|
# Update the license of a Cocina item if the options specify a new one, else return the original
|
93
|
-
def update_license(
|
94
|
-
return
|
114
|
+
def update_license(cocina_object)
|
115
|
+
return cocina_object unless options[:license]
|
95
116
|
|
96
|
-
|
97
|
-
access:
|
117
|
+
cocina_object.new(
|
118
|
+
access: cocina_object.access.new(
|
98
119
|
license: options[:license]
|
99
120
|
)
|
100
121
|
)
|
@@ -102,18 +123,18 @@ module SdrClient
|
|
102
123
|
|
103
124
|
# rubocop:disable Style/DoubleNegation
|
104
125
|
# Update the access of a Cocina item if the options specify a new one, else return the original
|
105
|
-
def update_access(
|
106
|
-
return
|
126
|
+
def update_access(cocina_object)
|
127
|
+
return cocina_object unless options[:view] || options[:download] || options[:location] || options[:cdl]
|
107
128
|
|
108
|
-
|
109
|
-
access:
|
129
|
+
cocina_object.new(
|
130
|
+
access: cocina_object.access.new(
|
110
131
|
view: options[:view],
|
111
132
|
download: options[:download],
|
112
133
|
location: options[:location],
|
113
134
|
controlledDigitalLending: !!options[:cdl]
|
114
135
|
),
|
115
|
-
structural:
|
116
|
-
contains:
|
136
|
+
structural: cocina_object.structural.new(
|
137
|
+
contains: cocina_object.structural.contains.map do |file_set|
|
117
138
|
file_set.new(
|
118
139
|
structural: file_set.structural.new(
|
119
140
|
contains: file_set.structural.contains.map do |file|
|
data/lib/sdr_client/version.rb
CHANGED
data/sdr-client.gemspec
CHANGED
@@ -28,7 +28,7 @@ Gem::Specification.new do |spec|
|
|
28
28
|
spec.require_paths = ['lib']
|
29
29
|
|
30
30
|
spec.add_dependency 'activesupport'
|
31
|
-
spec.add_dependency 'cocina-models', '~> 0.
|
31
|
+
spec.add_dependency 'cocina-models', '~> 0.70.0'
|
32
32
|
spec.add_dependency 'dry-monads'
|
33
33
|
spec.add_dependency 'faraday', '>= 0.16'
|
34
34
|
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: sdr-client
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.75.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Justin Coyne
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2022-03-
|
11
|
+
date: 2022-03-30 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activesupport
|
@@ -30,14 +30,14 @@ dependencies:
|
|
30
30
|
requirements:
|
31
31
|
- - "~>"
|
32
32
|
- !ruby/object:Gem::Version
|
33
|
-
version: 0.
|
33
|
+
version: 0.70.0
|
34
34
|
type: :runtime
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
38
|
- - "~>"
|
39
39
|
- !ruby/object:Gem::Version
|
40
|
-
version: 0.
|
40
|
+
version: 0.70.0
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
42
|
name: dry-monads
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|