preservation-client 2.2.0 → 3.3.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: a2b61bc152d52b868d7274c7e29753dca42e4547f04c836766922bad0eca4ed9
4
- data.tar.gz: 36f04a3919075d95729a6b74108f4acb9c5bb68f6625e4fc0e6b5a19f16fc52d
3
+ metadata.gz: 295c6b5719f6730587b25339215cb69a2a0577c83bb703cc0bc17bb0372b64e3
4
+ data.tar.gz: 26c60ca8f89488ed4d8e9ee301fb1632727ddb852ddaf4f2db796cf97f0a51f3
5
5
  SHA512:
6
- metadata.gz: 7750ce3cd4ef6df3ffe47dfb8b1f693894dff7dc9ad776ade1d703447c8dc52ce00464ac780d9870c93dfbf5dddbe9bd5b7a6977aeebb80876112aa31e5773b4
7
- data.tar.gz: 3a280db80ba0163894c8510238af78337866e853f09d3a528e097046d7f7c44d5f8f69805d5d67e993eafb76fc0cff9f3d53ca63ed1549941b3d72ceb7ff69fb
6
+ metadata.gz: 9d715a4987ea8c1091ba263eed8975feb66ab15e58669011860376a43ce7c80f7bbf771701f4416e9309fe7fb1dfa08e7986c0d7bf556bab939eab419e4c3fae
7
+ data.tar.gz: 2f27d27f5c0c02b0a9fb18943e5c25228e6e6d0f5ca24e190da9d7de20146f8f80d437f1351f659a627178ea52933c185aea811dcad6eff82586d6977ff6e733
@@ -1,4 +1,12 @@
1
1
  ## Why was this change made?
2
2
 
3
3
 
4
- ## Was the documentation (README, API, wiki, consul, etc.) updated?
4
+
5
+ ## How was this change tested?
6
+
7
+
8
+
9
+ ## Which documentation and/or configurations were updated?
10
+
11
+
12
+
@@ -24,6 +24,5 @@ Style/Documentation:
24
24
  Exclude:
25
25
  - 'spec/**/*'
26
26
 
27
-
28
27
  Style/WordArray:
29
28
  Enabled: false
@@ -1,11 +1,15 @@
1
1
  # This configuration was generated by
2
2
  # `rubocop --auto-gen-config`
3
- # on 2019-12-03 15:41:39 -0800 using RuboCop version 0.74.0.
3
+ # on 2020-01-27 18:06:55 -0800 using RuboCop version 0.77.0.
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
7
7
  # versions of RuboCop, may require this file to be generated again.
8
8
 
9
- # Offense count: 3
9
+ # Offense count: 2
10
10
  Metrics/AbcSize:
11
11
  Max: 34
12
+
13
+ # Offense count: 1
14
+ Metrics/CyclomaticComplexity:
15
+ Max: 7
@@ -3,12 +3,16 @@ cache: bundler
3
3
  rvm:
4
4
  - 2.5.3
5
5
  - 2.6.4
6
+ - 2.7.1
6
7
 
7
8
  env:
8
- - "RAILS_VERSION=5.2.3"
9
- - "RAILS_VERSION=6.0.0"
9
+ jobs:
10
+ - RAILS_VERSION=5.2.3
11
+ - RAILS_VERSION=6.0.0
12
+ global:
13
+ - CC_TEST_REPORTER_ID=02e8afad8d0b699828dd69b6f45b598e7317b2d9828ea23380c3a97113068a0c
10
14
 
11
- before_install: gem install bundler -v 2.0.2
15
+ before_install: gem install bundler -v 2.1.2
12
16
 
13
17
  before_script:
14
18
  - curl -L https://codeclimate.com/downloads/test-reporter/test-reporter-latest-linux-amd64 > ./cc-test-reporter
data/README.md CHANGED
@@ -37,7 +37,7 @@ end
37
37
  private
