dpn-client 1.3.1

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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 55ea45ebadcb8d3e8af3c0a8597ec31f8bb49f23
4
+ data.tar.gz: ad3e2f35e5572ece674d8cb48c3e1adae5a3903c
5
+ SHA512:
6
+ metadata.gz: df13b7da524edb3e8bf7fd7e1d4b34ac4eef89b7d012b24d59c7b33e889afae7dbcc5e79809a13e94497670545ae3344cf613cef3ee103c5394f51db86d1aee0
7
+ data.tar.gz: d70510caeb2651423862d6a895b097a7cbc8fcbb312e733cf0b4505030f0d0a8afd5952cc59e3f7f0bc4ea26bf9e6c29b619d52ff7351166cdcc8ff28a0f1f51
data/.gitignore ADDED
@@ -0,0 +1,44 @@
1
+ # Ignore bundler config.
2
+ /.bundle
3
+
4
+ # Ignore the default SQLite database.
5
+ /db/*.sqlite3
6
+ /db/*.sqlite3-journal
7
+
8
+ # Ignore all logfiles and tempfiles.
9
+ /log/*
10
+ !/log/.keep
11
+ /tmp
12
+
13
+ # Rubymine
14
+ /.idea
15
+
16
+ *.rbc
17
+ capybara-*.html
18
+ .rspec
19
+ /log
20
+ /tmp
21
+ /db/*.sqlite3
22
+ /db/*.sqlite3-journal
23
+ /public/system
24
+ /coverage/
25
+ /spec/tmp
26
+ **.orig
27
+ rerun.txt
28
+ pickle-email-*.html
29
+
30
+
31
+ ## Environment normalisation:
32
+ /.bundle
33
+ /vendor/bundle
34
+
35
+ # unless supporting rvm < 1.11.0 or doing something fancy, ignore this:
36
+ .rvmrc
37
+
38
+
39
+ # Ignore pow environment settings
40
+ .powenv
41
+
42
+ # Yard Documentation
43
+ .yardoc
44
+ doc/
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --color
2
+ --require spec_helper
data/.travis.yml ADDED
@@ -0,0 +1,19 @@
1
+ language: ruby
2
+ rvm:
3
+ - 2.2.1
4
+ before_install: gem install bundler -v 1.10.3
5
+ script: bundle exec rspec
6
+ addons:
7
+ code_climate:
8
+ repo_token: f22be735856cba5796a856b993f0d38a7655bf2eb75f0329701455327de301d2
9
+ notifications:
10
+ slack:
11
+ secure: >
12
+ TRWr6LiDI3mXdGdecKNtOIw7/znPNFzUbmf8hCy1SZg1/41QkMTmDFOKQJY2q8BexwuUEr1cBnYF/EJtwlqQ3bR6Rytr
13
+ chjmtgwlCBue90c1Rc/jt6W1FjPXPgWTQ1jki1fZcETLGvAeD2dzUxXTQfX3EJZ1rZ8Bi3TdbBKEM/h7PXHKbuA9Q+p+
14
+ xzXDP2up31z/nIaMjcOdAGtE2zng9hhEGw7NzYFRNS8eZ8kMUhw/6ED+BeefDXNr8HMyzOyMrBhOQjqogB4KPFS1uaAE
15
+ 8K5QQt/IqNF1bDq3pvatAILC2RWsPQOTjWkKt2uQK2pj0Rbm0uh8rRi9rKCpIjd6BHKKx+lut4Ma5H2Sy80Iltksf/AH
16
+ UlHI/6ZH4hE7LkQCdw3JmpTx5AHCI4OBo+JBRxSu3i4VfcFhxQrcuLDleib5NEha9KYVlRRM8y3+A9tP+5zrFEGi4DGH
17
+ oW8X7xUCJFoXh7Jsec/PgndLkdyPdq/bFpG8LPXdbKgWuhNXSqiRxYO/8gRZYRfhcBw2qGgsCyravSZeQIAaClk7RfKw
18
+ hBWqhrDAvW/tK05YaaLAC8Dt4WlGhx5Xa7TGfPzIsiZlLT8F27JXSIyQpg96I5RGzlmSoCmkcjwWYeum/6gzDDdogMrP
19
+ 4iTKoj18Oo/FyOPxo/aOeF/FfBBAT42jBVYl5g8=
data/Gemfile ADDED
@@ -0,0 +1,9 @@
1
+ # Copyright (c) 2015 The Regents of the University of Michigan.
2
+ # All Rights Reserved.
3
+ # Licensed according to the terms of the Revised BSD License
4
+ # See LICENSE.md for details.
5
+
6
+ source 'https://rubygems.org'
7
+
8
+ # Specify your gem's dependencies in dpn-client.gemspec
9
+ gemspec
data/Gemfile.lock ADDED
@@ -0,0 +1,57 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ dpn-client (1.3.1)
5
+ httpclient (~> 2.6.0.1)
6
+
7
+ GEM
8
+ remote: https://rubygems.org/
9
+ specs:
10
+ addressable (2.3.8)
11
+ codeclimate-test-reporter (0.4.8)
12
+ simplecov (>= 0.7.1, < 1.0.0)
13
+ crack (0.4.2)
14
+ safe_yaml (~> 1.0.0)
15
+ diff-lcs (1.2.5)
16
+ docile (1.1.5)
17
+ httpclient (2.6.0.1)
18
+ json (1.8.3)
19
+ rake (10.4.2)
20
+ rspec (3.3.0)
21
+ rspec-core (~> 3.3.0)
22
+ rspec-expectations (~> 3.3.0)
23
+ rspec-mocks (~> 3.3.0)
24
+ rspec-core (3.3.2)
25
+ rspec-support (~> 3.3.0)
26
+ rspec-expectations (3.3.1)
27
+ diff-lcs (>= 1.2.0, < 2.0)
28
+ rspec-support (~> 3.3.0)
29
+ rspec-mocks (3.3.2)
30
+ diff-lcs (>= 1.2.0, < 2.0)
31
+ rspec-support (~> 3.3.0)
32
+ rspec-support (3.3.0)
33
+ safe_yaml (1.0.4)
34
+ simplecov (0.10.0)
35
+ docile (~> 1.1.0)
36
+ json (~> 1.8)
37
+ simplecov-html (~> 0.10.0)
38
+ simplecov-html (0.10.0)
39
+ webmock (1.21.0)
40
+ addressable (>= 2.3.6)
41
+ crack (>= 0.3.2)
42
+ yard (0.8.7.6)
43
+
44
+ PLATFORMS
45
+ ruby
46
+
47
+ DEPENDENCIES
48
+ bundler (~> 1.10)
49
+ codeclimate-test-reporter
50
+ dpn-client!
51
+ rake (~> 10.0)
52
+ rspec
53
+ webmock
54
+ yard
55
+
56
+ BUNDLED WITH
57
+ 1.11.2
data/LICENSE.md ADDED
@@ -0,0 +1,27 @@
1
+ Copyright (c) 2015, The Regents of the University of Michigan.
2
+ All rights reserved.
3
+
4
+ Redistribution and use in source and binary forms, with or without
5
+ modification, are permitted provided that the following conditions are
6
+ met:
7
+
8
+ * Redistributions of source code must retain the above copyright
9
+ notice, this list of conditions and the following disclaimer.
10
+ * Redistributions in binary form must reproduce the above copyright
11
+ notice, this list of conditions and the following disclaimer in the
12
+ documentation and/or other materials provided with the distribution.
13
+ * Neither the name of the The University of Michigan nor the
14
+ names of its contributors may be used to endorse or promote products
15
+ derived from this software without specific prior written permission.
16
+
17
+ THIS SOFTWARE IS PROVIDED BY THE REGENTS OF THE UNIVERSITY OF MICHIGAN AND
18
+ CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT
19
+ NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
20
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OF THE
21
+ UNIVERSITY OF MICHIGAN BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
23
+ TO,PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
24
+ PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
25
+ LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
26
+ NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
27
+ EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
data/README.md ADDED
@@ -0,0 +1,56 @@
1
+ # DPN::Client
2
+
3
+ [![Build Status](https://travis-ci.org/dpn-admin/dpn-client.svg?branch=master)](https://travis-ci.org/dpn-admin/dpn-client)
4
+ [![Code Climate](https://codeclimate.com/github/dpn-admin/dpn-client/badges/gpa.svg)](https://codeclimate.com/github/dpn-admin/dpn-client)
5
+ [![Test Coverage](https://codeclimate.com/github/dpn-admin/dpn-client/badges/coverage.svg)](https://codeclimate.com/github/dpn-admin/dpn-client/coverage)
6
+
7
+ ## Installation
8
+
9
+ Add this line to your application's Gemfile:
10
+
11
+ ```ruby
12
+ gem 'dpn-client', :git => 'https://github.com/dpn-admin/dpn-client.git'
13
+
14
+ ```
15
+
16
+ And then execute:
17
+
18
+ $ bundle install
19
+
20
+ ## Usage
21
+
22
+ See the
23
+ [yard documentation](http://www.rubydoc.info/github/dpn-admin/dpn-client/master/DPN/Client/Agent)
24
+ for more info, but the basics are thus:
25
+
26
+ ```ruby
27
+ client = DPN::Client.client.configure do |c|
28
+ c.api_root = "https://hathitrust.org/api_root"
29
+ c.auth_token = "auth_token_for_hathi"
30
+ end
31
+
32
+ client.bags(page_size: 25, admin_node: "hathi") do |bag|
33
+ bag.inspect # this block is optional
34
+ end
35
+
36
+ resp = client.create_bag(some_bag_hash)
37
+ if resp.success?
38
+ some_bag_hash[:status] = resp[:status]
39
+ end
40
+ ```
41
+
42
+ Essentially, single-endpoint operations always return a Response object,
43
+ but you can treat this object as just a hash, if you want. Index operations
44
+ return an array of hashes.
45
+
46
+ You can pass a block to any operation. For single-endpoints, the response will
47
+ be passed to the block. For indexes, each individual result will be passed
48
+ successively to the block. Using blocks is recommended.
49
+
50
+ ## License
51
+
52
+ Copyright (c) 2015 The Regents of the University of Michigan.
53
+ All Rights Reserved.
54
+ Licensed according to the terms of the Revised BSD License.
55
+ See LICENSE.md for details.
56
+
data/Rakefile ADDED
@@ -0,0 +1,11 @@
1
+ # Copyright (c) 2015 The Regents of the University of Michigan.
2
+ # All Rights Reserved.
3
+ # Licensed according to the terms of the Revised BSD License
4
+ # See LICENSE.md for details.
5
+
6
+ require "bundler/gem_tasks"
7
+ require "rspec/core/rake_task"
8
+
9
+ RSpec::Core::RakeTask.new(:spec)
10
+
11
+ task :default => :spec
@@ -0,0 +1,35 @@
1
+ # coding: utf-8
2
+
3
+ # Copyright (c) 2015 The Regents of the University of Michigan.
4
+ # All Rights Reserved.
5
+ # Licensed according to the terms of the Revised BSD License
6
+ # See LICENSE.md for details.
7
+
8
+ lib = File.expand_path('../lib', __FILE__)
9
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
10
+ require 'dpn/client/version'
11
+
12
+ Gem::Specification.new do |spec|
13
+ spec.name = "dpn-client"
14
+ spec.version = DPN::Client::VERSION
15
+ spec.authors = ["Bryan Hockey"]
16
+ spec.email = ["bhock@umich.edu"]
17
+
18
+ spec.summary = %q{A client to process the DPN api.}
19
+ spec.description = %q{A client to process the DPN api.}
20
+ spec.homepage = "https://github.com/dpn-admin/dpn-client"
21
+
22
+ spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
23
+ spec.bindir = "exe"
24
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
25
+ spec.require_paths = ["lib"]
26
+
27
+ spec.add_runtime_dependency "httpclient", "~> 2.6.0.1"
28
+
29
+ spec.add_development_dependency "bundler", "~> 1.10"
30
+ spec.add_development_dependency "rake", "~> 10.0"
31
+ spec.add_development_dependency "rspec"
32
+ spec.add_development_dependency "yard"
33
+ spec.add_development_dependency "webmock"
34
+ spec.add_development_dependency "codeclimate-test-reporter"
35
+ end
@@ -0,0 +1,84 @@
1
+ # Copyright (c) 2015 The Regents of the University of Michigan.
2
+ # All Rights Reserved.
3
+ # Licensed according to the terms of the Revised BSD License
4
+ # See LICENSE.md for details.
5
+
6
+ module DPN
7
+ module Client
8
+ class Agent
9
+ module Bag
10
+
11
+ # Get the bags index
12
+ # @param [Hash] options
13
+ # @option options [Fixnum] :page_size (25) Number of entries per page
14
+ # @option options [DateTime String] :before (nil) Include only entries last modified
15
+ # before this date.
16
+ # @option options [DateTime String] :after (nil) Include only entries last modified
17
+ # after this date.
18
+ # @option options [String] :admin_node (nil) Namespace of the admin_node of the bag.
19
+ # @option options [String] :member (nil) The UUID of the member that owns or is vested
20
+ # in this bag.
21
+ # @option options [String] :bag_type (nil) One of 'D', 'R', 'I', for data, rights, and
22
+ # interpretive, respectively.
23
+ # @yield [Response] Optional block to process individual bag.
24
+ # @return [Array<Hash>] Array of all bag data. Generated and returned
25
+ # only if no block is passed.
26
+ def bags(options = {page_size: 25}, &block)
27
+ [:after, :before].each do |date_field|
28
+ if options[date_field].is_a?(DateTime)
29
+ options[date_field] = options[:date_field].new_offset(0).strftime(DPN::Client.time_format)
30
+ end
31
+ end
32
+
33
+ return paginate_each "/bag/", options, options[:page_size], &block
34
+ end
35
+
36
+
37
+ # @overload bag(uuid, &block)
38
+ # Get a specific bag
39
+ # @param [String] uuid UUID of the bag.
40
+ # @yield [Response]
41
+ # @return [Response]
42
+ # @overload bag(options)
43
+ # Alias for #bags
44
+ # @return [Array<Hash>]
45
+ # @see #bags
46
+ def bag(uuid = nil, options = {page_size: 25}, &block)
47
+ if uuid
48
+ get "/bag/#{uuid}/", nil, &block
49
+ else
50
+ bags(options, &block)
51
+ end
52
+ end
53
+
54
+
55
+ # Create a bag
56
+ # @param [Hash] bag Body of the bag
57
+ # @yield [Response]
58
+ # @return [Response]
59
+ def create_bag(bag, &block)
60
+ post "/bag", bag, &block
61
+ end
62
+
63
+
64
+ # Update a bag
65
+ # @param [Hash] bag Body of the bag
66
+ # @yield [Response]
67
+ # @return [Response]
68
+ def update_bag(bag, &block)
69
+ put "/bag/#{bag[:uuid]}/", bag, &block
70
+ end
71
+
72
+
73
+ # Delete a bag
74
+ # @param [String] uuid UUID of the bag
75
+ # @yield [Response]
76
+ # @return [Response]
77
+ def delete_bag(uuid, &block)
78
+ delete "/bag/#{uuid}/", &block
79
+ end
80
+
81
+ end
82
+ end
83
+ end
84
+ end
@@ -0,0 +1,80 @@
1
+ # Copyright (c) 2015 The Regents of the University of Michigan.
2
+ # All Rights Reserved.
3
+ # Licensed according to the terms of the Revised BSD License
4
+ # See LICENSE.md for details.
5
+
6
+ require "logger"
7
+
8
+ module DPN
9
+ module Client
10
+ class Agent
11
+ module Configuration
12
+ @@keys = [
13
+ :api_root, :auth_token,
14
+ :per_page, :user_agent,
15
+ :logger
16
+ ]
17
+
18
+ @@defaults = {
19
+ api_root: nil.freeze,
20
+ auth_token: nil.freeze,
21
+ per_page: 25.freeze,
22
+ user_agent: "dpn-client".freeze
23
+ }.freeze
24
+
25
+ attr_accessor :api_root, :auth_token,
26
+ :per_page, :user_agent
27
+ attr_writer :logger
28
+
29
+
30
+ # Apply the options hash to the configuration
31
+ def configure(options_hash = {})
32
+ keys.each do |key|
33
+ if options_hash[key]
34
+ instance_variable_set(:"@#{key}", options_hash[key])
35
+ end
36
+ end
37
+ if block_given?
38
+ yield self
39
+ end
40
+ return self
41
+ end
42
+
43
+
44
+ # Reset to default values
45
+ def reset
46
+ keys.each do |key|
47
+ instance_variable_set(:"@#{key}", defaults[key])
48
+ self
49
+ end
50
+ end
51
+ alias_method :setup, :reset
52
+
53
+ def base_url
54
+ File.join(@api_root, "api-v#{DPN::Client.api_version}")
55
+ end
56
+
57
+ def logger
58
+ @logger ||= NullLogger.new
59
+ end
60
+
61
+ protected
62
+
63
+ class NullLogger < Logger
64
+ def initialize(*args); end
65
+ def add(*args, &block); end
66
+ end
67
+
68
+ def defaults
69
+ @@defaults
70
+ end
71
+
72
+ def keys
73
+ @@keys
74
+ end
75
+
76
+
77
+ end
78
+ end
79
+ end
80
+ end
@@ -0,0 +1,183 @@
1
+ # Copyright (c) 2015 The Regents of the University of Michigan.
2
+ # All Rights Reserved.
3
+ # Licensed according to the terms of the Revised BSD License
4
+ # See LICENSE.md for details.
5
+
6
+ require "uri"
7
+ require "json"
8
+ require "httpclient"
9
+ require "csv" # stringify_nested_arrays!
10
+ require "dpn/client/response"
11
+
12
+ module DPN
13
+ module Client
14
+ class Agent
15
+ module Connection
16
+
17
+ # Make a GET request
18
+ # @param url [String] The path, relative to base_url
19
+ # @param query [Hash] Optional query parameters.
20
+ # @yield [Response] Optional block that takes the
21
+ # response object as a parameter.
22
+ # @return [Response]
23
+ def get(url, query = nil, &block)
24
+ request :get, url, query, nil, &block
25
+ end
26
+
27
+
28
+ # Make a POST request
29
+ # @param url [String] The path, relative to base_url
30
+ # @param body [String] The message body.
31
+ # @yield [Response] Optional block that takes the
32
+ # response object as a parameter.
33
+ # @return [Response]
34
+ def post(url, body, &block )
35
+ request :post, url, nil, body, &block
36
+ end
37
+
38
+
39
+ # Make a PUT request
40
+ # @param url [String] The path, relative to base_url
41
+ # @param body [String] The message body.
42
+ # @yield [Response] Optional block that takes the
43
+ # response object as a parameter.
44
+ # @return [Response]
45
+ def put(url, body, &block)
46
+ request :put, url, nil, body, &block
47
+ end
48
+
49
+
50
+ # Make a DELETE request
51
+ # @param url [String] The path, relative to base_url
52
+ # @yield [Response] Optional block that takes the
53
+ # response object as a parameter.
54
+ # @return [Response]
55
+ def delete(url, &block)
56
+ request :delete, url, nil, nil, &block
57
+ end
58
+
59
+
60
+ # Make a one or more GET requests, fetching the next
61
+ # page of results one page at a time, so long as the
62
+ # response indicates there is another page.
63
+ # @param url [String] The path, relative to base_url
64
+ # @param query [Hash] Optional query parameters.
65
+ # @param page_size [Fixnum] The number of results to request
66
+ # from each page.
67
+ # @yield [Response] Mandatory block that takes a page
68
+ # of results (the response object) as a parameter.
69
+ # The results will be available via response[:results].
70
+ def paginate(url, query, page_size, &block)
71
+ raise ArgumentError, "Must pass a block" unless block_given?
72
+
73
+ query ||= {}
74
+ query = query.merge({ :page_size => page_size, :page => 1})
75
+
76
+ response = get(url, query) # pass an empty block so we can call the block manually on :results
77
+ yield response
78
+ while response.success? && response[:next] && response[:results].empty? == false
79
+ query[:page] += 1
80
+ query[:page_size] = response[:results].size # in case the server specifies a different page size
81
+ response = get(url, query) {}
82
+ yield response
83
+ end
84
+ end
85
+
86
+
87
+ # Make a one or more GET requests, fetching the next
88
+ # page of results one page at a time, so long as the
89
+ # response indicates there is another page. This method
90
+ # yields each individual result, wrapped in a [Response].
91
+ # @param url [String] The path, relative to base_url
92
+ # @param query [Hash] Optional query parameters.
93
+ # @param page_size [Fixnum] The number of results to request
94
+ # from each page.
95
+ # @yield [Response] Mandatory block that takes each individual
96
+ # result wrapped in a response object as a parameter. If a
97
+ # request is unsuccessful, the failed response is yielded.
98
+ def paginate_each(url, query, page_size, &block)
99
+ raise ArgumentError, "Must pass a block" unless block_given?
100
+ paginate(url, query, (page_size || 25)) do |response|
101
+ if response.success?
102
+ logger.info("Response has #{response[:results].size} results.")
103
+ response[:results].each do |result|
104
+ yield Response.from_data(response.status, result)
105
+ end
106
+ else
107
+ yield response
108
+ end
109
+ end
110
+ end
111
+
112
+
113
+ protected
114
+
115
+ def request(method, url, query, body, &block)
116
+ url, extra_query = parse_url(url)
117
+ query ||= {}
118
+ options = {
119
+ query: stringify_nested_arrays!(query.merge(extra_query)),
120
+ body: body.to_json,
121
+ follow_redirect: true
122
+ }
123
+
124
+ logger.info("Sending #{method.upcase}: #{File.join(base_url, fix_url(url))} #{options} ")
125
+ raw_response = connection.request method, fix_url(url), options
126
+ logger.debug("Received #{raw_response.inspect}")
127
+ response = DPN::Client::Response.new(raw_response)
128
+ logger.info("Received #{response.status}")
129
+ if block_given?
130
+ yield response
131
+ end
132
+
133
+ return response
134
+ end
135
+
136
+
137
+ def parse_url(raw_url)
138
+ url, query = raw_url.split("?", 2)
139
+ url = File.join url, ""
140
+ if query
141
+ query = URI::decode_www_form(query).to_h
142
+ else
143
+ query = {}
144
+ end
145
+ return url, query
146
+ end
147
+
148
+
149
+ def connection
150
+ @connection ||= ::HTTPClient.new({
151
+ agent_name: user_agent,
152
+ base_url: base_url,
153
+ default_header: {
154
+ "Content-Type" => "application/json",
155
+ "Authorization" => "Token #{auth_token}"
156
+ },
157
+ force_basic_auth: true
158
+ })
159
+ end
160
+
161
+
162
+ def fix_url(url)
163
+ File.join url, "/"
164
+ end
165
+
166
+
167
+ # Convert array values to csv
168
+ # Only goes one level deep.
169
+ # @param [Hash] hash
170
+ # @return [Hash]
171
+ def stringify_nested_arrays!(hash)
172
+ hash.keys.each do |key|
173
+ if hash[key].kind_of?(Array)
174
+ hash[key] = hash[key].to_csv.strip
175
+ end
176
+ end
177
+ return hash
178
+ end
179
+
180
+ end
181
+ end
182
+ end
183
+ end
@@ -0,0 +1,88 @@
1
+ # Copyright (c) 2015 The Regents of the University of Michigan.
2
+ # All Rights Reserved.
3
+ # Licensed according to the terms of the Revised BSD License
4
+ # See LICENSE.md for details.
5
+
6
+ module DPN
7
+ module Client
8
+ class Agent
9
+
10
+ # Operations on the member resource.
11
+ module Member
12
+
13
+ # Get the members index
14
+ # @param [Hash] options
15
+ # @option options [Fixnum] :page_size (25) Number of members per page
16
+ # @yield [Response] Optional block to process each individual member.
17
+ # @return [Array<Hash>] Array of all member data. Generated and returned
18
+ # only if no block is passed.
19
+ def members(options = {page_size: 25}, &block)
20
+ return paginate_each "/member/", options, options[:page_size], &block
21
+ end
22
+
23
+
24
+ # @overload member(uuid, &block)
25
+ # Get a specific member
26
+ # @param [String] uuid UUIDv4 of the member.
27
+ # @yield [Response] Optional block to process the response.
28
+ # @return [Response]
29
+ # @overload member(options, &block)
30
+ # Alias for #members
31
+ # @return [Array<Hash>]
32
+ # @see #members
33
+ def member(uuid = nil, options = {page_size: 25}, &block)
34
+ if uuid
35
+ get "/member/#{fix_uuid(uuid)}/", nil, &block
36
+ else
37
+ members(options, &block)
38
+ end
39
+ end
40
+
41
+
42
+ # Create a member
43
+ # @param [Hash] member Body of the member
44
+ # @yield [Response]
45
+ # @return [Response]
46
+ def create_member(member, &block)
47
+ post "/member/", member, &block
48
+ end
49
+
50
+
51
+ # Update a member
52
+ # @param [Hash] member Body of the member
53
+ # @yield [Response]
54
+ # @return [Response]
55
+ def update_member(member, &block)
56
+ put "/member/#{fix_uuid(member[:uuid])}/", member, &block
57
+ end
58
+
59
+
60
+ # Delete a member
61
+ # @param [String] uuid UUIDv4 of the member.
62
+ # @yield [Response]
63
+ # @return [Response]
64
+ def delete_member(uuid, &block)
65
+ delete "/member/#{fix_uuid(uuid)}/", &block
66
+ end
67
+
68
+
69
+ private
70
+ # Add dashes to a uuid if they are missing
71
+ def fix_uuid(uuid)
72
+ if uuid && uuid.size == 32
73
+ unless uuid.include?("-")
74
+ uuid.insert(8, "-") # 9th, 14th, 19th and 24th
75
+ uuid.insert(13, "-")
76
+ uuid.insert(18, "-")
77
+ uuid.insert(23, "-")
78
+ end
79
+ end
80
+ uuid.downcase
81
+ end
82
+
83
+
84
+ end
85
+
86
+ end
87
+ end
88
+ end
@@ -0,0 +1,71 @@
1
+ # Copyright (c) 2015 The Regents of the University of Michigan.
2
+ # All Rights Reserved.
3
+ # Licensed according to the terms of the Revised BSD License
4
+ # See LICENSE.md for details.
5
+
6
+ module DPN
7
+ module Client
8
+ class Agent
9
+
10
+ # Operations on the node resource.
11
+ module Node
12
+
13
+ # Get the nodes index
14
+ # @param [Hash] options
15
+ # @option options [Fixnum] :page_size (25) Number of nodes per page
16
+ # @yield [Response] Optional block to process each individual node.
17
+ # @return [Array<Hash>] Array of all node data. Generated and returned
18
+ # only if no block is passed.
19
+ def nodes(options = {page_size: 25}, &block)
20
+ return paginate_each "/node/", options, options[:page_size], &block
21
+ end
22
+
23
+
24
+ # @overload node(namespace, &block)
25
+ # Get a specific node
26
+ # @param [String] namespace Namespace of the node.
27
+ # @yield [Response] Optional block to process the response.
28
+ # @return [Response]
29
+ # @overload node(options, &block)
30
+ # Alias for #nodes
31
+ # @return [Array<Hash>]
32
+ # @see #nodes
33
+ def node(namespace = nil, options = {page_size: 25}, &block)
34
+ if namespace
35
+ get "/node/#{namespace}/", nil, &block
36
+ else
37
+ nodes(options, &block)
38
+ end
39
+ end
40
+
41
+
42
+ # Create a node
43
+ # @param [Hash] node Body of the node
44
+ # @yield [Response]
45
+ # @return [Response]
46
+ def create_node(node, &block)
47
+ post "/node/", node, &block
48
+ end
49
+
50
+
51
+ # Update a node
52
+ # @param [Hash] node Body of the node
53
+ # @yield [Response]
54
+ # @return [Response]
55
+ def update_node(node, &block)
56
+ put "/node/#{node[:namespace]}/", node, &block
57
+ end
58
+
59
+
60
+ # Delete a node
61
+ # @param [String] namespace Namespace of the node.
62
+ # @yield [Response]
63
+ # @return [Response]
64
+ def delete_node(namespace, &block)
65
+ delete "/node/#{namespace}/", &block
66
+ end
67
+
68
+ end
69
+ end
70
+ end
71
+ end
@@ -0,0 +1,83 @@
1
+ # Copyright (c) 2015 The Regents of the University of Michigan.
2
+ # All Rights Reserved.
3
+ # Licensed according to the terms of the Revised BSD License
4
+ # See LICENSE.md for details.
5
+
6
+ module DPN
7
+ module Client
8
+ class Agent
9
+ module Replicate
10
+
11
+ # Get the replication request index
12
+ # @param [Hash] options
13
+ # @option options [Fixnum] :page_size (25) Number of entries per page
14
+ # @option options [DateTime,String] :after (nil) Include only entries last modified
15
+ # after this date. Takes a properly formatted string, or a datetime.
16
+ # @option options [String] uuid (nil) Filter by a specific bag's UUID.
17
+ # @option options [String] status (nil) Filter by status.
18
+ # @option options [Boolean] fixity_accept (nil) Filter by the value of fixity_accept.
19
+ # @option options [Boolean] bag_valid (nil) Filter by the value of bag_valid.
20
+ # @option options [String] :from_node (nil) Namespace of the from_node of the bag.
21
+ # @option options [String] :to_node (nil) Namespace of the to_node of the bag.
22
+ # @option options [String] :order_by (nil) Comma-separated list of strings to order the
23
+ # result by. Accepted values are 'created_at' and 'updated_at'
24
+ # @yield [Response] Optional block to process each individual replication.
25
+ # @return [Array<Hash>] Array of all replication data. Generated and returned
26
+ # only if no block is passed.
27
+ def replications(options = {page_size: 25}, &block)
28
+ if options[:after].is_a?(DateTime)
29
+ options[:after] = options[:after].new_offset(0).strftime(DPN::Client.time_format)
30
+ end
31
+
32
+ return paginate_each "/replicate/", options, options[:page_size], &block
33
+ end
34
+
35
+
36
+ # @overload replicate(replication_id, &block)
37
+ # Get a specific replication request.
38
+ # @param [String] replication_id
39
+ # @yield [Response]
40
+ # @return [Response]
41
+ # @overload replicate(options, &block)
42
+ # Alias for #replications
43
+ # @return [Array<Hash>]
44
+ # @see #replications
45
+ def replicate(replication_id = nil, options = {page_size: 25}, &block)
46
+ if replication_id
47
+ get "/replicate/#{replication_id}/", nil, &block
48
+ else
49
+ replications(options, &block)
50
+ end
51
+ end
52
+
53
+
54
+ # Create a replication request
55
+ # @param [Hash] request Body of the replication request
56
+ # @yield [Response]
57
+ # @return [Response]
58
+ def create_replication(request, &block)
59
+ post "/replicate", request, &block
60
+ end
61
+
62
+
63
+ # Update a replication request
64
+ # @param [Hash] request Body of the replication request
65
+ # @yield [Response]
66
+ # @return [Response]
67
+ def update_replication(request, &block)
68
+ put "/replicate/#{request[:replication_id]}/", request, &block
69
+ end
70
+
71
+
72
+ # Delete a replication request
73
+ # @param [String] replication_id The replication_id of the replication request
74
+ # @yield [Response]
75
+ # @return [Response]
76
+ def delete_replication(replication_id, &block)
77
+ delete "/replicate/#{replication_id}/", &block
78
+ end
79
+
80
+ end
81
+ end
82
+ end
83
+ end
@@ -0,0 +1,30 @@
1
+ # Copyright (c) 2015 The Regents of the University of Michigan.
2
+ # All Rights Reserved.
3
+ # Licensed according to the terms of the Revised BSD License
4
+ # See LICENSE.md for details.
5
+
6
+ require "dpn/client/agent/configuration"
7
+ require "dpn/client/agent/connection"
8
+ require "dpn/client/agent/node"
9
+ require "dpn/client/agent/bag"
10
+ require "dpn/client/agent/replicate"
11
+ require "dpn/client/agent/member"
12
+
13
+ module DPN
14
+ module Client
15
+ class Agent
16
+ include DPN::Client::Agent::Configuration
17
+ include DPN::Client::Agent::Connection
18
+
19
+ include DPN::Client::Agent::Node
20
+ include DPN::Client::Agent::Bag
21
+ include DPN::Client::Agent::Replicate
22
+ include DPN::Client::Agent::Member
23
+
24
+ def initialize(options = {})
25
+ self.configure(options)
26
+ end
27
+
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,86 @@
1
+ # Copyright (c) 2015 The Regents of the University of Michigan.
2
+ # All Rights Reserved.
3
+ # Licensed according to the terms of the Revised BSD License
4
+ # See LICENSE.md for details.
5
+
6
+ require "httpclient"
7
+ require "json"
8
+
9
+ module DPN
10
+ module Client
11
+ class Response
12
+
13
+ attr_reader :status, :body
14
+
15
+ def initialize(httpclient_response = nil)
16
+ if httpclient_response
17
+ load_from_response!(httpclient_response)
18
+ end
19
+ end
20
+
21
+
22
+ # Manually create a response.
23
+ def self.from_data(status, body)
24
+ self.new.load_from_data!(status, body)
25
+ end
26
+
27
+ attr_reader :status, :body
28
+
29
+
30
+ def json
31
+ @cached_json ||= @body.to_json
32
+ end
33
+ alias_method :to_json, :json
34
+ alias_method :to_s, :json
35
+
36
+
37
+ def ok?
38
+ [ 200, 201, 202, 203, 204, 205, 206, 207, 208, 226].include?(@status)
39
+ end
40
+ alias_method :success?, :ok?
41
+
42
+
43
+ def keys
44
+ @body.keys
45
+ end
46
+
47
+
48
+ def [](key)
49
+ @body[key.to_sym]
50
+ end
51
+
52
+
53
+ def load_from_data!(status, body)
54
+ @body = body
55
+ @status = status
56
+ return self
57
+ end
58
+
59
+ def load_from_response!(httpclient_message_response)
60
+ raw_body = httpclient_message_response.body
61
+ @status = httpclient_message_response.header.status_code
62
+ begin
63
+ @body = JSON.parse(raw_body, symbolize_names: true)
64
+ @cached_json = raw_body
65
+ rescue JSON::ParserError
66
+ @body = {
67
+ status: @status,
68
+ parsed: nil,
69
+ raw: raw_body
70
+ }
71
+ @cached_json = @body.to_json
72
+ if success? # It wasn't actually successful
73
+ @status = 999
74
+ end
75
+ end
76
+ return self
77
+ end
78
+
79
+ def ==(other)
80
+ status == other.status && body == other.body
81
+ end
82
+ alias_method :eql?, :==
83
+
84
+ end
85
+ end
86
+ end
@@ -0,0 +1,10 @@
1
+ # Copyright (c) 2015 The Regents of the University of Michigan.
2
+ # All Rights Reserved.
3
+ # Licensed according to the terms of the Revised BSD License
4
+ # See LICENSE.md for details.
5
+
6
+ module DPN
7
+ module Client
8
+ VERSION = "1.3.1"
9
+ end
10
+ end
data/lib/dpn/client.rb ADDED
@@ -0,0 +1,30 @@
1
+ # Copyright (c) 2015 The Regents of the University of Michigan.
2
+ # All Rights Reserved.
3
+ # Licensed according to the terms of the Revised BSD License
4
+ # See LICENSE.md for details.
5
+
6
+ require "dpn/client/agent"
7
+ require "dpn/client/response"
8
+ require "dpn/client/version"
9
+
10
+ module DPN
11
+ module Client
12
+
13
+ # Get the api version, based on the major version of this library.
14
+ def self.api_version
15
+ DPN::Client::VERSION.split(".")[0]
16
+ end
17
+
18
+
19
+ def self.time_format
20
+ "%Y-%m-%dT%H:%M:%SZ"
21
+ end
22
+
23
+
24
+ def self.client(options = {})
25
+ return ::DPN::Client::Agent.new options
26
+ end
27
+
28
+
29
+ end
30
+ end
metadata ADDED
@@ -0,0 +1,161 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: dpn-client
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.3.1
5
+ platform: ruby
6
+ authors:
7
+ - Bryan Hockey
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2016-08-12 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: httpclient
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: 2.6.0.1
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: 2.6.0.1
27
+ - !ruby/object:Gem::Dependency
28
+ name: bundler
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '1.10'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '1.10'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rake
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '10.0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '10.0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rspec
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: yard
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: webmock
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ - !ruby/object:Gem::Dependency
98
+ name: codeclimate-test-reporter
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ">="
102
+ - !ruby/object:Gem::Version
103
+ version: '0'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ">="
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
111
+ description: A client to process the DPN api.
112
+ email:
113
+ - bhock@umich.edu
114
+ executables: []
115
+ extensions: []
116
+ extra_rdoc_files: []
117
+ files:
118
+ - ".gitignore"
119
+ - ".rspec"
120
+ - ".travis.yml"
121
+ - Gemfile
122
+ - Gemfile.lock
123
+ - LICENSE.md
124
+ - README.md
125
+ - Rakefile
126
+ - dpn-client.gemspec
127
+ - lib/dpn/client.rb
128
+ - lib/dpn/client/agent.rb
129
+ - lib/dpn/client/agent/bag.rb
130
+ - lib/dpn/client/agent/configuration.rb
131
+ - lib/dpn/client/agent/connection.rb
132
+ - lib/dpn/client/agent/member.rb
133
+ - lib/dpn/client/agent/node.rb
134
+ - lib/dpn/client/agent/replicate.rb
135
+ - lib/dpn/client/response.rb
136
+ - lib/dpn/client/version.rb
137
+ homepage: https://github.com/dpn-admin/dpn-client
138
+ licenses: []
139
+ metadata: {}
140
+ post_install_message:
141
+ rdoc_options: []
142
+ require_paths:
143
+ - lib
144
+ required_ruby_version: !ruby/object:Gem::Requirement
145
+ requirements:
146
+ - - ">="
147
+ - !ruby/object:Gem::Version
148
+ version: '0'
149
+ required_rubygems_version: !ruby/object:Gem::Requirement
150
+ requirements:
151
+ - - ">="
152
+ - !ruby/object:Gem::Version
153
+ version: '0'
154
+ requirements: []
155
+ rubyforge_project:
156
+ rubygems_version: 2.4.5.1
157
+ signing_key:
158
+ specification_version: 4
159
+ summary: A client to process the DPN api.
160
+ test_files: []
161
+ has_rdoc: