skn_utils 5.6.0 → 5.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/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
|