sdr-client 0.7.1 → 0.8.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/lib/sdr_client/cli.rb +3 -0
- data/lib/sdr_client/credentials.rb +4 -4
- data/lib/sdr_client/deposit.rb +2 -0
- data/lib/sdr_client/deposit/files/direct_upload_request.rb +5 -5
- data/lib/sdr_client/deposit/metadata_builder.rb +42 -0
- data/lib/sdr_client/deposit/process.rb +14 -54
- data/lib/sdr_client/deposit/upload_files.rb +87 -0
- data/lib/sdr_client/version.rb +1 -1
- metadata +5 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d4ac0ef485cd0ede90e6bcb2b99dcf001f92f3f296720520e6f1d4f5dcccef47
|
4
|
+
data.tar.gz: 52d7af6780779c41dcb67d87b9f87a139568132e612c2118ae5170617b023d06
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 48f9cb820ed8e23aada68d2bd65fe676b94941bb47e618832449df5bbcfe53ffb632fc961e1f5d3279d5fc9a8d6458dc32f28fd5b6e3ba240911cc50a9f137c8
|
7
|
+
data.tar.gz: 6ad9e1dd66c890a2ae771c95d53c3204872fc8c8fc3eb851863f021c1150748134a426b6aedd511b378a9bba29566d828c4eefa9b027462fedeeea0a170c9df7
|
data/lib/sdr_client/cli.rb
CHANGED
@@ -3,6 +3,8 @@
|
|
3
3
|
module SdrClient
|
4
4
|
# The stored credentials
|
5
5
|
class Credentials
|
6
|
+
class NoCredentialsError < StandardError; end
|
7
|
+
|
6
8
|
# @param [String] a json string that contains a field 'token'
|
7
9
|
def self.write(body)
|
8
10
|
json = JSON.parse(body)
|
@@ -10,14 +12,12 @@ module SdrClient
|
|
10
12
|
File.open(credentials_file, 'w', 0o600) do |file|
|
11
13
|
file.write(json.fetch('token'))
|
12
14
|
end
|
13
|
-
puts 'Signed in.'
|
14
15
|
end
|
15
16
|
|
16
17
|
def self.read
|
17
|
-
|
18
|
+
raise NoCredentialsError unless ::File.exist?(credentials_file)
|
18
19
|
|
19
|
-
|
20
|
-
exit(1)
|
20
|
+
IO.readlines(credentials_file, chomp: true).first
|
21
21
|
end
|
22
22
|
|
23
23
|
def self.credentials_path
|
data/lib/sdr_client/deposit.rb
CHANGED
@@ -39,4 +39,6 @@ require 'sdr_client/deposit/files/direct_upload_response'
|
|
39
39
|
require 'sdr_client/deposit/file'
|
40
40
|
require 'sdr_client/deposit/file_set'
|
41
41
|
require 'sdr_client/deposit/request'
|
42
|
+
require 'sdr_client/deposit/upload_files'
|
43
|
+
require 'sdr_client/deposit/metadata_builder'
|
42
44
|
require 'sdr_client/deposit/process'
|
@@ -6,12 +6,12 @@ module SdrClient
|
|
6
6
|
module Deposit
|
7
7
|
module Files
|
8
8
|
DirectUploadRequest = Struct.new(:checksum, :byte_size, :content_type, :filename, keyword_init: true) do
|
9
|
-
def self.from_file(
|
10
|
-
checksum = Digest::MD5.file(
|
9
|
+
def self.from_file(path, file_name:, content_type:)
|
10
|
+
checksum = Digest::MD5.file(path).base64digest
|
11
11
|
new(checksum: checksum,
|
12
|
-
byte_size: ::File.size(
|
13
|
-
content_type: '
|
14
|
-
filename:
|
12
|
+
byte_size: ::File.size(path),
|
13
|
+
content_type: content_type || 'application/octet-stream',
|
14
|
+
filename: file_name)
|
15
15
|
end
|
16
16
|
|
17
17
|
def as_json
|
@@ -0,0 +1,42 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'logger'
|
4
|
+
|
5
|
+
module SdrClient
|
6
|
+
module Deposit
|
7
|
+
# Constructs the deposit metadata for the DRO
|
8
|
+
class MetadataBuilder
|
9
|
+
# @param [Request] metadata information about the object
|
10
|
+
# @param [Class] grouping_strategy class whose run method groups an array of uploads
|
11
|
+
# @param [Hash<String, Hash<String, String>>] files_metadata file name, hash of additional file metadata
|
12
|
+
# Additional metadata includes access, preserve, shelve, md5, sha1
|
13
|
+
# @param [Logger] logger the logger to use
|
14
|
+
def initialize(metadata:, grouping_strategy:, files_metadata:, logger:)
|
15
|
+
@metadata = metadata
|
16
|
+
@logger = logger
|
17
|
+
@grouping_strategy = grouping_strategy
|
18
|
+
@files_metadata = files_metadata
|
19
|
+
end
|
20
|
+
|
21
|
+
def with_uploads(upload_responses)
|
22
|
+
file_sets = build_filesets(uploads: upload_responses)
|
23
|
+
metadata.with_file_sets(file_sets)
|
24
|
+
end
|
25
|
+
|
26
|
+
private
|
27
|
+
|
28
|
+
attr_reader :metadata, :files, :logger, :grouping_strategy, :files_metadata
|
29
|
+
|
30
|
+
# @param [Array<SdrClient::Deposit::Files::DirectUploadResponse>] uploads the uploaded files to attach.
|
31
|
+
# @return [Array<SdrClient::Deposit::FileSet>] the uploads transformed to filesets
|
32
|
+
def build_filesets(uploads:)
|
33
|
+
grouped_uploads = grouping_strategy.run(uploads: uploads)
|
34
|
+
grouped_uploads.map.with_index(1) do |upload_group, i|
|
35
|
+
metadata_group = {}
|
36
|
+
upload_group.each { |upload| metadata_group[upload.filename] = files_metadata.fetch(upload.filename, {}) }
|
37
|
+
FileSet.new(uploads: upload_group, uploads_metadata: metadata_group, label: "Object #{i}")
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -6,7 +6,6 @@ module SdrClient
|
|
6
6
|
module Deposit
|
7
7
|
# The process for doing a deposit
|
8
8
|
class Process
|
9
|
-
BLOB_PATH = '/v1/direct_uploads'
|
10
9
|
DRO_PATH = '/v1/resources'
|
11
10
|
# @param [Request] metadata information about the object
|
12
11
|
# @param [Class] grouping_strategy class whose run method groups an array of uploads
|
@@ -31,11 +30,13 @@ module SdrClient
|
|
31
30
|
|
32
31
|
def run
|
33
32
|
check_files_exist
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
33
|
+
upload_responses = UploadFiles.new(files: files, logger: logger,
|
34
|
+
connection: connection, files_metadata: files_metadata).run
|
35
|
+
metadata_builder = MetadataBuilder.new(metadata: metadata,
|
36
|
+
grouping_strategy: grouping_strategy,
|
37
|
+
files_metadata: files_metadata,
|
38
|
+
logger: logger)
|
39
|
+
request = metadata_builder.with_uploads(upload_responses)
|
39
40
|
upload_metadata(request.as_json)
|
40
41
|
end
|
41
42
|
|
@@ -50,51 +51,6 @@ module SdrClient
|
|
50
51
|
end
|
51
52
|
end
|
52
53
|
|
53
|
-
def collect_file_metadata
|
54
|
-
files.each_with_object({}) do |filename, obj|
|
55
|
-
obj[filename] = Files::DirectUploadRequest.from_file(filename)
|
56
|
-
end
|
57
|
-
end
|
58
|
-
|
59
|
-
# @param [Hash<String,Files::DirectUploadRequest>] file_metadata the filenames and their upload request
|
60
|
-
def upload_file_metadata(file_metadata)
|
61
|
-
Hash[file_metadata.map { |filename, metadata| [filename, direct_upload(metadata.to_json)] }]
|
62
|
-
end
|
63
|
-
|
64
|
-
def direct_upload(metadata_json)
|
65
|
-
logger.info("Starting an upload request: #{metadata_json}")
|
66
|
-
response = connection.post(BLOB_PATH, metadata_json, 'Content-Type' => 'application/json')
|
67
|
-
raise "unexpected response: #{response.inspect}" unless response.status == 200
|
68
|
-
|
69
|
-
logger.info("Response from server: #{response.body}")
|
70
|
-
|
71
|
-
Files::DirectUploadResponse.new(JSON.parse(response.body))
|
72
|
-
end
|
73
|
-
|
74
|
-
# @param [Hash<String,Files::DirectUploadResponse>] upload_responses the filenames and their upload response
|
75
|
-
def upload_files(upload_responses)
|
76
|
-
upload_responses.each do |filename, response|
|
77
|
-
upload_file(filename: filename,
|
78
|
-
url: response.direct_upload.fetch('url'),
|
79
|
-
content_type: response.content_type,
|
80
|
-
content_length: response.byte_size)
|
81
|
-
|
82
|
-
logger.info('Upload complete')
|
83
|
-
end
|
84
|
-
end
|
85
|
-
|
86
|
-
def upload_file(filename:, url:, content_type:, content_length:)
|
87
|
-
logger.info("Uploading `#{filename}' to #{url}")
|
88
|
-
|
89
|
-
upload_response = connection.put(url) do |req|
|
90
|
-
req.body = ::File.open(filename)
|
91
|
-
req.headers['Content-Type'] = content_type
|
92
|
-
req.headers['Content-Length'] = content_length.to_s
|
93
|
-
end
|
94
|
-
|
95
|
-
raise "unexpected response: #{upload_response.inspect}" unless upload_response.status == 204
|
96
|
-
end
|
97
|
-
|
98
54
|
# @return [Hash<Symbol,String>] the result of the metadata call
|
99
55
|
def upload_metadata(metadata)
|
100
56
|
logger.info("Starting upload metadata: #{metadata}")
|
@@ -122,16 +78,20 @@ module SdrClient
|
|
122
78
|
end
|
123
79
|
|
124
80
|
# @param [Array<SdrClient::Deposit::Files::DirectUploadResponse>] uploads the uploaded files to attach.
|
125
|
-
# @param [Hash<String,Hash<String, String>>] files_metadata filename, hash of additional file metadata.
|
126
81
|
# @return [Array<SdrClient::Deposit::FileSet>] the uploads transformed to filesets
|
127
|
-
def build_filesets(uploads
|
82
|
+
def build_filesets(uploads:)
|
128
83
|
grouped_uploads = grouping_strategy.run(uploads: uploads)
|
129
84
|
grouped_uploads.map.with_index(1) do |upload_group, i|
|
130
85
|
metadata_group = {}
|
131
|
-
upload_group.each { |upload| metadata_group[upload.filename] =
|
86
|
+
upload_group.each { |upload| metadata_group[upload.filename] = file_metadata_for(upload.filename) }
|
132
87
|
FileSet.new(uploads: upload_group, uploads_metadata: metadata_group, label: "Object #{i}")
|
133
88
|
end
|
134
89
|
end
|
90
|
+
|
91
|
+
# @return [Hash<Symbol,String>] the file metadata for this file
|
92
|
+
def file_metadata_for(filename)
|
93
|
+
files_metadata.fetch(filename, {})
|
94
|
+
end
|
135
95
|
end
|
136
96
|
end
|
137
97
|
end
|
@@ -0,0 +1,87 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'logger'
|
4
|
+
|
5
|
+
module SdrClient
|
6
|
+
module Deposit
|
7
|
+
# The file uploading part of a deposit
|
8
|
+
class UploadFiles
|
9
|
+
BLOB_PATH = '/v1/direct_uploads'
|
10
|
+
# @param [Array<String>] files a list of file names to upload
|
11
|
+
# @param [Logger] logger the logger to use
|
12
|
+
# @param [Faraday::Connection] connection
|
13
|
+
# @param [Hash<String, Hash<String, String>>] files_metadata file name, hash of additional file metadata
|
14
|
+
def initialize(files:, files_metadata:, logger:, connection:)
|
15
|
+
@files = files
|
16
|
+
@files_metadata = files_metadata
|
17
|
+
@logger = logger
|
18
|
+
@connection = connection
|
19
|
+
end
|
20
|
+
|
21
|
+
# @return [Array<SdrClient::Deposit::Files::DirectUploadResponse>] the responses from the server for the uploads
|
22
|
+
def run
|
23
|
+
file_metadata = collect_file_metadata
|
24
|
+
upload_responses = upload_file_metadata(file_metadata)
|
25
|
+
upload_files(upload_responses)
|
26
|
+
upload_responses.values
|
27
|
+
end
|
28
|
+
|
29
|
+
private
|
30
|
+
|
31
|
+
attr_reader :files, :files_metadata, :logger, :connection
|
32
|
+
|
33
|
+
def collect_file_metadata
|
34
|
+
files.each_with_object({}) do |path, obj|
|
35
|
+
file_name = ::File.basename(path)
|
36
|
+
obj[path] = Files::DirectUploadRequest.from_file(path,
|
37
|
+
file_name: file_name,
|
38
|
+
content_type: file_metadata_for(file_name)[:mime_type])
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
# @param [Hash<String,Files::DirectUploadRequest>] file_metadata the filenames and their upload request
|
43
|
+
def upload_file_metadata(file_metadata)
|
44
|
+
Hash[file_metadata.map { |filename, metadata| [filename, direct_upload(metadata.to_json)] }]
|
45
|
+
end
|
46
|
+
|
47
|
+
def direct_upload(metadata_json)
|
48
|
+
logger.info("Starting an upload request: #{metadata_json}")
|
49
|
+
response = connection.post(BLOB_PATH, metadata_json, 'Content-Type' => 'application/json')
|
50
|
+
raise "unexpected response: #{response.inspect}" unless response.status == 200
|
51
|
+
|
52
|
+
logger.info("Response from server: #{response.body}")
|
53
|
+
|
54
|
+
Files::DirectUploadResponse.new(JSON.parse(response.body))
|
55
|
+
end
|
56
|
+
|
57
|
+
# @param [Hash<String,Files::DirectUploadResponse>] upload_responses the filenames and their upload response
|
58
|
+
def upload_files(upload_responses)
|
59
|
+
upload_responses.each do |filename, response|
|
60
|
+
upload_file(filename: filename,
|
61
|
+
url: response.direct_upload.fetch('url'),
|
62
|
+
content_type: response.content_type,
|
63
|
+
content_length: response.byte_size)
|
64
|
+
|
65
|
+
logger.info('Upload complete')
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
def upload_file(filename:, url:, content_type:, content_length:)
|
70
|
+
logger.info("Uploading `#{filename}' to #{url}")
|
71
|
+
|
72
|
+
upload_response = connection.put(url) do |req|
|
73
|
+
req.body = ::File.open(filename)
|
74
|
+
req.headers['Content-Type'] = content_type
|
75
|
+
req.headers['Content-Length'] = content_length.to_s
|
76
|
+
end
|
77
|
+
|
78
|
+
raise "unexpected response: #{upload_response.inspect}" unless upload_response.status == 204
|
79
|
+
end
|
80
|
+
|
81
|
+
# @return [Hash<Symbol,String>] the file metadata for this file
|
82
|
+
def file_metadata_for(filename)
|
83
|
+
files_metadata.fetch(filename, {})
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
data/lib/sdr_client/version.rb
CHANGED
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.8.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: 2020-01-
|
11
|
+
date: 2020-01-31 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: dry-monads
|
@@ -168,9 +168,11 @@ files:
|
|
168
168
|
- lib/sdr_client/deposit/files/direct_upload_request.rb
|
169
169
|
- lib/sdr_client/deposit/files/direct_upload_response.rb
|
170
170
|
- lib/sdr_client/deposit/matching_file_grouping_strategy.rb
|
171
|
+
- lib/sdr_client/deposit/metadata_builder.rb
|
171
172
|
- lib/sdr_client/deposit/process.rb
|
172
173
|
- lib/sdr_client/deposit/request.rb
|
173
174
|
- lib/sdr_client/deposit/single_file_grouping_strategy.rb
|
175
|
+
- lib/sdr_client/deposit/upload_files.rb
|
174
176
|
- lib/sdr_client/login.rb
|
175
177
|
- lib/sdr_client/login_prompt.rb
|
176
178
|
- lib/sdr_client/version.rb
|
@@ -196,7 +198,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
196
198
|
- !ruby/object:Gem::Version
|
197
199
|
version: '0'
|
198
200
|
requirements: []
|
199
|
-
rubygems_version: 3.
|
201
|
+
rubygems_version: 3.0.6
|
200
202
|
signing_key:
|
201
203
|
specification_version: 4
|
202
204
|
summary: The CLI for https://github.com/sul-dlss/sdr-api
|