dpn-client 1.3.1

Sign up to get free protection for your applications and to get access to all the features.
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: