arborist-webservice 0.0.1.pre20180815100446 → 0.0.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 +4 -4
- checksums.yaml.gz.sig +2 -0
- data.tar.gz.sig +0 -0
- data/ChangeLog +45 -2
- data/History.md +1 -1
- data/README.md +4 -4
- data/Rakefile +7 -7
- data/lib/arborist/monitor/webservice.rb +54 -15
- data/lib/arborist/node/webservice.rb +25 -10
- data/lib/arborist/webservice/constants.rb +76 -0
- data/spec/arborist/monitor/webservice_spec.rb +169 -0
- data/spec/arborist/node/webservice_spec.rb +59 -9
- data/spec/arborist/webservice_spec.rb +27 -0
- data/spec/spec_helper.rb +11 -0
- metadata +13 -10
- metadata.gz.sig +0 -0
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 3d364d3021e618267b924682c39b011d365aa486c56a37c13842a23d71e4b4c6
|
|
4
|
+
data.tar.gz: b6028b714764befd0d89372432d6936037eaa0b5bd54d10f735c537903fbeb38
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: f7b5ff725bd2e08a5737e5c2d0ceb8dfdff21aec1d30633cf08fa0c310ca82c01f1524c3bdb2ce472843ca002536311cbf1eca65d1e087bd2487ecfb156741ee
|
|
7
|
+
data.tar.gz: 1c023a87365bc5551a3ccb3f054e5c15a671f8bff6df0e66e88b8f83232d08524d0f4f07a94a791c19a033b67d8ff71eef437ecf730a4dbebefc08773472fcf4
|
checksums.yaml.gz.sig
ADDED
data.tar.gz.sig
ADDED
|
Binary file
|
data/ChangeLog
CHANGED
|
@@ -1,12 +1,55 @@
|
|
|
1
|
+
2018-08-30 Michael Granger <ged@FaerieMUD.org>
|
|
2
|
+
|
|
3
|
+
* History.md, arborist-webservice.gemspec:
|
|
4
|
+
Update history and the gemspec
|
|
5
|
+
[65c19b823a1b] [tip]
|
|
6
|
+
|
|
7
|
+
* README.md, lib/arborist/monitor/webservice.rb,
|
|
8
|
+
lib/arborist/node/webservice.rb,
|
|
9
|
+
lib/arborist/webservice/constants.rb,
|
|
10
|
+
spec/arborist/monitor/webservice_spec.rb,
|
|
11
|
+
spec/arborist/node/webservice_spec.rb, spec/spec_helper.rb:
|
|
12
|
+
Finish up tests, flesh out settings and config for less-common
|
|
13
|
+
cases.
|
|
14
|
+
[53ff11b5ccf6]
|
|
15
|
+
|
|
16
|
+
2018-08-29 Michael Granger <ged@FaerieMUD.org>
|
|
17
|
+
|
|
18
|
+
* lib/arborist/monitor/webservice.rb,
|
|
19
|
+
spec/arborist/monitor/webservice_spec.rb:
|
|
20
|
+
Rename 'HTML' monitor callback to 'HTTP'
|
|
21
|
+
[c970fb9b5ccf] [github/master]
|
|
22
|
+
|
|
1
23
|
2018-08-15 Michael Granger <ged@FaerieMUD.org>
|
|
2
24
|
|
|
25
|
+
* README.md, Rakefile, arborist-webservice.gemspec:
|
|
26
|
+
Fix some documentation issues.
|
|
27
|
+
[1e226b9d9561]
|
|
28
|
+
|
|
29
|
+
* .hgignore:
|
|
30
|
+
Ignore built gems
|
|
31
|
+
[a580ef4ff61b]
|
|
32
|
+
|
|
33
|
+
* Rakefile, arborist-webservice.gemspec:
|
|
34
|
+
Update dependencies.
|
|
35
|
+
[c08c1e0bbb70]
|
|
36
|
+
|
|
37
|
+
* .gems, .hgignore, ChangeLog, Manifest.txt, Rakefile, arborist-
|
|
38
|
+
webservice.gemspec, lib/arborist/monitor/webservice.rb,
|
|
39
|
+
lib/arborist/webservice.rb, lib/arborist/webservice/connection.rb,
|
|
40
|
+
lib/arborist/webservice/constants.rb,
|
|
41
|
+
spec/arborist/monitor/webservice_spec.rb,
|
|
42
|
+
spec/arborist/node/webservice_spec.rb:
|
|
43
|
+
Switch to Typhoeus for batched parallel requests
|
|
44
|
+
[59e390021ccd]
|
|
45
|
+
|
|
3
46
|
* .gems, Rakefile, lib/arborist/monitor/webservice.rb,
|
|
4
47
|
lib/arborist/node/webservice.rb, lib/arborist/webservice.rb,
|
|
5
48
|
lib/arborist/webservice/connection.rb,
|
|
6
49
|
lib/arborist/webservice/constants.rb,
|
|
7
50
|
lib/arborist/webservice/monkeypatches.rb:
|
|
8
51
|
Checkpoint commit before switching to Typhoeus
|
|
9
|
-
[d2e9ed791434]
|
|
52
|
+
[d2e9ed791434]
|
|
10
53
|
|
|
11
54
|
2018-08-01 Mahlon E. Smith <mahlon@martini.nu>
|
|
12
55
|
|
|
@@ -18,7 +61,7 @@
|
|
|
18
61
|
|
|
19
62
|
* README.md:
|
|
20
63
|
Fix incorrect URLs in the README
|
|
21
|
-
[7bdc40158b25]
|
|
64
|
+
[7bdc40158b25]
|
|
22
65
|
|
|
23
66
|
* .gems, .pryrc, .ruby-gemset, .ruby-version, .rvm.gems, .rvmrc,
|
|
24
67
|
ChangeLog, History.md, LICENSE.txt, Manifest.txt, README.md,
|
data/History.md
CHANGED
data/README.md
CHANGED
|
@@ -30,7 +30,7 @@ The simplest example is an unauthenticated REST service running on port 80:
|
|
|
30
30
|
end
|
|
31
31
|
|
|
32
32
|
This adds a `webservice` child node to the containing host with an identifier of
|
|
33
|
-
`
|
|
33
|
+
`example-webserver-api-vi`.
|
|
34
34
|
|
|
35
35
|
The simplest monitor setup to monitor that service might look something like:
|
|
36
36
|
|
|
@@ -38,9 +38,9 @@ The simplest monitor setup to monitor that service might look something like:
|
|
|
38
38
|
#encoding: utf-8
|
|
39
39
|
|
|
40
40
|
require 'arborist/monitor/webservice'
|
|
41
|
-
Arborist::Monitor::Webservice::
|
|
41
|
+
Arborist::Monitor::Webservice::HTTP.default
|
|
42
42
|
|
|
43
|
-
This would check that an
|
|
43
|
+
This would check that an HEAD HTTP request to `http://api.example.com/v1/heartbeat` responds with a 2xx status code.
|
|
44
44
|
|
|
45
45
|
|
|
46
46
|
## Prerequisites
|
|
@@ -69,7 +69,7 @@ and generate the API documentation.
|
|
|
69
69
|
|
|
70
70
|
## License
|
|
71
71
|
|
|
72
|
-
Copyright (c) 2016, Michael Granger
|
|
72
|
+
Copyright (c) 2016-2018, Michael Granger
|
|
73
73
|
All rights reserved.
|
|
74
74
|
|
|
75
75
|
Redistribution and use in source and binary forms, with or without
|
data/Rakefile
CHANGED
|
@@ -29,13 +29,13 @@ hoespec = Hoe.spec 'arborist-webservice' do |spec|
|
|
|
29
29
|
|
|
30
30
|
spec.developer 'Michael Granger', 'ged@FaerieMUD.org'
|
|
31
31
|
|
|
32
|
-
spec.dependency 'arborist', '~> 0'
|
|
33
|
-
spec.dependency 'loggability', '~> 0.
|
|
32
|
+
spec.dependency 'arborist', '~> 0.2'
|
|
33
|
+
spec.dependency 'loggability', '~> 0.14'
|
|
34
34
|
spec.dependency 'typhoeus', '~> 1.3'
|
|
35
35
|
|
|
36
|
-
spec.dependency 'hoe-deveiate', '~> 0.
|
|
36
|
+
spec.dependency 'hoe-deveiate', '~> 0.10', :developer
|
|
37
37
|
spec.dependency 'simplecov', '~> 0.7', :developer
|
|
38
|
-
spec.dependency 'rdoc-generator-fivefish', '~> 0.
|
|
38
|
+
spec.dependency 'rdoc-generator-fivefish', '~> 0.4', :developer
|
|
39
39
|
|
|
40
40
|
spec.hg_sign_tags = true if spec.respond_to?( :hg_sign_tags= )
|
|
41
41
|
spec.check_history_on_release = true if spec.respond_to?( :check_history_on_release= )
|
|
@@ -69,11 +69,11 @@ if File.directory?( '.hg' )
|
|
|
69
69
|
|
|
70
70
|
Rake::Task[ 'docs' ].clear
|
|
71
71
|
RDoc::Task.new( 'docs' ) do |rdoc|
|
|
72
|
-
rdoc.main = "README.
|
|
72
|
+
rdoc.main = "README.md"
|
|
73
73
|
rdoc.markup = 'markdown'
|
|
74
|
-
rdoc.rdoc_files.include( "*.rdoc", "ChangeLog", "lib/**/*.rb" )
|
|
74
|
+
rdoc.rdoc_files.include( "*.rdoc", "*.md", "ChangeLog", "lib/**/*.rb" )
|
|
75
75
|
rdoc.generator = :fivefish
|
|
76
|
-
rdoc.title = 'Webservice Node Type for Arborist'
|
|
76
|
+
rdoc.title = 'Webservice Node Type and Monitor for Arborist'
|
|
77
77
|
rdoc.rdoc_dir = 'doc'
|
|
78
78
|
end
|
|
79
79
|
end
|
|
@@ -34,12 +34,20 @@ module Arborist::Monitor::Webservice
|
|
|
34
34
|
Integer( val )
|
|
35
35
|
end
|
|
36
36
|
|
|
37
|
+
##
|
|
38
|
+
# Whether or not to enable SSL peer certificate verification by default. The
|
|
39
|
+
# value is either `1` to enable it by default, or `0` to disable it by default.
|
|
40
|
+
# The config of each invidual webservice node can override this.
|
|
41
|
+
setting :ssl_verifypeer, default: 1 do |val|
|
|
42
|
+
Integer( val ).nonzero? ? 1 : 0
|
|
43
|
+
end
|
|
44
|
+
|
|
37
45
|
end
|
|
38
46
|
|
|
39
47
|
|
|
40
48
|
|
|
41
|
-
# Arborist
|
|
42
|
-
class
|
|
49
|
+
# Arborist HTTP web service monitor logic
|
|
50
|
+
class HTTP
|
|
43
51
|
extend Loggability
|
|
44
52
|
include Arborist::Webservice::Constants
|
|
45
53
|
|
|
@@ -53,7 +61,7 @@ module Arborist::Monitor::Webservice
|
|
|
53
61
|
}
|
|
54
62
|
|
|
55
63
|
# The array of node properites used by this monitor
|
|
56
|
-
NODE_PROPERTIES = %i[ uri http_method body body_mimetype ].freeze
|
|
64
|
+
NODE_PROPERTIES = %i[ uri http_method body body_mimetype config ].freeze
|
|
57
65
|
|
|
58
66
|
|
|
59
67
|
### Return an array of attributes to fetch from nodes for this monitor.
|
|
@@ -68,7 +76,7 @@ module Arborist::Monitor::Webservice
|
|
|
68
76
|
end
|
|
69
77
|
|
|
70
78
|
|
|
71
|
-
### Create a new
|
|
79
|
+
### Create a new HTTP webservice monitor with the specified +options+. Valid options are:
|
|
72
80
|
###
|
|
73
81
|
### +:timeout+
|
|
74
82
|
### Set the number of seconds to wait for a connection for each node.
|
|
@@ -103,7 +111,8 @@ module Arborist::Monitor::Webservice
|
|
|
103
111
|
request = self.request_for_node( node )
|
|
104
112
|
request.on_complete do |response|
|
|
105
113
|
self.log.debug "Handling response for %s" % [ identifier ]
|
|
106
|
-
results[ identifier ] =
|
|
114
|
+
results[ identifier ] =
|
|
115
|
+
self.make_response_results( response, node['expected_status'] )
|
|
107
116
|
end
|
|
108
117
|
hydra.queue( request )
|
|
109
118
|
end
|
|
@@ -116,9 +125,11 @@ module Arborist::Monitor::Webservice
|
|
|
116
125
|
|
|
117
126
|
### Return a request object built to test the specified webservice +node+.
|
|
118
127
|
def request_for_node( node_data )
|
|
128
|
+
http_version = convert_http_version( node_data['http_version'] || DEFAULT_HTTP_VERSION )
|
|
129
|
+
|
|
119
130
|
options = {
|
|
120
131
|
method: node_data['http_method'] || DEFAULT_HTTP_METHOD,
|
|
121
|
-
http_version:
|
|
132
|
+
http_version: http_version,
|
|
122
133
|
headers: self.make_headers_hash( node_data ),
|
|
123
134
|
body: node_data['body'],
|
|
124
135
|
timeout: self.timeout,
|
|
@@ -129,6 +140,7 @@ module Arborist::Monitor::Webservice
|
|
|
129
140
|
options.merge!( ssl_opts )
|
|
130
141
|
end
|
|
131
142
|
|
|
143
|
+
self.log.debug "Node options for %p are: %p" % [ node_data['uri'], options ]
|
|
132
144
|
return Typhoeus::Request.new( node_data['uri'], options )
|
|
133
145
|
end
|
|
134
146
|
|
|
@@ -137,10 +149,15 @@ module Arborist::Monitor::Webservice
|
|
|
137
149
|
def make_ssl_options( uri, node_data )
|
|
138
150
|
return nil unless uri.start_with?( 'https:' )
|
|
139
151
|
|
|
140
|
-
|
|
141
|
-
|
|
152
|
+
self.log.debug "Extracting valid SSL options from the node's config: %p" %
|
|
153
|
+
[ node_data['config'] ]
|
|
154
|
+
ssl_attributes = SSL_ATTRIBUTES.each_with_object({}) do |(key, desc), opts|
|
|
155
|
+
opts[ key ] = node_data[ 'config' ][ key.to_s ] if
|
|
156
|
+
node_data['config']&.key?( key.to_s )
|
|
142
157
|
end
|
|
143
158
|
|
|
159
|
+
ssl_attributes[ :ssl_verifypeer ] ||= Arborist::Monitor::Webservice.ssl_verifypeer
|
|
160
|
+
|
|
144
161
|
return ssl_attributes
|
|
145
162
|
end
|
|
146
163
|
|
|
@@ -167,17 +184,18 @@ module Arborist::Monitor::Webservice
|
|
|
167
184
|
|
|
168
185
|
|
|
169
186
|
### Return a Hash of results appropriate for the specified +response+.
|
|
170
|
-
def make_response_results( response )
|
|
171
|
-
if response.
|
|
187
|
+
def make_response_results( response, expected_status=200 )
|
|
188
|
+
if response.code == expected_status
|
|
172
189
|
return { webservice: self.success_results(response) }
|
|
173
190
|
elsif response.timed_out?
|
|
174
191
|
self.log.error "Request timed out."
|
|
175
192
|
return { error: 'Request timed out.' }
|
|
176
193
|
elsif response.code == 0
|
|
177
|
-
self.log.error
|
|
178
|
-
return { error: response.
|
|
194
|
+
self.log.error( response.return_message )
|
|
195
|
+
return { error: response.return_message }
|
|
179
196
|
else
|
|
180
|
-
self.log.error "Got
|
|
197
|
+
self.log.error "Got an unexpected %03d %s response; expected %03d." %
|
|
198
|
+
[ response.code, response.status_message, expected_status ]
|
|
181
199
|
return {
|
|
182
200
|
error: "%03d %s" % [ response.code, response.status_message ]
|
|
183
201
|
}
|
|
@@ -189,6 +207,7 @@ module Arborist::Monitor::Webservice
|
|
|
189
207
|
### responses.
|
|
190
208
|
def success_results( response )
|
|
191
209
|
return {
|
|
210
|
+
http_version: response.http_version,
|
|
192
211
|
status: response.code,
|
|
193
212
|
status_message: response.status_message,
|
|
194
213
|
headers: response.headers_hash,
|
|
@@ -203,11 +222,31 @@ module Arborist::Monitor::Webservice
|
|
|
203
222
|
}
|
|
204
223
|
end
|
|
205
224
|
|
|
206
|
-
|
|
225
|
+
|
|
226
|
+
#######
|
|
227
|
+
private
|
|
228
|
+
#######
|
|
229
|
+
|
|
230
|
+
### Convert a version string like `1.1` into the Symbol Typhoeus/Ethon expect
|
|
231
|
+
### (e.g., `:httpv1_1`)
|
|
232
|
+
def convert_http_version( version_string )
|
|
233
|
+
return case version_string
|
|
234
|
+
when '1.0'
|
|
235
|
+
:httpv1_0
|
|
236
|
+
when '1.1'
|
|
237
|
+
:httpv1_1
|
|
238
|
+
when '2.0'
|
|
239
|
+
:httpv2_0
|
|
240
|
+
else
|
|
241
|
+
version_string.to_sym
|
|
242
|
+
end
|
|
243
|
+
end
|
|
244
|
+
|
|
245
|
+
end # class HTTP
|
|
207
246
|
|
|
208
247
|
|
|
209
248
|
# Arborist REST webservice monitor logic
|
|
210
|
-
class REST < Arborist::Monitor::Webservice::
|
|
249
|
+
class REST < Arborist::Monitor::Webservice::HTTP
|
|
211
250
|
end # class REST
|
|
212
251
|
|
|
213
252
|
end # class Arborist::Monitor::Webservice
|
|
@@ -25,14 +25,11 @@ class Arborist::Node::Webservice < Arborist::Node::Service
|
|
|
25
25
|
|
|
26
26
|
### Create a new Webservice node.
|
|
27
27
|
def initialize( identifier, host, uri, attributes={}, &block )
|
|
28
|
-
|
|
29
|
-
uri_obj = URI( uri )
|
|
30
|
-
|
|
31
|
-
attributes[:app_protocol] ||= uri_obj.scheme
|
|
32
|
-
attributes[:port] ||= uri_obj.port
|
|
28
|
+
attributes[:uri] = URI( uri )
|
|
33
29
|
attributes[:protocol] = 'tcp'
|
|
34
30
|
attributes[:app_protocol] = 'http'
|
|
35
31
|
attributes[:http_method] ||= DEFAULT_HTTP_METHOD
|
|
32
|
+
attributes[:http_version] ||= DEFAULT_HTTP_VERSION
|
|
36
33
|
attributes[:http_headers] ||= {}
|
|
37
34
|
attributes[:expected_status] ||= DEFAULT_EXPECTED_STATUS
|
|
38
35
|
attributes[:body] ||= ''
|
|
@@ -47,14 +44,14 @@ class Arborist::Node::Webservice < Arborist::Node::Service
|
|
|
47
44
|
public
|
|
48
45
|
######
|
|
49
46
|
|
|
50
|
-
##
|
|
51
|
-
# The URI of an endpoint that can be used to monitor the webservice
|
|
52
|
-
dsl_accessor :uri
|
|
53
|
-
|
|
54
47
|
##
|
|
55
48
|
# The http_method used by the service
|
|
56
49
|
dsl_accessor :http_method
|
|
57
50
|
|
|
51
|
+
##
|
|
52
|
+
# The http version used by the service
|
|
53
|
+
dsl_accessor :http_version
|
|
54
|
+
|
|
58
55
|
##
|
|
59
56
|
# The expected_status used by the service
|
|
60
57
|
dsl_accessor :expected_status
|
|
@@ -73,6 +70,20 @@ class Arborist::Node::Webservice < Arborist::Node::Service
|
|
|
73
70
|
end
|
|
74
71
|
|
|
75
72
|
|
|
73
|
+
### Get/set the URI of the service.
|
|
74
|
+
def uri( new_uri=nil )
|
|
75
|
+
if new_uri
|
|
76
|
+
@uri = URI( new_uri )
|
|
77
|
+
@uri.host ||= self.addresses.first.to_s
|
|
78
|
+
|
|
79
|
+
self.app_protocol( @uri.scheme )
|
|
80
|
+
self.port( @uri.port )
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
return @uri.to_s
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
|
|
76
87
|
### Set node +attributes+ from a Hash.
|
|
77
88
|
def modify( attributes )
|
|
78
89
|
attributes = stringify_keys( attributes )
|
|
@@ -81,6 +92,7 @@ class Arborist::Node::Webservice < Arborist::Node::Service
|
|
|
81
92
|
|
|
82
93
|
self.uri( attributes['uri'] )
|
|
83
94
|
self.http_method( attributes['http_method'] )
|
|
95
|
+
self.http_version( attributes['http_version'] )
|
|
84
96
|
self.expected_status( attributes['expected_status'] )
|
|
85
97
|
self.body( attributes['body'] )
|
|
86
98
|
self.body_mimetype( attributes['body_mimetype'] )
|
|
@@ -95,6 +107,8 @@ class Arborist::Node::Webservice < Arborist::Node::Service
|
|
|
95
107
|
URI( self.uri ) == URI( val )
|
|
96
108
|
when 'http_method'
|
|
97
109
|
self.http_method == val
|
|
110
|
+
when 'http_version'
|
|
111
|
+
self.http_version == val
|
|
98
112
|
when 'expected_status'
|
|
99
113
|
self.expected_status == val
|
|
100
114
|
when 'body'
|
|
@@ -122,10 +136,11 @@ class Arborist::Node::Webservice < Arborist::Node::Service
|
|
|
122
136
|
|
|
123
137
|
### Return service-node-specific information for #inspect.
|
|
124
138
|
def node_description
|
|
125
|
-
desc = "%s %s %s
|
|
139
|
+
desc = "%s %s %s/%s" % [
|
|
126
140
|
self.http_method,
|
|
127
141
|
self.uri,
|
|
128
142
|
self.app_protocol.upcase,
|
|
143
|
+
self.http_version,
|
|
129
144
|
]
|
|
130
145
|
|
|
131
146
|
if body && !body.empty?
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
# -*- ruby -*-
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
require 'arborist/webservice' unless defined?( Arborist::Webservice )
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
module Arborist::Webservice::Constants
|
|
8
|
+
|
|
9
|
+
# The default HTTP verb to use for monitoring requests
|
|
10
|
+
DEFAULT_HTTP_METHOD = 'HEAD'.freeze
|
|
11
|
+
|
|
12
|
+
# The default HTTP status code to expect from responses
|
|
13
|
+
DEFAULT_EXPECTED_STATUS = 200
|
|
14
|
+
|
|
15
|
+
# The default Content-type to use for requests with a body
|
|
16
|
+
DEFAULT_BODY_MIMETYPE = 'text/plain'.freeze
|
|
17
|
+
|
|
18
|
+
# The version of HTTP to use in the request line
|
|
19
|
+
DEFAULT_HTTP_VERSION = '2.0'
|
|
20
|
+
|
|
21
|
+
# The headers to include with the request
|
|
22
|
+
DEFAULT_HTTP_HEADERS = {
|
|
23
|
+
'Connection' => 'close',
|
|
24
|
+
'Accept' => '*/*',
|
|
25
|
+
'User-Agent' => "Arborist-WebService/%s" % [ Arborist::Webservice::VERSION ],
|
|
26
|
+
}.freeze
|
|
27
|
+
|
|
28
|
+
# The SSL attributes that are settable
|
|
29
|
+
SSL_ATTRIBUTES = {
|
|
30
|
+
sslcert: "Client cert.",
|
|
31
|
+
sslcerttype: "Client cert type.",
|
|
32
|
+
sslkey: "Client key.",
|
|
33
|
+
sslkeytype: "Client key type.",
|
|
34
|
+
keypasswd: "Client key password.",
|
|
35
|
+
ssl_enable_alpn: "Enable use of ALPN.",
|
|
36
|
+
ssl_enable_npn: "Enable use of NPN.",
|
|
37
|
+
sslengine: "Use identifier with SSL engine.",
|
|
38
|
+
sslengine_default: "Default SSL engine.",
|
|
39
|
+
ssl_falsestart: "Enable TLS False Start.",
|
|
40
|
+
sslversion: "SSL version to use.",
|
|
41
|
+
ssl_verifyhost: "Verify the host name in the SSL certificate.",
|
|
42
|
+
ssl_verifypeer: "Verify the SSL certificate.",
|
|
43
|
+
ssl_verifystatus: "Verify the SSL certificate's status.",
|
|
44
|
+
cainfo: "CA cert bundle.",
|
|
45
|
+
issuercert: "Issuer certificate.",
|
|
46
|
+
capath: "Path to CA cert bundle.",
|
|
47
|
+
crlfile: "Certificate Revocation List.",
|
|
48
|
+
certinfo: "Extract certificate info.",
|
|
49
|
+
pinnedpublickey: "Set pinned SSL public key .",
|
|
50
|
+
random_file: "Provide source for entropy random data.",
|
|
51
|
+
egdsocket: "Identify EGD socket for entropy.",
|
|
52
|
+
ssl_cipher_list: "Ciphers to use.",
|
|
53
|
+
tls13_ciphers: "TLS 1.3 cipher suites to use.",
|
|
54
|
+
ssl_sessionid_cache: "Disable SSL session-id cache.",
|
|
55
|
+
ssl_options: "Control SSL behavior.",
|
|
56
|
+
krblevel: "Kerberos security level.",
|
|
57
|
+
gssapi_delegation: "Disable GSS-API delegation.",
|
|
58
|
+
proxy_sslcert: "Proxy client cert.",
|
|
59
|
+
proxy_sslcerttype: "Proxy client cert type.",
|
|
60
|
+
proxy_sslkey: "Proxy client key.",
|
|
61
|
+
proxy_sslkeytype: "Proxy client key type.",
|
|
62
|
+
proxy_keypasswd: "Proxy client key password.",
|
|
63
|
+
proxy_sslversion: "Proxy SSL version to use.",
|
|
64
|
+
proxy_ssl_verifyhost: "Verify the host name in the proxy SSL certificate.",
|
|
65
|
+
proxy_ssl_verifypeer: "Verify the proxy SSL certificate.",
|
|
66
|
+
proxy_cainfo: "Proxy CA cert bundle.",
|
|
67
|
+
proxy_capath: "Path to proxy CA cert bundle.",
|
|
68
|
+
proxy_crlfile: "Proxy Certificate Revocation List.",
|
|
69
|
+
proxy_pinnedpublickey: "Set the proxy's pinned SSL public key.",
|
|
70
|
+
proxy_ssl_cipher_list: "Proxy ciphers to use.",
|
|
71
|
+
proxy_tls13_ciphers: "Proxy TLS 1.3 cipher suites to use.",
|
|
72
|
+
proxy_ssl_options: "Control proxy SSL behavior.",
|
|
73
|
+
}.freeze
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
end # module Arborist::Webservice::Constants
|
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
#!/usr/bin/env rspec -cfd
|
|
2
|
+
|
|
3
|
+
require_relative '../../spec_helper'
|
|
4
|
+
|
|
5
|
+
require 'typhoeus'
|
|
6
|
+
require 'arborist/webservice'
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
describe Arborist::Monitor::Webservice do
|
|
10
|
+
|
|
11
|
+
using Arborist::TimeRefinements
|
|
12
|
+
|
|
13
|
+
before( :each ) do
|
|
14
|
+
Typhoeus::Expectation.clear
|
|
15
|
+
end
|
|
16
|
+
after( :each ) do
|
|
17
|
+
Typhoeus::Expectation.clear
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
describe Arborist::Monitor::Webservice::HTTP do
|
|
22
|
+
|
|
23
|
+
let( :monitor ) { described_class.new }
|
|
24
|
+
let( :host_node ) do
|
|
25
|
+
Arborist::Node.create( :host, 'webserver' ) do
|
|
26
|
+
description "Test host node with a few web services"
|
|
27
|
+
address '10.2.18.64'
|
|
28
|
+
tags :testing
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
let( :webservice_node1 ) { host_node.webservice('marketing', 'https://www.acme.com/') }
|
|
33
|
+
let( :webservice_node2 ) { host_node.webservice('store', 'https://store.acme.com/') }
|
|
34
|
+
let( :webservice_node3 ) { host_node.webservice('support', 'https://int.support.acme.com/') }
|
|
35
|
+
|
|
36
|
+
let( :nodes ) {[ webservice_node1, webservice_node2, webservice_node3 ]}
|
|
37
|
+
let( :nodes_hash ) do
|
|
38
|
+
nodes.each_with_object({}) do |node, accum|
|
|
39
|
+
accum[ node.identifier ] = node.fetch_values
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
it "is created with a default timeout" do
|
|
45
|
+
expect( monitor.timeout ).to be_an( Numeric )
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
it "can clone itself with a new timeout" do
|
|
50
|
+
new_monitor = monitor.with_timeout( 2.minutes )
|
|
51
|
+
expect( new_monitor ).to_not equal( monitor )
|
|
52
|
+
expect( new_monitor.timeout ).to eq( 2.minutes )
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
it "runs against a collection of nodes and updates the statuses of each one" do
|
|
57
|
+
Typhoeus.stub( /acme/i ).and_return do |req|
|
|
58
|
+
Typhoeus::Response.new( code: 200, body: "OK" )
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
result = monitor.run( nodes_hash )
|
|
62
|
+
|
|
63
|
+
expect( result ).to be_a( Hash )
|
|
64
|
+
expect( result.keys ).to contain_exactly( *nodes.map(&:identifier) )
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
it "sets an error for HTTP error response statuses" do
|
|
69
|
+
Typhoeus.stub( /support\.acme/i ).and_return do |req|
|
|
70
|
+
Typhoeus::Response.new( code: 500, status_message: 'Server Error' )
|
|
71
|
+
end
|
|
72
|
+
Typhoeus.stub( /(www|store)\.acme/i ).and_return do |req|
|
|
73
|
+
Typhoeus::Response.new( code: 200, body: "OK" )
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
result = monitor.run( nodes_hash )
|
|
77
|
+
|
|
78
|
+
expect( result[webservice_node3.identifier] ).to include( error: '500 Server Error' )
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
it "sets a human-readable error message for lower-layer error response statuses" do
|
|
83
|
+
Typhoeus.stub( /store\.acme/i ).and_return do |req|
|
|
84
|
+
Typhoeus::Response.new( code: 0, return_code: :couldnt_connect )
|
|
85
|
+
end
|
|
86
|
+
Typhoeus.stub( /(www|support)\.acme/i ).and_return do |req|
|
|
87
|
+
Typhoeus::Response.new( code: 200, body: "OK" )
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
result = monitor.run( nodes_hash )
|
|
91
|
+
|
|
92
|
+
expect( result[webservice_node2.identifier] ).to include( error: "Couldn't connect to server" )
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
it "sets an error for timeouts" do
|
|
97
|
+
Typhoeus.stub( /store\.acme/i ).and_return do |req|
|
|
98
|
+
Typhoeus::Response.new( code: 0, return_code: :operation_timedout )
|
|
99
|
+
end
|
|
100
|
+
Typhoeus.stub( /(www|support)\.acme/i ).and_return do |req|
|
|
101
|
+
Typhoeus::Response.new( code: 200, body: "OK" )
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
result = monitor.run( nodes_hash )
|
|
105
|
+
|
|
106
|
+
expect( result[webservice_node2.identifier] ).to include( error: 'Request timed out.' )
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
it "doesn't error if HTTP error response status matches the expected status" do
|
|
111
|
+
Typhoeus.stub( /store\.acme/i ).and_return do |req|
|
|
112
|
+
Typhoeus::Response.new( code: 401, status_message: 'Access denied' )
|
|
113
|
+
end
|
|
114
|
+
Typhoeus.stub( /(www|support)\.acme/i ).and_return do |req|
|
|
115
|
+
Typhoeus::Response.new( code: 200, body: "OK" )
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
webservice_node2.expected_status( 401 )
|
|
119
|
+
result = monitor.run( nodes_hash )
|
|
120
|
+
|
|
121
|
+
expect( result[webservice_node2.identifier] ).to_not include( :error )
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
|
|
125
|
+
it "posts with the provided body if one is set" do
|
|
126
|
+
Typhoeus.stub( /support\.acme/i ).and_return do |req|
|
|
127
|
+
expect( req.options[:method] ).to eq( 'POST' )
|
|
128
|
+
expect( req.options[:body] ).to eq( '[1, 2, 3, 4]' )
|
|
129
|
+
expect( req.options[:headers] ).to include( 'Content-type' => 'application/json' )
|
|
130
|
+
Typhoeus::Response.new( code: 201, status_message: 'Object created' )
|
|
131
|
+
end
|
|
132
|
+
Typhoeus.stub( /(www|store)\.acme/i ).and_return do |req|
|
|
133
|
+
Typhoeus::Response.new( code: 200, body: "OK" )
|
|
134
|
+
end
|
|
135
|
+
|
|
136
|
+
webservice_node3.http_method( 'POST' )
|
|
137
|
+
webservice_node3.body( '[1, 2, 3, 4]' )
|
|
138
|
+
webservice_node3.body_mimetype( 'application/json' )
|
|
139
|
+
webservice_node3.expected_status( 201 )
|
|
140
|
+
|
|
141
|
+
result = monitor.run( nodes_hash )
|
|
142
|
+
|
|
143
|
+
expect( result.keys ).to contain_exactly( *nodes.map(&:identifier) )
|
|
144
|
+
end
|
|
145
|
+
|
|
146
|
+
|
|
147
|
+
it "uses valid entries from the node's config as SSL configuration" do
|
|
148
|
+
Typhoeus.stub( /acme/i ).and_return do |req|
|
|
149
|
+
expect( req.options[:ssl_verifypeer] ).to eq( 0 )
|
|
150
|
+
Typhoeus::Response.new( code: 200, body: "OK" )
|
|
151
|
+
end
|
|
152
|
+
|
|
153
|
+
nodes.each do |node|
|
|
154
|
+
node.config( ssl_verifypeer: 0 )
|
|
155
|
+
end
|
|
156
|
+
|
|
157
|
+
result = monitor.run( nodes_hash )
|
|
158
|
+
|
|
159
|
+
expect( result ).to be_a( Hash )
|
|
160
|
+
expect( result.keys ).to contain_exactly( *nodes.map(&:identifier) )
|
|
161
|
+
end
|
|
162
|
+
|
|
163
|
+
end
|
|
164
|
+
|
|
165
|
+
|
|
166
|
+
describe "REST monitor logic"
|
|
167
|
+
|
|
168
|
+
end
|
|
169
|
+
|
|
@@ -4,21 +4,71 @@
|
|
|
4
4
|
require_relative '../../spec_helper'
|
|
5
5
|
|
|
6
6
|
require 'rspec'
|
|
7
|
+
require 'arborist/node/host'
|
|
7
8
|
require 'arborist/node/webservice'
|
|
8
9
|
|
|
9
10
|
describe Arborist::Node::Webservice do
|
|
10
11
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
12
|
+
let( :host_node ) do
|
|
13
|
+
Arborist::Host 'testhost' do
|
|
14
|
+
address '192.168.66.12'
|
|
15
|
+
address '10.2.12.68'
|
|
16
|
+
hostname 'example.com'
|
|
17
|
+
end
|
|
18
|
+
end
|
|
15
19
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
+
let( :node ) { host_node.webservice('api', 'https://example.com/api/v1') }
|
|
21
|
+
let( :getonly_node ) do
|
|
22
|
+
host_node.webservice( 'repo-api', 'https://repo.example.com/' ) do
|
|
23
|
+
http_method 'GET'
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
let( :http10_node ) do
|
|
27
|
+
host_node.webservice( 'archive-site', 'http://archive.example.com/' ) do
|
|
28
|
+
http_version '1.0'
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
it "can match on URI" do
|
|
34
|
+
expect( node ).to match_criteria( uri: 'https://example.com/api/v1' )
|
|
35
|
+
expect( node ).to_not match_criteria( uri: 'https://example.com/api/v2' )
|
|
36
|
+
expect( node ).to_not match_criteria( uri: 'https://bitter.com/api/v1' )
|
|
37
|
+
expect( node ).to_not match_criteria( uri: 'http://example.com/api/v1' )
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
it "can match on HTTP method" do
|
|
42
|
+
expect( node ).to match_criteria( http_method: 'HEAD' )
|
|
43
|
+
expect( node ).to_not match_criteria( http_method: 'GET' )
|
|
44
|
+
expect( getonly_node ).to match_criteria( http_method: 'GET' )
|
|
45
|
+
expect( getonly_node ).to_not match_criteria( http_method: 'HEAD' )
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
it "can match on HTTP version" do
|
|
50
|
+
expect( node ).to match_criteria( http_version: '2.0' )
|
|
51
|
+
expect( node ).to_not match_criteria( http_version: '1.0' )
|
|
52
|
+
expect( http10_node ).to match_criteria( http_version: '1.0' )
|
|
53
|
+
expect( http10_node ).to_not match_criteria( http_version: '1.1' )
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
it "includes the URI in the operational attributes" do
|
|
58
|
+
expect( node.operational_values ).to include( uri: node.uri )
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
it "includes the HTTP method in the operational attributes" do
|
|
63
|
+
expect( node.operational_values ).to include( http_method: node.http_method )
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
it "allows shorthand URI syntax for implicit host" do
|
|
68
|
+
node = host_node.webservice( 'djinn', 'http:///' )
|
|
69
|
+
expect( node.uri ).to eq( 'http://192.168.66.12/' )
|
|
70
|
+
end
|
|
20
71
|
|
|
21
|
-
it "provides a DSL declaration to disable SSL verification"
|
|
22
72
|
|
|
23
73
|
end
|
|
24
74
|
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
#!/usr/bin/env rspec -cfd
|
|
2
|
+
|
|
3
|
+
require_relative '../spec_helper'
|
|
4
|
+
|
|
5
|
+
require 'arborist/webservice'
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
describe Arborist::Webservice do
|
|
9
|
+
|
|
10
|
+
it "has a version constant" do
|
|
11
|
+
expect( described_class::VERSION ).to match( /^\d+(\.\d+){2}$/ )
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
it "can return a version string for itself" do
|
|
16
|
+
expect( described_class.version_string ).
|
|
17
|
+
to match( /Arborist::Webservice v\d+\.\d+\.\d+/ )
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
it "can return a version string with the build ID" do
|
|
22
|
+
expect( described_class.version_string(include_build: true) ).
|
|
23
|
+
to match( /Arborist::Webservice v\d+\.\d+\.\d+.*\(Revision: \w+\)/ )
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
end
|
|
27
|
+
|
data/spec/spec_helper.rb
CHANGED
|
@@ -6,6 +6,17 @@ require 'simplecov' if ENV['COVERAGE']
|
|
|
6
6
|
require 'rspec'
|
|
7
7
|
|
|
8
8
|
require 'loggability/spechelpers'
|
|
9
|
+
require 'arborist'
|
|
10
|
+
require 'arborist/mixins'
|
|
11
|
+
require 'arborist/webservice'
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
RSpec::Matchers.define( :match_criteria ) do |criteria|
|
|
15
|
+
match do |node|
|
|
16
|
+
criteria = Arborist::HashUtilities.stringify_keys( criteria )
|
|
17
|
+
node.matches?( criteria )
|
|
18
|
+
end
|
|
19
|
+
end
|
|
9
20
|
|
|
10
21
|
|
|
11
22
|
### Mock with RSpec
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: arborist-webservice
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.0.1
|
|
4
|
+
version: 0.0.1
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Michael Granger
|
|
@@ -35,7 +35,7 @@ cert_chain:
|
|
|
35
35
|
X0qdrKi+2aZZ0NGuFj9AItBsVmAvkBGIpX4TEKQp5haEbPpmaqO5nIIhV26PXmyT
|
|
36
36
|
OMKv6pWsoS81vw5KAGBmfX8nht/Py90DQrbRvakATGI=
|
|
37
37
|
-----END CERTIFICATE-----
|
|
38
|
-
date: 2018-08-
|
|
38
|
+
date: 2018-08-31 00:00:00.000000000 Z
|
|
39
39
|
dependencies:
|
|
40
40
|
- !ruby/object:Gem::Dependency
|
|
41
41
|
name: arborist
|
|
@@ -43,28 +43,28 @@ dependencies:
|
|
|
43
43
|
requirements:
|
|
44
44
|
- - "~>"
|
|
45
45
|
- !ruby/object:Gem::Version
|
|
46
|
-
version: '0'
|
|
46
|
+
version: '0.2'
|
|
47
47
|
type: :runtime
|
|
48
48
|
prerelease: false
|
|
49
49
|
version_requirements: !ruby/object:Gem::Requirement
|
|
50
50
|
requirements:
|
|
51
51
|
- - "~>"
|
|
52
52
|
- !ruby/object:Gem::Version
|
|
53
|
-
version: '0'
|
|
53
|
+
version: '0.2'
|
|
54
54
|
- !ruby/object:Gem::Dependency
|
|
55
55
|
name: loggability
|
|
56
56
|
requirement: !ruby/object:Gem::Requirement
|
|
57
57
|
requirements:
|
|
58
58
|
- - "~>"
|
|
59
59
|
- !ruby/object:Gem::Version
|
|
60
|
-
version: '0.
|
|
60
|
+
version: '0.14'
|
|
61
61
|
type: :runtime
|
|
62
62
|
prerelease: false
|
|
63
63
|
version_requirements: !ruby/object:Gem::Requirement
|
|
64
64
|
requirements:
|
|
65
65
|
- - "~>"
|
|
66
66
|
- !ruby/object:Gem::Version
|
|
67
|
-
version: '0.
|
|
67
|
+
version: '0.14'
|
|
68
68
|
- !ruby/object:Gem::Dependency
|
|
69
69
|
name: typhoeus
|
|
70
70
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -141,14 +141,14 @@ dependencies:
|
|
|
141
141
|
requirements:
|
|
142
142
|
- - "~>"
|
|
143
143
|
- !ruby/object:Gem::Version
|
|
144
|
-
version: '0.
|
|
144
|
+
version: '0.4'
|
|
145
145
|
type: :development
|
|
146
146
|
prerelease: false
|
|
147
147
|
version_requirements: !ruby/object:Gem::Requirement
|
|
148
148
|
requirements:
|
|
149
149
|
- - "~>"
|
|
150
150
|
- !ruby/object:Gem::Version
|
|
151
|
-
version: '0.
|
|
151
|
+
version: '0.4'
|
|
152
152
|
- !ruby/object:Gem::Dependency
|
|
153
153
|
name: rdoc
|
|
154
154
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -202,7 +202,10 @@ files:
|
|
|
202
202
|
- lib/arborist/monitor/webservice.rb
|
|
203
203
|
- lib/arborist/node/webservice.rb
|
|
204
204
|
- lib/arborist/webservice.rb
|
|
205
|
+
- lib/arborist/webservice/constants.rb
|
|
206
|
+
- spec/arborist/monitor/webservice_spec.rb
|
|
205
207
|
- spec/arborist/node/webservice_spec.rb
|
|
208
|
+
- spec/arborist/webservice_spec.rb
|
|
206
209
|
- spec/spec_helper.rb
|
|
207
210
|
homepage: http://deveiate.org/projects/arborist-webservice
|
|
208
211
|
licenses:
|
|
@@ -221,9 +224,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
|
221
224
|
version: '0'
|
|
222
225
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
223
226
|
requirements:
|
|
224
|
-
- - "
|
|
227
|
+
- - ">="
|
|
225
228
|
- !ruby/object:Gem::Version
|
|
226
|
-
version:
|
|
229
|
+
version: '0'
|
|
227
230
|
requirements: []
|
|
228
231
|
rubyforge_project:
|
|
229
232
|
rubygems_version: 2.7.6
|
metadata.gz.sig
ADDED
|
Binary file
|