38
38
 
39
39
  def client
40
- @client ||= Preservation::Client.configure(url: Settings.preservation_catalog.url)
40
+ @client ||= Preservation::Client.configure(url: Settings.preservation_catalog.url, token: Settings.preservation_catalog.token)
41
41
  end
42
42
  ```
43
43
 
@@ -47,7 +47,7 @@ OR
47
47
  require 'preservation/client'
48
48
 
49
49
  def initialize
50
- Preservation::Client.configure(url: Settings.preservation_catalog.url)
50
+ Preservation::Client.configure(url: Settings.preservation_catalog.url, token: Settings.preservation_catalog.token)
51
51
  end
52
52
 
53
53
  def do_the_thing
@@ -55,7 +55,9 @@ def do_the_thing
55
55
  end
56
56
  ```
57
57
 
58
- Note that the client may **not** be used without first having been configured, and the `url` keyword is **required**.
58
+ Note that the client may **not** be used without first having been configured, and both the `url` and `token` keywords are **required**.
59
+
60
+ See https://github.com/sul-dlss/preservation_catalog#api for info on obtaining a valid API token.
59
61
 
60
62
  Note that the preservation service is behind a firewall.
61
63
 
@@ -86,6 +88,10 @@ Note that the preservation service is behind a firewall.
86
88
  - `client.objects.metadata(druid: 'oo000oo0000', filepath: 'identityMetadata.xml', version: '8')` - returns contents of identityMetadata.xml in version 8 of Moab object
87
89
  - `client.objects.signature_catalog('oo000oo0000')` - returns latest Moab::SignatureCatalog from Moab
88
90
 
91
+ ### Retrieve the primary moab storage location
92
+
93
+ - `client.objects.primary_moab_location(druid: 'ooo000oo0000')` - returns the path to the storage location for the primary moab
94
+
89
95
  ### Get difference information between passed contentMetadata.xml and files in the Moab
90
96
 
91
97
  - `client.objects.content_inventory_diff(druid: 'oo000oo0000', content_metadata: '<contentMetadata>...</contentMetadata>')` - returns Moab::FileInventoryDifference containing differences between passed content metadata and latest version for subset 'all'
@@ -17,16 +17,22 @@ module Preservation
17
17
  class Client
18
18
  class Error < StandardError; end
19
19
 
20
- # Error that is raised when the remote server returns a 404 Not Found
20
+ # Error raised when server returns 404 Not Found
21
21
  class NotFoundError < Error; end
22
22
 
23
- # Error that is raised when the remote server returns some unexpected response
24
- # e.g. 4xx or 5xx status
23
+ # Error raised when server returns 423 Locked
24
+ class LockedError < Error; end
25
+
26
+ # Error raised when server returns an unexpected response
27
+ # e.g., 4xx or 5xx status not otherwise handled
25
28
  class UnexpectedResponseError < Error; end
26
29
 
30
+ # Error raised when Faraday gem fails to connect, e.g., on SSL errors or
31
+ # timeouts
27
32
  class ConnectionFailedError < Error; end
28
33
 
29
34
  DEFAULT_API_VERSION = 'v1'
35
+ TOKEN_HEADER = 'Authorization'
30
36
 
31
37
  include Singleton
32
38
 
@@ -42,8 +48,10 @@ module Preservation
42
48
 
43
49
  class << self
44
50
  # @param [String] url
45
- def configure(url:)
51
+ # @param [String] token a bearer token for HTTP authentication
52
+ def configure(url:, token:)
46
53
  instance.url = url
54
+ instance.token = token
47
55
 
48
56
  # Force connection to be re-established when `.configure` is called
49
57
  instance.connection = nil
@@ -54,7 +62,7 @@ module Preservation
54
62
  delegate :objects, :update, to: :instance
55
63
  end
56
64
 
57
- attr_writer :url, :connection
65
+ attr_writer :url, :connection, :token
58
66
  delegate :update, to: :catalog
59
67
 
60
68
  private
@@ -63,6 +71,10 @@ module Preservation
63
71
  @url || raise(Error, 'url has not yet been configured')
64
72
  end
65
73
 
74
+ def token
75
+ @token || raise(Error, 'auth token has not been configured')
76
+ end
77
+
66
78
  def connection
67
79
  @connection ||= Faraday.new(url) do |builder|
68
80
  builder.use ErrorFaradayMiddleware
@@ -70,6 +82,7 @@ module Preservation
70
82
  builder.use Faraday::Response::RaiseError # raise exceptions on 40x, 50x responses
71
83
  builder.adapter Faraday.default_adapter
72
84
  builder.headers[:user_agent] = user_agent
85
+ builder.headers[TOKEN_HEADER] = "Bearer #{token}"
73
86
  end
74
87
  end
75
88
 
@@ -50,8 +50,9 @@ module Preservation
50
50
  # @param [String] druid - with or without prefix: 'druid:ab123cd4567' OR 'ab123cd4567'
51
51
  # @param [String] filepath - the path of the file relative to the moab content directory
52
52
  # @param [String] version - the version of the file requested (defaults to nil for latest version)
53
- def content(druid:, filepath:, version: nil)
54
- file(druid, 'content', filepath, version)
53
+ # @param [Proc] on_data a block, if provided is called to do streaming responses
54
+ def content(druid:, filepath:, version: nil, on_data: nil)
55
+ file(druid, 'content', filepath, version, on_data: on_data)
55
56
  end
56
57
 
57
58
  # retrieve a manifest file from a Moab object
@@ -70,6 +71,15 @@ module Preservation
70
71
  file(druid, 'metadata', filepath, version)
71
72
  end
72
73
 
74
+ # retrieve the storage location for the primary moab of the given druid
75
+ # @param [String] druid - with or without prefix: 'druid:ab123cd4567' or 'ab123cd4567'
76
+ # @return [String] the storage location of the primary moab for the given druid
77
+ # @raise [Preservation::Client::NotFoundError] when druid is not found
78
+ # @raise [Preservation::Client::LockedError] when druid is in locked state (not available for versioning)
79
+ def primary_moab_location(druid:)
80
+ get("objects/#{druid}/primary_moab_location", {}, on_data: nil)
81
+ end
82
+
73
83
  # convenience method for retrieving latest Moab::SignatureCatalog from a Moab object,
74
84
  # @param [String] druid - with or without prefix: 'druid:ab123cd4567' OR 'ab123cd4567'
75
85
  # @return [Moab::SignatureCatalog] the manifest of all files previously ingested
@@ -83,10 +93,11 @@ module Preservation
83
93
  # @param [String] druid - with or without prefix: 'druid:ab123cd4567' OR 'ab123cd4567'
84
94
  # @param [String] category - one of 'manifest', 'metadata' or 'content'
85
95
  # @param [String] filepath - the path of the file relative to the moab category directory
86
- # @param [String] version - the version of the file requested (defaults to nil for latest version)
96
+ # @param [String] version - the version of the file requested
97
+ # @param [Proc] on_data a block, if provided is called to do streaming responses
87
98
  # @return the retrieved file
88
- def file(druid, category, filepath, version = nil)
89
- get("objects/#{druid}/file", category: category, filepath: filepath, version: version)
99
+ def file(druid, category, filepath, version, on_data: nil)
100
+ get("objects/#{druid}/file", { category: category, filepath: filepath, version: version }, on_data: on_data)
90
101
  end
91
102
  end
92
103
  end
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Preservation
4
4
  class Client
5
- VERSION = '2.2.0'
5
+ VERSION = '3.3.0'
6
6
  end
7
7
  end
@@ -15,7 +15,7 @@ module Preservation
15
15
 
16
16
  # @param path [String] path to be appended to connection url (no leading slash)
