skn_utils 5.6.0 → 5.7.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +14 -1
- data/lib/skn_utils/concurrent_jobs.rb +11 -2
- data/lib/skn_utils/configurable.rb +36 -0
- data/lib/skn_utils/job_commands.rb +14 -9
- data/lib/skn_utils/version.rb +1 -1
- data/spec/lib/skn_utils/concurrent_jobs_spec.rb +6 -4
- data/spec/spec_helper.rb +1 -0
- data/spec/support/xml_matchers.rb +121 -0
- metadata +4 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: '01339ef95f65037a1a9951185b69a8ee2fb9160c'
|
4
|
+
data.tar.gz: fd2bd2b6b3ae66f17b268f6f23abd2d1a8c0e69b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: cb6089054a1e97e7e21d03df41c6622e253487fee45e9799217c8cff211dcb8ca63c39776e15c89876edd88e22a9a22c099a133328bb5786801a0d53ce682924
|
7
|
+
data.tar.gz: 288b6c71971afd3f0b84b5524d0c96ceec28b7db93a8183ea6c9e31e0a00a974b0eb11f8acbcda03f7b3d0b5160de6e244ec78b7fca13d43f75a63951765e72c
|
data/README.md
CHANGED
@@ -8,6 +8,7 @@ dependencies, to augment the development of Ruby applications. Examples of thes
|
|
8
8
|
utilities in action can be found in my related projects `SknServices`, `SknWebApp`,
|
9
9
|
and `SknBase`.
|
10
10
|
|
11
|
+
* Most classes are standalone modules, or cleary documented, and can be copy/pasted into your project.
|
11
12
|
* The exchange or handoff of values between objects is addressed via the `NestedResults`
|
12
13
|
class which implements dot-notation and nesting over a concurrent hash: A ruby Hash can
|
13
14
|
use any valid ruby object as a key or value.
|
@@ -31,7 +32,8 @@ classname, symbol, or string as needed
|
|
31
32
|
* `ConcurrentJobs` is a feature implemented to allow concurrent/multi-threaded execution of jobs. The included
|
32
33
|
companion classes focus on HTTP GET,PUT,POST, and DELETE jobs as an example of how to use the `ConcurrentJobs` feature.
|
33
34
|
|
34
|
-
All classes and modules have RSpec test coverage (90+) of their originally intended
|
35
|
+
All classes and modules have RSpec test coverage (90+) of their originally intended
|
36
|
+
use-cases.
|
35
37
|
|
36
38
|
|
37
39
|
### Available Classes
|
@@ -65,8 +67,19 @@ All classes and modules have RSpec test coverage (90+) of their originally inten
|
|
65
67
|
* SknUtils.as_human_size()
|
66
68
|
* SknUtils.duration(start_time=nil)
|
67
69
|
|
70
|
+
### Available RSpec Helpers
|
71
|
+
* spec/support/xml_matchers.rb
|
72
|
+
* expect(bundle).to have_xpath('//witnesses/witness/role')
|
73
|
+
* expect(bundle).to have_nodes('//witnesses/witness/role', 3)
|
74
|
+
* expect(bundle).to match_xpath('//lossInformation/date', "2020-01-28")
|
75
|
+
|
68
76
|
|
69
77
|
## History
|
78
|
+
2/3/2030 V5.7.0
|
79
|
+
Added
|
80
|
+
* RSpec XML_Matchers to spec/support folders
|
81
|
+
* Update ConcurrentJobs JobCommands to support HTTP Headers
|
82
|
+
|
70
83
|
2/24/2019 V5.5.0
|
71
84
|
Added
|
72
85
|
* ConcurrentJobs feature set
|
@@ -15,6 +15,8 @@ module SknUtils
|
|
15
15
|
|
16
16
|
def call
|
17
17
|
@blk.call
|
18
|
+
rescue => ex
|
19
|
+
SknFailure.(ex.class.name, { cause: ex.message, backtrace: ex.backtrace[0..8]})
|
18
20
|
end
|
19
21
|
end
|
20
22
|
|
@@ -25,6 +27,8 @@ module SknUtils
|
|
25
27
|
|
26
28
|
def call
|
27
29
|
@blk.value
|
30
|
+
rescue => ex
|
31
|
+
SknFailure.(ex.class.name, { cause: ex.message, backtrace: ex.backtrace[0..8]})
|
28
32
|
end
|
29
33
|
end
|
30
34
|
|
@@ -50,7 +54,7 @@ module SknUtils
|
|
50
54
|
def self.call(command, callable)
|
51
55
|
callable.call(command)
|
52
56
|
rescue => ex
|
53
|
-
SknFailure.(ex.class.name,
|
57
|
+
SknFailure.(ex.class.name, { cause: ex.message, backtrace: ex.backtrace[0..8]})
|
54
58
|
end
|
55
59
|
end
|
56
60
|
|
@@ -85,7 +89,12 @@ module SknUtils
|
|
85
89
|
def render_jobs
|
86
90
|
stime = SknUtils.duration
|
87
91
|
merged = @workers.each_with_object([]) do |worker, acc|
|
88
|
-
|
92
|
+
begin
|
93
|
+
res = worker.call
|
94
|
+
acc.push( res.nil? ? SknFailure.("Unknown", {cause: "Nil Return Value to render Jobs", backtrace: []}) : res )
|
95
|
+
rescue => ex
|
96
|
+
acc.push SknFailure.(ex.class.name, { cause: ex.message, backtrace: ex.backtrace[0..8]})
|
97
|
+
end
|
89
98
|
end
|
90
99
|
@elapsed_time_string = SknUtils.duration(stime)
|
91
100
|
Result.new(merged)
|
@@ -59,6 +59,10 @@ module SknUtils
|
|
59
59
|
# - env = string value from RACK_ENV
|
60
60
|
# - registry = SknRegistry instance
|
61
61
|
# - logger = Assigned Logger instance
|
62
|
+
# - romDB = var for Rom-DB if used or Any Platform Database
|
63
|
+
# - metadata = platform metadata container
|
64
|
+
# - userdata = user area
|
65
|
+
# - metrics = platform metrics container
|
62
66
|
# #with(*user_attrs, enable_root: true|false) - defaults to enable of Main Class Attrs
|
63
67
|
# ##
|
64
68
|
# User-Defined Attrs
|
@@ -131,6 +135,38 @@ module SknUtils
|
|
131
135
|
def logger=(obj)
|
132
136
|
@__logger = obj
|
133
137
|
end
|
138
|
+
|
139
|
+
# Any Platform Database
|
140
|
+
def romDB
|
141
|
+
@__db ||= nil
|
142
|
+
end
|
143
|
+
def romDB(obj)
|
144
|
+
@__db = obj
|
145
|
+
end
|
146
|
+
|
147
|
+
# Maybe Platform Metadata
|
148
|
+
def metadata
|
149
|
+
@__metadata ||= nil
|
150
|
+
end
|
151
|
+
def metadata=(obj)
|
152
|
+
@__metadata = obj
|
153
|
+
end
|
154
|
+
|
155
|
+
# Userdata container for any use
|
156
|
+
def userdata
|
157
|
+
@__userdata ||= nil
|
158
|
+
end
|
159
|
+
def userdata=(obj)
|
160
|
+
@__userdata = obj
|
161
|
+
end
|
162
|
+
|
163
|
+
# Metrics container for any use
|
164
|
+
def metrics
|
165
|
+
@__metrics ||= nil
|
166
|
+
end
|
167
|
+
def metrics=(obj)
|
168
|
+
@__metrics = obj
|
169
|
+
end
|
134
170
|
end
|
135
171
|
end
|
136
172
|
|
@@ -7,7 +7,7 @@ module SknUtils
|
|
7
7
|
# #################################################
|
8
8
|
#
|
9
9
|
class CommandJSONPost
|
10
|
-
def self.call(options) # {full_url:,username:,userpass:,payload:}
|
10
|
+
def self.call(options) # {full_url:,username:,userpass:,payload:,headers:}
|
11
11
|
new(options)
|
12
12
|
end
|
13
13
|
|
@@ -20,7 +20,7 @@ module SknUtils
|
|
20
20
|
end
|
21
21
|
|
22
22
|
def request
|
23
|
-
req = Net::HTTP::Post.new(uri.path) # Generate HTTPRequest object
|
23
|
+
req = @_headers.nil? ? Net::HTTP::Post.new(uri.path) : Net::HTTP::Post.new(uri.path, @_headers) # Generate HTTPRequest object
|
24
24
|
req.basic_auth(@_username, @_userpass) if credentials?
|
25
25
|
req.content_type = 'application/json'
|
26
26
|
req.body = formatted_data
|
@@ -32,6 +32,7 @@ module SknUtils
|
|
32
32
|
def initialize(opts={})
|
33
33
|
@_username = opts[:username]
|
34
34
|
@_userpass = opts[:userpass]
|
35
|
+
@_headers = opts[:headers]
|
35
36
|
@_uri = URI.parse( opts[:full_url])
|
36
37
|
@_data = opts[:payload]
|
37
38
|
end
|
@@ -49,7 +50,7 @@ module SknUtils
|
|
49
50
|
# #################################################
|
50
51
|
#
|
51
52
|
class CommandFORMPost
|
52
|
-
def self.call(options) # {full_url:,username:,userpass:,payload:}
|
53
|
+
def self.call(options) # {full_url:,username:,userpass:,payload:,headers:}
|
53
54
|
new(options)
|
54
55
|
end
|
55
56
|
|
@@ -62,7 +63,7 @@ module SknUtils
|
|
62
63
|
end
|
63
64
|
|
64
65
|
def request
|
65
|
-
req = Net::HTTP::Post.new(uri.path) # Generate HTTPRequest object
|
66
|
+
req = @_headers.nil? ? Net::HTTP::Post.new(uri.path) : Net::HTTP::Post.new(uri.path, @_headers) # Generate HTTPRequest object
|
66
67
|
req.basic_auth(@_username, @_userpass) if credentials?
|
67
68
|
req.content_type = 'application/x-www-form-urlencoded'
|
68
69
|
req.set_form_data(formatted_data)
|
@@ -74,6 +75,7 @@ module SknUtils
|
|
74
75
|
def initialize(opts={})
|
75
76
|
@_username = opts[:username]
|
76
77
|
@_userpass = opts[:userpass]
|
78
|
+
@_headers = opts[:headers]
|
77
79
|
@_uri = URI.parse( opts[:full_url])
|
78
80
|
@_data = opts[:payload]
|
79
81
|
end
|
@@ -91,7 +93,7 @@ module SknUtils
|
|
91
93
|
# #################################################
|
92
94
|
#
|
93
95
|
class CommandJSONGet
|
94
|
-
def self.call(options) # {full_url:,username:,userpass:}
|
96
|
+
def self.call(options) # {full_url:,username:,userpass:,headers:}
|
95
97
|
new(options)
|
96
98
|
end
|
97
99
|
|
@@ -104,7 +106,7 @@ module SknUtils
|
|
104
106
|
end
|
105
107
|
|
106
108
|
def request
|
107
|
-
req = Net::HTTP::Get.new(uri.request_uri)
|
109
|
+
req = @_headers.nil? ? Net::HTTP::Get.new(uri.request_uri) : Net::HTTP::Get.new(uri.request_uri, @_headers) # Generate HTTPRequest object
|
108
110
|
req.basic_auth(@_username, @_userpass) if credentials?
|
109
111
|
req
|
110
112
|
end
|
@@ -114,6 +116,7 @@ module SknUtils
|
|
114
116
|
def initialize(opts={})
|
115
117
|
@_username = opts[:username]
|
116
118
|
@_userpass = opts[:userpass]
|
119
|
+
@_headers = opts[:headers]
|
117
120
|
@_uri = URI.parse( opts[:full_url])
|
118
121
|
end
|
119
122
|
|
@@ -126,7 +129,7 @@ module SknUtils
|
|
126
129
|
# #################################################
|
127
130
|
#
|
128
131
|
class CommandJSONPut
|
129
|
-
def self.call(options) # {full_url:,username:,userpass:,payload:}
|
132
|
+
def self.call(options) # {full_url:,username:,userpass:,payload:,headers:}
|
130
133
|
new(options)
|
131
134
|
end
|
132
135
|
|
@@ -139,7 +142,7 @@ module SknUtils
|
|
139
142
|
end
|
140
143
|
|
141
144
|
def request
|
142
|
-
req = Net::HTTP::Put.new(uri.path) # Generate HTTPRequest object
|
145
|
+
req = @_headers.nil? ? Net::HTTP::Put.new(uri.path) : Net::HTTP::Put.new(uri.path, @_headers) # Generate HTTPRequest object
|
143
146
|
req.basic_auth(@_username, @_userpass) if credentials?
|
144
147
|
req.content_type = 'application/json'
|
145
148
|
req.body = formatted_data
|
@@ -151,6 +154,7 @@ module SknUtils
|
|
151
154
|
def initialize(opts={})
|
152
155
|
@_username = opts[:username]
|
153
156
|
@_userpass = opts[:userpass]
|
157
|
+
@_headers = opts[:headers]
|
154
158
|
@_uri = URI.parse( opts[:full_url])
|
155
159
|
@_data = opts[:payload]
|
156
160
|
end
|
@@ -181,7 +185,7 @@ module SknUtils
|
|
181
185
|
end
|
182
186
|
|
183
187
|
def request
|
184
|
-
req = Net::HTTP::Delete.new(uri.request_uri)
|
188
|
+
req = @_headers.nil? ? Net::HTTP::Delete.new(uri.request_uri) : Net::HTTP::Delete.new(uri.request_uri, @_headers) # Generate HTTPRequest object
|
185
189
|
req.basic_auth(@_username, @_userpass) if credentials?
|
186
190
|
req
|
187
191
|
end
|
@@ -191,6 +195,7 @@ module SknUtils
|
|
191
195
|
def initialize(opts={})
|
192
196
|
@_username = opts[:username]
|
193
197
|
@_userpass = opts[:userpass]
|
198
|
+
@_headers = opts[:headers]
|
194
199
|
@_uri = URI.parse( opts[:full_url])
|
195
200
|
end
|
196
201
|
|
data/lib/skn_utils/version.rb
CHANGED
@@ -7,7 +7,7 @@ describe SknUtils::ConcurrentJobs, 'Run Multiple Jobs' do
|
|
7
7
|
|
8
8
|
let(:commands) {
|
9
9
|
[
|
10
|
-
SknUtils::CommandJSONPost.call(full_url: "http://example.com/posts", payload: {one: 1}),
|
10
|
+
SknUtils::CommandJSONPost.call(full_url: "http://example.com/posts", payload: {one: 1}, headers: {'my-header'=> "header-value"}),
|
11
11
|
SknUtils::CommandFORMPost.call(full_url: "http://example.com/posts", payload: {one: 1}),
|
12
12
|
SknUtils::CommandJSONGet.call(full_url: "http://example.com/posts/1"),
|
13
13
|
SknUtils::CommandJSONPut.call(full_url: "http://example.com/posts", payload: {one: 1}),
|
@@ -199,10 +199,12 @@ describe SknUtils::ConcurrentJobs, 'Run Multiple Jobs' do
|
|
199
199
|
expect(result).to be_a(SknUtils::Result)
|
200
200
|
expect(result.success?).to be false
|
201
201
|
expect(result.values.size).to eq(commands.size)
|
202
|
+
expect(result.values.last).to be_a(SknSuccess)
|
202
203
|
expect(result.values[3].value).to eq("NameError")
|
203
|
-
expect(result.values[
|
204
|
-
expect(result.values[
|
205
|
-
expect(result.values[0]).to
|
204
|
+
expect(result.values[2]).to be_a(SknFailure)
|
205
|
+
expect(result.values[1]).to be_a(SknFailure)
|
206
|
+
expect(result.values[0]).to be_a(SknFailure)
|
207
|
+
expect(result.values[0].value).to eq("Unknown")
|
206
208
|
end
|
207
209
|
end
|
208
210
|
|
data/spec/spec_helper.rb
CHANGED
@@ -0,0 +1,121 @@
|
|
1
|
+
# ##
|
2
|
+
# File: <spec>/xml_matchers.rb
|
3
|
+
#
|
4
|
+
# Refs: https://github.com/sparklemotion/nokogiri/wiki/Cheat-sheet
|
5
|
+
# https://arjanvandergaag.nl/blog/rspec-matchers.html
|
6
|
+
# http://blog.wolfman.com/articles/2008/1/2/xpath-matchers-for-rspec
|
7
|
+
# https://semaphoreci.com/community/tutorials/how-to-use-custom-rspec-matchers-to-specify-behaviour
|
8
|
+
#
|
9
|
+
|
10
|
+
# Useage
|
11
|
+
# ----------------------------------------------------------------------
|
12
|
+
# expect(bundle).to have_xpath('//witnesses/witness/role')
|
13
|
+
# expect(bundle).to have_nodes('//witnesses/witness/role', 3)
|
14
|
+
# expect(bundle).to match_xpath('//lossInformation/date', "2020-01-28")
|
15
|
+
|
16
|
+
# check if the xpath exists one or more times
|
17
|
+
class HaveXpath
|
18
|
+
def initialize(xpath)
|
19
|
+
@xpath = xpath
|
20
|
+
end
|
21
|
+
|
22
|
+
def matches?(str)
|
23
|
+
@str = str
|
24
|
+
xml_document.xpath(@xpath).any?
|
25
|
+
end
|
26
|
+
|
27
|
+
def failure_message
|
28
|
+
"Expected xpath #{@xpath.inspect} to match in:\n" + pretty_printed_xml
|
29
|
+
end
|
30
|
+
|
31
|
+
def failure_message_when_negated
|
32
|
+
"Expected xpath #{@xpath.inspect} not to match in:\n" + pretty_printed_xml
|
33
|
+
end
|
34
|
+
|
35
|
+
private
|
36
|
+
|
37
|
+
def pretty_printed_xml
|
38
|
+
xml_document.to_xml(indent: 2)
|
39
|
+
end
|
40
|
+
|
41
|
+
def xml_document
|
42
|
+
@xml_document ||= Nokogiri::XML(@str)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def have_xpath(*xpath)
|
47
|
+
HaveXpath.new(*xpath)
|
48
|
+
end
|
49
|
+
|
50
|
+
# check if the xpath has the specified value
|
51
|
+
# value is a string and there must be a single result to match its
|
52
|
+
# equality against
|
53
|
+
class MatchXpath
|
54
|
+
def initialize(xpath, val)
|
55
|
+
@xpath = xpath
|
56
|
+
@val= val
|
57
|
+
end
|
58
|
+
|
59
|
+
def matches?(response)
|
60
|
+
@response = response
|
61
|
+
doc = response.is_a?(Nokogiri::XML::Document) ? response : Nokogiri::XML(@response)
|
62
|
+
ok= true
|
63
|
+
doc.xpath(@xpath).each do |e|
|
64
|
+
@actual_val= case e
|
65
|
+
when Nokogiri::XML::Attr
|
66
|
+
e.to_s
|
67
|
+
when Nokogiri::XML::Element
|
68
|
+
e.text
|
69
|
+
else
|
70
|
+
e.to_s
|
71
|
+
end
|
72
|
+
return false unless @val == @actual_val
|
73
|
+
end
|
74
|
+
return ok
|
75
|
+
end
|
76
|
+
|
77
|
+
def failure_message
|
78
|
+
"The xpath #{@xpath} did not have the value '#{@val}' \n It was '#{@actual_val}'"
|
79
|
+
end
|
80
|
+
|
81
|
+
def failure_message_when_negated
|
82
|
+
"The xpath #{@xpath} has the value '#{@val}' \n Was expected not to match '#{@actual_val}'"
|
83
|
+
end
|
84
|
+
|
85
|
+
def description
|
86
|
+
"match the xpath expression #{@xpath} with #{@val}"
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
def match_xpath(xpath, val)
|
91
|
+
MatchXpath.new(xpath, val)
|
92
|
+
end
|
93
|
+
|
94
|
+
# checks if the given xpath occurs num times
|
95
|
+
class HaveNodes #:nodoc:
|
96
|
+
def initialize(xpath, num)
|
97
|
+
@xpath= xpath
|
98
|
+
@num = num
|
99
|
+
end
|
100
|
+
|
101
|
+
def matches?(response)
|
102
|
+
@response = response
|
103
|
+
doc = response.is_a?(Nokogiri::XML::Document) ? response : Nokogiri::XML(@response)
|
104
|
+
matches = doc.xpath(@xpath)
|
105
|
+
@num_found= matches.size
|
106
|
+
@num_found == @num
|
107
|
+
end
|
108
|
+
|
109
|
+
def failure_message
|
110
|
+
"Did not find expected number of nodes #{@num} in xpath #{@xpath} \n Found #{@num_found}"
|
111
|
+
end
|
112
|
+
|
113
|
+
def description
|
114
|
+
"match the number of nodes #{@num}"
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
def have_nodes(xpath, num)
|
119
|
+
HaveNodes.new(xpath, num)
|
120
|
+
end
|
121
|
+
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: skn_utils
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 5.
|
4
|
+
version: 5.7.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- James Scott Jr
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2020-02-03 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: deep_merge
|
@@ -242,6 +242,7 @@ files:
|
|
242
242
|
- spec/lib/skn_utils/wrappers_spec.rb
|
243
243
|
- spec/spec_helper.rb
|
244
244
|
- spec/support/configurables.rb
|
245
|
+
- spec/support/xml_matchers.rb
|
245
246
|
homepage: https://github.com/skoona/skn_utils
|
246
247
|
licenses:
|
247
248
|
- MIT
|
@@ -293,3 +294,4 @@ test_files:
|
|
293
294
|
- spec/lib/skn_utils/wrappers_spec.rb
|
294
295
|
- spec/spec_helper.rb
|
295
296
|
- spec/support/configurables.rb
|
297
|
+
- spec/support/xml_matchers.rb
|