17
17
  def get_json(path, object_id)
18
- req_url = api_version.present? ? "#{api_version}/#{path}" : path
18
+ req_url = "#{api_version}/#{path}"
19
19
  resp = connection.get do |req|
20
20
  req.url req_url
21
21
  req.headers['Content-Type'] = 'application/json'
@@ -25,46 +25,78 @@ module Preservation
25
25
 
26
26
  errmsg = ResponseErrorFormatter
27
27
  .format(response: resp, object_id: object_id, client_method_name: caller_locations.first.label)
28
- raise Preservation::Client::UnexpectedResponseError, errmsg
28
+ raise UnexpectedResponseError, errmsg
29
29
  rescue Faraday::ResourceNotFound
30
30
  errmsg = "#{object_id} not found in Preservation at #{connection.url_prefix}#{req_url}"
31
- raise Preservation::Client::NotFoundError, errmsg
31
+ raise NotFoundError, errmsg
32
32
  rescue Faraday::Error => e
33
33
  errmsg = "Preservation::Client.#{caller_locations.first.label} for #{object_id} " \
34
34
  "got #{e.response[:status]} from Preservation at #{req_url}: #{e.response[:body]}"
35
- raise Preservation::Client::UnexpectedResponseError, errmsg
35
+ raise UnexpectedResponseError, errmsg
36
36
  end
37
37
 
38
38
  # @param path [String] path to be appended to connection url (no leading slash)
39
- # @param params [Hash] optional params
40
- def get(path, params)
41
- http_response(:get, path, params)
39
+ # @param params [Hash] optional request parameters
40
+ # @param on_data [Proc] a callback to use when a streaming response is desired.
41
+ def get(path, params, on_data:)
42
+ return http_response(:get, path, params) unless on_data
43
+
44
+ connection.get("#{api_version}/#{path}", params) do |req|
45
+ req.options.on_data = on_data
46
+ end
42
47
  end
43
48
 
44
49
  # @param path [String] path to be appended to connection url (no leading slash)
45
- # @param params [Hash] optional params
50
+ # @param params [Hash] optional request parameters
46
51
  def post(path, params)
47
52
  http_response(:post, path, params)
48
53
  end
49
54
 
50
- # @param method [Symbol] :get or :post
51
55
  # @param path [String] path to be appended to connection url (no leading slash)
52
- # @param params [Hash] optional params
56
+ # @param params [Hash] optional request parameters
57
+ def patch(path, params)
58
+ http_response(:patch, path, params)
59
+ end
60
+
61
+ # @param path [String] path to be appended to connection url (no leading slash)
62
+ # @param params [Hash] optional request parameters
63
+ def put(path, params)
64
+ http_response(:put, path, params)
65
+ end
66
+
67
+ # @param path [String] path to be appended to connection url (no leading slash)
68
+ # @param params [Hash] optional request parameters
69
+ def delete(path, params)
70
+ http_response(:delete, path, params)
71
+ end
72
+
73
+ # @param method [Symbol] a symbol representing an HTTP method: :get, :post, :patch, :put, :delete
74
+ # @param path [String] path to be appended to connection url (no leading slash)
75
+ # @param params [Hash] optional request parameters
53
76
  def http_response(method, path, params)
54
- req_url = api_version.present? ? "#{api_version}/#{path}" : path
55
- resp = connection.send(method, req_url, params)
77
+ req_url = "#{api_version}/#{path}"
78
+ resp =
79
+ case method
80
+ when :delete, :get
81
+ connection.public_send(method, req_url, params)
82
+ when :patch, :post, :put
83
+ request_json = params.to_json if params&.any?
84
+ connection.public_send(method, req_url, request_json, 'Content-Type' => 'application/json')
85
+ end
86
+
56
87
  return resp.body if resp.success?
57
88
 
58
89
  errmsg = ResponseErrorFormatter.format(response: resp, client_method_name: caller_locations.first.label)
59
- raise Preservation::Client::UnexpectedResponseError, errmsg
90
+ raise UnexpectedResponseError, errmsg
60
91
  rescue Faraday::ResourceNotFound => e
61
92
  errmsg = "Preservation::Client.#{caller_locations.first.label} " \
62
93
  "got #{e.response[:status]} from Preservation at #{req_url}: #{e.response[:body]}"
63
- raise Preservation::Client::NotFoundError, errmsg
94
+ raise NotFoundError, errmsg
64
95
  rescue Faraday::Error => e
65
96
  errmsg = "Preservation::Client.#{caller_locations.first.label} " \
66
97
  "got #{e.response[:status]} from Preservation at #{req_url}: #{e.response[:body]}"
67
- raise Preservation::Client::UnexpectedResponseError, errmsg
98
+ exception_class = e.response[:status] == 423 ? LockedError : UnexpectedResponseError
99
+ raise exception_class, errmsg
68
100
  end
69
101
  end
70
102
  end
@@ -35,9 +35,9 @@ Gem::Specification.new do |spec|
35
35
 
36
36
  spec.add_development_dependency 'bundler', '~> 2.0'
37
37
  spec.add_development_dependency 'pry-byebug'
38
- spec.add_development_dependency 'rake', '~> 10.0'
38
+ spec.add_development_dependency 'rake', '>= 12.3.3'
39
39
  spec.add_development_dependency 'rspec', '~> 3.0'
40
40
  spec.add_development_dependency 'rubocop', '~> 0.77.0'
41
- spec.add_development_dependency 'simplecov'
41
+ spec.add_development_dependency 'simplecov', '~> 0.17.0' # For CodeClimate
42
42
  spec.add_development_dependency 'webmock'
43
43
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: preservation-client
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.2.0
4
+ version: 3.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Naomi Dushay
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2020-01-15 00:00:00.000000000 Z
11
+ date: 2020-07-02 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -110,16 +110,16 @@ dependencies:
110
110
  name: rake
111
111
  requirement: !ruby/object:Gem::Requirement
112
112
  requirements:
113
- - - "~>"
113
+ - - ">="
114
114
  - !ruby/object:Gem::Version
115
- version: '10.0'
115
+ version: 12.3.3
116
116
  type: :development
117
117
  prerelease: false
118
118
  version_requirements: !ruby/object:Gem::Requirement
119
119
  requirements:
120
- - - "~>"
120
+ - - ">="
121
121
  - !ruby/object:Gem::Version
122
- version: '10.0'
122
+ version: 12.3.3
123
123
  - !ruby/object:Gem::Dependency
124
124
  name: rspec
125
125
  requirement: !ruby/object:Gem::Requirement
@@ -152,16 +152,16 @@ dependencies:
152
152
  name: simplecov
153
153
  requirement: !ruby/object:Gem::Requirement
154
154
  requirements:
155
- - - ">="
155
+ - - "~>"
156
156
  - !ruby/object:Gem::Version
157
- version: '0'
157
+ version: 0.17.0
158
158
  type: :development
159
159
  prerelease: false
160
160
  version_requirements: !ruby/object:Gem::Requirement
161
161
  requirements:
162
- - - ">="
162
+ - - "~>"
163
163
  - !ruby/object:Gem::Version
164
- version: '0'
164
+ version: 0.17.0
165
165
  - !ruby/object:Gem::Dependency
166
166
  name: webmock
167
167
  requirement: !ruby/object:Gem::Requirement
@@ -225,7 +225,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
225
225
  - !ruby/object:Gem::Version
226
226
  version: '0'
227
227
  requirements: []
228
- rubygems_version: 3.0.3
228
+ rubygems_version: 3.0.6
229
229
  signing_key:
230
230
  specification_version: 4
231
231
  summary: A thin client for getting info from SDR preservation.