arborist 0.2.0.pre20170519125456 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- checksums.yaml.gz.sig +0 -0
- data.tar.gz.sig +0 -0
- data/ChangeLog +670 -1
- data/History.md +67 -0
- data/Manifest.txt +9 -6
- data/README.md +1 -3
- data/Rakefile +39 -4
- data/TODO.md +22 -31
- data/lib/arborist.rb +9 -2
- data/lib/arborist/cli.rb +67 -85
- data/lib/arborist/client.rb +125 -59
- data/lib/arborist/command/ack.rb +86 -0
- data/lib/arborist/command/reset.rb +48 -0
- data/lib/arborist/command/start.rb +11 -1
- data/lib/arborist/command/summary.rb +173 -0
- data/lib/arborist/command/tree.rb +215 -0
- data/lib/arborist/command/watch.rb +22 -22
- data/lib/arborist/dependency.rb +24 -4
- data/lib/arborist/event.rb +18 -2
- data/lib/arborist/event/node.rb +6 -2
- data/lib/arborist/event/node_warn.rb +16 -0
- data/lib/arborist/manager.rb +179 -48
- data/lib/arborist/mixins.rb +11 -0
- data/lib/arborist/monitor.rb +29 -17
- data/lib/arborist/monitor/connection_batching.rb +293 -0
- data/lib/arborist/monitor/socket.rb +101 -167
- data/lib/arborist/monitor_runner.rb +101 -24
- data/lib/arborist/node.rb +297 -68
- data/lib/arborist/node/ack.rb +1 -1
- data/lib/arborist/node/host.rb +26 -5
- data/lib/arborist/node/resource.rb +14 -5
- data/lib/arborist/node/root.rb +12 -3
- data/lib/arborist/node/service.rb +29 -26
- data/lib/arborist/node_subscription.rb +65 -0
- data/lib/arborist/observer.rb +8 -0
- data/lib/arborist/observer/action.rb +6 -0
- data/lib/arborist/subscription.rb +22 -16
- data/lib/arborist/tree_api.rb +7 -2
- data/spec/arborist/client_spec.rb +157 -51
- data/spec/arborist/dependency_spec.rb +21 -0
- data/spec/arborist/event/node_spec.rb +5 -0
- data/spec/arborist/event_spec.rb +3 -3
- data/spec/arborist/manager_spec.rb +626 -347
- data/spec/arborist/mixins_spec.rb +19 -0
- data/spec/arborist/monitor/socket_spec.rb +1 -2
- data/spec/arborist/monitor_runner_spec.rb +81 -29
- data/spec/arborist/monitor_spec.rb +89 -14
- data/spec/arborist/node/host_spec.rb +68 -0
- data/spec/arborist/node/resource_spec.rb +2 -0
- data/spec/arborist/node/root_spec.rb +13 -0
- data/spec/arborist/node/service_spec.rb +9 -0
- data/spec/arborist/node_spec.rb +673 -111
- data/spec/arborist/node_subscription_spec.rb +54 -0
- data/spec/arborist/observer/action_spec.rb +6 -0
- data/spec/arborist/observer_runner_spec.rb +8 -1
- data/spec/arborist/tree_api_spec.rb +111 -8
- data/spec/data/monitors/pings.rb +0 -11
- data/spec/data/monitors/port_checks.rb +0 -9
- data/spec/data/nodes/sidonie.rb +1 -0
- data/spec/data/nodes/vhosts.rb +23 -0
- data/spec/data/nodes/yevaud.rb +4 -2
- data/spec/spec_helper.rb +71 -1
- metadata +91 -28
- metadata.gz.sig +0 -0
- data/Events.md +0 -35
- data/Monitors.md +0 -155
- data/Nodes.md +0 -70
- data/Observers.md +0 -72
- data/Protocol.md +0 -276
- data/Tutorial.md +0 -8
@@ -82,6 +82,7 @@ describe Arborist, "mixins" do
|
|
82
82
|
expect( extended_class ).to respond_to( :foo? )
|
83
83
|
end
|
84
84
|
|
85
|
+
|
85
86
|
it "can declare a class-level predicate method" do
|
86
87
|
extended_class.singleton_predicate_reader :foo
|
87
88
|
expect( extended_class ).to_not respond_to( :foo )
|
@@ -89,6 +90,24 @@ describe Arborist, "mixins" do
|
|
89
90
|
expect( extended_class ).to respond_to( :foo? )
|
90
91
|
end
|
91
92
|
|
93
|
+
|
94
|
+
it "can declare an instance DSLish accessor" do
|
95
|
+
extended_class.dsl_accessor( :foo )
|
96
|
+
instance = extended_class.new
|
97
|
+
|
98
|
+
instance.foo( 13 )
|
99
|
+
expect( instance.foo ).to eq( 13 )
|
100
|
+
end
|
101
|
+
|
102
|
+
|
103
|
+
it "the instance DSLish accessor works with a `false` argument" do
|
104
|
+
extended_class.dsl_accessor( :foo )
|
105
|
+
instance = extended_class.new
|
106
|
+
|
107
|
+
instance.foo( false )
|
108
|
+
expect( instance.foo ).to equal( false )
|
109
|
+
end
|
110
|
+
|
92
111
|
end
|
93
112
|
|
94
113
|
|
@@ -102,9 +102,8 @@ describe Arborist::Monitor::Socket do
|
|
102
102
|
expect( result ).to be_a( Hash )
|
103
103
|
expect( result ).to include( *service_nodes.map(&:identifier) )
|
104
104
|
expect( result.values ).to all( include(
|
105
|
-
tcp_socket_connect: a_hash_including(:
|
105
|
+
tcp_socket_connect: a_hash_including(:duration)
|
106
106
|
) )
|
107
|
-
expect( result.map {|_, res| res[:tcp_socket_connect][:time]} ).to all( be_a(String) )
|
108
107
|
end
|
109
108
|
|
110
109
|
|
@@ -3,7 +3,7 @@
|
|
3
3
|
require_relative '../spec_helper'
|
4
4
|
|
5
5
|
require 'arborist/monitor_runner'
|
6
|
-
|
6
|
+
require 'arborist/node/root'
|
7
7
|
|
8
8
|
describe Arborist::MonitorRunner do
|
9
9
|
|
@@ -35,8 +35,11 @@ describe Arborist::MonitorRunner do
|
|
35
35
|
|
36
36
|
before( :each ) do
|
37
37
|
allow( CZTop::Reactor ).to receive( :new ).and_return( reactor )
|
38
|
+
allow( Thread ).to receive( :new ).and_yield
|
38
39
|
allow( reactor ).to receive( :register )
|
39
40
|
allow( reactor ).to receive( :unregister )
|
41
|
+
allow( reactor ).to receive( :add_periodic_timer ).
|
42
|
+
with( described_class::THREAD_CLEANUP_INTERVAL )
|
40
43
|
end
|
41
44
|
|
42
45
|
|
@@ -72,36 +75,39 @@ describe Arborist::MonitorRunner do
|
|
72
75
|
|
73
76
|
it "can run a monitor using async ZMQ IO" do
|
74
77
|
|
75
|
-
#
|
78
|
+
# Set up the monitor's execution block with fixtured data
|
76
79
|
mon1.exec do |nodes|
|
77
80
|
ping_monitor_data
|
78
81
|
end
|
79
82
|
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
properties: mon1.node_properties
|
85
|
-
)
|
86
|
-
response = Arborist::TreeAPI.successful_response( node_tree )
|
83
|
+
expect( reactor ).to receive( :event_enabled? ).with( runner.client.tree_api, :write ).
|
84
|
+
at_least( :once ).
|
85
|
+
and_return( true )
|
86
|
+
|
87
87
|
|
88
|
-
|
89
|
-
|
88
|
+
search_request = instance_double( CZTop::Message )
|
89
|
+
search_response = Arborist::TreeAPI.successful_response( node_tree )
|
90
|
+
update_request = instance_double( CZTop::Message )
|
91
|
+
update_response = Arborist::TreeAPI.successful_response( nil )
|
90
92
|
|
91
|
-
|
93
|
+
expect( CZTop::Message ).to receive( :new ).and_return( search_request, update_request )
|
94
|
+
expect( search_request ).to receive( :send_to ).with( runner.client.tree_api )
|
95
|
+
expect( update_request ).to receive( :send_to ).with( runner.client.tree_api )
|
96
|
+
expect( CZTop::Message ).to receive( :receive_from ).with( runner.client.tree_api ).
|
97
|
+
and_return( search_response, update_response )
|
98
|
+
expect( reactor ).to receive( :disable_events ).with( runner.client.tree_api, :write )
|
92
99
|
|
93
|
-
|
94
|
-
request = runner.client.make_update_request( ping_monitor_data )
|
95
|
-
response = Arborist::TreeAPI.successful_response( nil )
|
96
|
-
expect( runner.client.tree_api ).to receive( :send ).with( request )
|
97
|
-
expect( runner.client.tree_api ).to receive( :recv ).and_return( response )
|
100
|
+
runner.run_monitor( mon1 )
|
98
101
|
|
99
|
-
#
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
}.to change { runner.registered? }.from( true ).to( false )
|
102
|
+
# trigger the search request
|
103
|
+
search_event = instance_double( CZTop::Reactor::Event,
|
104
|
+
writable?: true, socket: runner.client.tree_api )
|
105
|
+
runner.handle_io_event( search_event )
|
104
106
|
|
107
|
+
# trigger the update request
|
108
|
+
update_event = instance_double( CZTop::Reactor::Event,
|
109
|
+
writable?: true, socket: runner.client.tree_api )
|
110
|
+
runner.handle_io_event( update_event )
|
105
111
|
end
|
106
112
|
|
107
113
|
|
@@ -117,25 +123,71 @@ describe Arborist::MonitorRunner do
|
|
117
123
|
nodes = { 'test1' => {}, 'test2' => {} }
|
118
124
|
monitor_results = { 'test1' => {ping: {rtt: 1}}, 'test2' => {ping: {rtt: 8}} }
|
119
125
|
|
120
|
-
expect( runner ).to receive( :
|
126
|
+
expect( runner ).to receive( :search ).
|
121
127
|
with( {type: 'host'}, false, [:addresses], {} ).
|
122
128
|
and_yield( nodes )
|
123
129
|
|
124
130
|
expect( monitor ).to receive( :run ).with( nodes ).
|
125
131
|
and_return( monitor_results )
|
126
132
|
|
127
|
-
expect( runner ).to receive( :update ).
|
128
|
-
|
129
|
-
"test1"=>{:ping=>{:rtt=>1}
|
130
|
-
"test2"=>{:ping=>{:rtt=>8}
|
131
|
-
}
|
133
|
+
expect( runner ).to receive( :update ).with(
|
134
|
+
{
|
135
|
+
"test1"=>{:ping=>{:rtt=>1}},
|
136
|
+
"test2"=>{:ping=>{:rtt=>8}}
|
137
|
+
},
|
138
|
+
:test
|
139
|
+
)
|
132
140
|
|
133
141
|
runner.run_monitor( monitor )
|
134
142
|
end
|
135
143
|
|
136
|
-
end
|
137
144
|
|
145
|
+
it "sets an error condition if the monitor raises an exception" do
|
146
|
+
monitor = Arborist::Monitor.new do
|
147
|
+
description 'test monitor'
|
148
|
+
key :test
|
149
|
+
every 20
|
150
|
+
match type: 'host'
|
151
|
+
use :addresses
|
152
|
+
exec do |nodes|
|
153
|
+
raise "boom!"
|
154
|
+
end
|
155
|
+
end
|
156
|
+
nodes = { 'test' => {} }
|
157
|
+
|
158
|
+
expect( runner ).to receive( :search ).
|
159
|
+
with( {type: 'host'}, false, [:addresses], {} ).
|
160
|
+
and_yield( nodes )
|
138
161
|
|
162
|
+
expect( runner ).to receive( :update ).with(
|
163
|
+
{"test" => {error: 'Exception while running "test monitor" monitor: RuntimeError: boom!'}},
|
164
|
+
:test
|
165
|
+
)
|
166
|
+
|
167
|
+
runner.run_monitor( monitor )
|
168
|
+
end
|
139
169
|
|
170
|
+
|
171
|
+
it "skips the monitor execution if no nodes were returned in the search" do
|
172
|
+
monitor = Arborist::Monitor.new do
|
173
|
+
description 'test monitor'
|
174
|
+
key :test
|
175
|
+
every 20
|
176
|
+
match type: 'host'
|
177
|
+
use :addresses
|
178
|
+
exec 'fping', '-e', '-t', '150'
|
179
|
+
end
|
180
|
+
nodes = {}
|
181
|
+
|
182
|
+
expect( runner ).to receive( :search ).
|
183
|
+
with( {type: 'host'}, false, [:addresses], {} ).
|
184
|
+
and_yield( nodes )
|
185
|
+
|
186
|
+
expect( runner ).to_not receive( :update )
|
187
|
+
runner.run_monitor( monitor )
|
188
|
+
end
|
189
|
+
|
190
|
+
|
191
|
+
end
|
140
192
|
end
|
141
193
|
|
@@ -20,6 +20,7 @@ describe Arborist::Monitor do
|
|
20
20
|
end
|
21
21
|
let( :leaf_node ) do
|
22
22
|
testing_node( 'leaf', 'branch' ) do
|
23
|
+
tags :one, :two
|
23
24
|
properties['pork'] = 'twice'
|
24
25
|
end
|
25
26
|
end
|
@@ -37,7 +38,7 @@ describe Arborist::Monitor do
|
|
37
38
|
expect( mon ).to be_a( described_class )
|
38
39
|
expect( mon.description ).to eq( "the description" )
|
39
40
|
expect( mon.key ).to eq( :key )
|
40
|
-
expect( mon.
|
41
|
+
expect( mon.exclude_down? ).to be_falsey
|
41
42
|
expect( mon.interval ).to eq( Arborist::Monitor::DEFAULT_INTERVAL )
|
42
43
|
expect( mon.splay ).to eq( 0 )
|
43
44
|
expect( mon.positive_criteria ).to be_empty
|
@@ -55,7 +56,7 @@ describe Arborist::Monitor do
|
|
55
56
|
expect( mon ).to be_a( described_class )
|
56
57
|
expect( mon.description ).to eq( "the description" )
|
57
58
|
expect( mon.key ).to eq( :key )
|
58
|
-
expect( mon.
|
59
|
+
expect( mon.exclude_down? ).to be_falsey
|
59
60
|
expect( mon.interval ).to eq( Arborist::Monitor::DEFAULT_INTERVAL )
|
60
61
|
expect( mon.splay ).to eq( 0 )
|
61
62
|
expect( mon.positive_criteria ).to be_empty
|
@@ -72,7 +73,7 @@ describe Arborist::Monitor do
|
|
72
73
|
expect( mon ).to be_a( described_class )
|
73
74
|
expect( mon.description ).to eq( "the description" )
|
74
75
|
expect( mon.key ).to eq( :key )
|
75
|
-
expect( mon.
|
76
|
+
expect( mon.exclude_down? ).to be_falsey
|
76
77
|
expect( mon.interval ).to eq( Arborist::Monitor::DEFAULT_INTERVAL )
|
77
78
|
expect( mon.splay ).to eq( 0 )
|
78
79
|
expect( mon.positive_criteria ).to be_empty
|
@@ -87,7 +88,7 @@ describe Arborist::Monitor do
|
|
87
88
|
expect( mon ).to be_a( described_class )
|
88
89
|
expect( mon.description ).to eq( "the description" )
|
89
90
|
expect( mon.key ).to eq( :the_key )
|
90
|
-
expect( mon.
|
91
|
+
expect( mon.exclude_down? ).to be_falsey
|
91
92
|
expect( mon.interval ).to eq( Arborist::Monitor::DEFAULT_INTERVAL )
|
92
93
|
expect( mon.splay ).to eq( 0 )
|
93
94
|
expect( mon.positive_criteria ).to be_empty
|
@@ -96,12 +97,12 @@ describe Arborist::Monitor do
|
|
96
97
|
end
|
97
98
|
|
98
99
|
|
99
|
-
it "
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
100
|
+
it "uses a default description if constructed without one" do
|
101
|
+
mon = described_class.new do
|
102
|
+
key :key
|
103
|
+
end
|
104
|
+
|
105
|
+
expect( mon.description ).to_not be_empty
|
105
106
|
end
|
106
107
|
|
107
108
|
|
@@ -163,16 +164,16 @@ describe Arborist::Monitor do
|
|
163
164
|
match status: 'down'
|
164
165
|
end
|
165
166
|
|
166
|
-
expect( mon.
|
167
|
+
expect( mon.exclude_down? ).to be_falsey
|
167
168
|
end
|
168
169
|
|
169
170
|
|
170
|
-
it "can specify that it will
|
171
|
+
it "can specify that it will exclude hosts marked as 'down'" do
|
171
172
|
mon = described_class.new( "testing monitor", :testing ) do
|
172
|
-
|
173
|
+
exclude_down true
|
173
174
|
end
|
174
175
|
|
175
|
-
expect( mon.
|
176
|
+
expect( mon.exclude_down? ).to be_truthy
|
176
177
|
end
|
177
178
|
|
178
179
|
|
@@ -230,6 +231,27 @@ describe Arborist::Monitor do
|
|
230
231
|
end
|
231
232
|
|
232
233
|
|
234
|
+
it "uses node properties specified by the runnable object if it provides them" do
|
235
|
+
mod = Module.new do
|
236
|
+
class << self; attr_accessor :was_run ; end
|
237
|
+
@was_run = false
|
238
|
+
|
239
|
+
def self::run( nodes )
|
240
|
+
self.was_run = true
|
241
|
+
end
|
242
|
+
|
243
|
+
def self::node_properties
|
244
|
+
%i[ uri http_method body mimetype ]
|
245
|
+
end
|
246
|
+
end
|
247
|
+
|
248
|
+
mon = described_class.new( "the description", :testing )
|
249
|
+
mon.exec( mod )
|
250
|
+
|
251
|
+
expect( mon.node_properties ).to include( :uri, :http_method, :body, :mimetype )
|
252
|
+
end
|
253
|
+
|
254
|
+
|
233
255
|
it "can provide a function for building arguments for its command" do
|
234
256
|
mon = described_class.new( "the description", :testing ) do
|
235
257
|
|
@@ -257,6 +279,30 @@ describe Arborist::Monitor do
|
|
257
279
|
end
|
258
280
|
|
259
281
|
|
282
|
+
it "stringifies any Array properties with the default exec_input context" do
|
283
|
+
mon = described_class.new( "the description", :testing ) do
|
284
|
+
exec 'the_command'
|
285
|
+
handle_results {|*| }
|
286
|
+
end
|
287
|
+
|
288
|
+
child_stdin, parent_writer = IO.pipe
|
289
|
+
parent_reader, child_stdout = IO.pipe
|
290
|
+
parent_err_reader, child_stderr = IO.pipe
|
291
|
+
|
292
|
+
expect( IO ).to receive( :pipe ).and_return(
|
293
|
+
[ child_stdin, parent_writer ],
|
294
|
+
[ parent_reader, child_stdout ],
|
295
|
+
[ parent_err_reader, child_stderr ]
|
296
|
+
)
|
297
|
+
|
298
|
+
expect( parent_writer ).to receive( :puts ).with match( 'tags=one,two' )
|
299
|
+
expect( Process ).to receive( :spawn ).
|
300
|
+
with( 'the_command', out: child_stdout, in: child_stdin, err: child_stderr )
|
301
|
+
|
302
|
+
mon.run({ leaf: leaf_node.to_h })
|
303
|
+
end
|
304
|
+
|
305
|
+
|
260
306
|
it "handles system call errors while running the monitor command" do
|
261
307
|
mon = described_class.new( "the description", :testing ) do
|
262
308
|
|
@@ -350,5 +396,34 @@ describe Arborist::Monitor do
|
|
350
396
|
expect( results['leaf'] ).to eq({ echoed: 'yep' })
|
351
397
|
end
|
352
398
|
|
399
|
+
|
400
|
+
it "uses node properties specified by the exec_callbacks module if it provides them" do
|
401
|
+
the_module = Module.new do
|
402
|
+
|
403
|
+
def self::node_properties
|
404
|
+
%i[ uri http_method body mimetype ]
|
405
|
+
end
|
406
|
+
|
407
|
+
def exec_input( nodes, writer )
|
408
|
+
writer.puts( nodes.keys )
|
409
|
+
end
|
410
|
+
|
411
|
+
def handle_results( pid, out, err )
|
412
|
+
err.flush
|
413
|
+
return out.each_line.with_object({}) do |line, accum|
|
414
|
+
accum[ line.chomp ] = { echoed: 'yep' }
|
415
|
+
end
|
416
|
+
end
|
417
|
+
|
418
|
+
end
|
419
|
+
|
420
|
+
mon = described_class.new( "the description", :testing ) do
|
421
|
+
exec 'cat'
|
422
|
+
exec_callbacks( the_module )
|
423
|
+
end
|
424
|
+
|
425
|
+
expect( mon.node_properties ).to include( :uri, :http_method, :body, :mimetype )
|
426
|
+
end
|
427
|
+
|
353
428
|
end
|
354
429
|
|
@@ -81,6 +81,35 @@ describe Arborist::Node::Host do
|
|
81
81
|
end
|
82
82
|
|
83
83
|
|
84
|
+
it "can be created with a hostname attribute" do
|
85
|
+
result = described_class.new( 'testhost', hostname: 'example.com' )
|
86
|
+
expect( result.hostname ).to eq( 'example.com')
|
87
|
+
end
|
88
|
+
|
89
|
+
|
90
|
+
it "sets a hostname if unset, and the address was discovered via DNS" do
|
91
|
+
expect( TCPSocket ).to receive( :gethostbyname ).with( 'example.com' ).
|
92
|
+
and_return(['example.com', [], Socket::AF_INET, '1.1.1.1'])
|
93
|
+
result = described_class.new( 'testhost' ) do
|
94
|
+
address 'example.com'
|
95
|
+
end
|
96
|
+
expect( result.addresses ).to include( IPAddr.new('1.1.1.1') )
|
97
|
+
expect( result.hostname ).to eq( 'example.com')
|
98
|
+
end
|
99
|
+
|
100
|
+
|
101
|
+
it "leaves the hostname untouched if already set" do
|
102
|
+
expect( TCPSocket ).to receive( :gethostbyname ).with( 'example.com' ).
|
103
|
+
and_return(['example.com', [], Socket::AF_INET, '1.1.1.1'])
|
104
|
+
result = described_class.new( 'testhost' ) do
|
105
|
+
hostname 'www.example.com'
|
106
|
+
address 'example.com'
|
107
|
+
end
|
108
|
+
expect( result.addresses ).to include( IPAddr.new('1.1.1.1') )
|
109
|
+
expect( result.hostname ).to_not eq( 'example.com')
|
110
|
+
end
|
111
|
+
|
112
|
+
|
84
113
|
it "appends block address arguments to addresses in attributes" do
|
85
114
|
result = described_class.new( 'testhost', addresses: '192.168.118.3' ) do
|
86
115
|
address '127.0.0.1'
|
@@ -116,6 +145,16 @@ describe Arborist::Node::Host do
|
|
116
145
|
end
|
117
146
|
|
118
147
|
|
148
|
+
it "includes its hostname when turned into a Hash" do
|
149
|
+
node = described_class.new( 'testhost' ) do
|
150
|
+
hostname 'example.com'
|
151
|
+
end
|
152
|
+
|
153
|
+
expect( node.to_h ).to include( :hostname )
|
154
|
+
expect( node.to_h[:hostname] ).to eq( 'example.com' )
|
155
|
+
end
|
156
|
+
|
157
|
+
|
119
158
|
it "keeps its addresses when marshalled" do
|
120
159
|
node = described_class.new( 'testhost' ) do
|
121
160
|
address '192.168.118.3'
|
@@ -127,6 +166,16 @@ describe Arborist::Node::Host do
|
|
127
166
|
end
|
128
167
|
|
129
168
|
|
169
|
+
it "keeps its hostname when marshalled" do
|
170
|
+
node = described_class.new( 'testhost' ) do
|
171
|
+
hostname 'example.com'
|
172
|
+
end
|
173
|
+
clone = Marshal.load( Marshal.dump(node) )
|
174
|
+
|
175
|
+
expect( clone.hostname ).to eq( node.hostname )
|
176
|
+
end
|
177
|
+
|
178
|
+
|
130
179
|
it "is equal to another host node with the same metadata and addresses" do
|
131
180
|
node1 = described_class.new( 'testhost' ) do
|
132
181
|
address '192.168.118.3'
|
@@ -154,12 +203,26 @@ describe Arborist::Node::Host do
|
|
154
203
|
end
|
155
204
|
|
156
205
|
|
206
|
+
it "is not equal to another host node with differing hostnames" do
|
207
|
+
node1 = described_class.new( 'testhost' ) do
|
208
|
+
hostname 'example.com'
|
209
|
+
end
|
210
|
+
node2 = described_class.new( 'testhost' ) do
|
211
|
+
hostname 'pets.com'
|
212
|
+
end
|
213
|
+
|
214
|
+
expect( node1 ).to_not eq( node2 )
|
215
|
+
end
|
216
|
+
|
217
|
+
|
218
|
+
|
157
219
|
describe "matching" do
|
158
220
|
|
159
221
|
let( :node ) do
|
160
222
|
described_class.new( 'testhost' ) do
|
161
223
|
address '192.168.66.12'
|
162
224
|
address '10.2.12.68'
|
225
|
+
hostname 'example.com'
|
163
226
|
end
|
164
227
|
end
|
165
228
|
|
@@ -170,6 +233,11 @@ describe Arborist::Node::Host do
|
|
170
233
|
end
|
171
234
|
|
172
235
|
|
236
|
+
it "can be matched on its hostname" do
|
237
|
+
expect( node ).to match_criteria( hostname: 'example.com' )
|
238
|
+
end
|
239
|
+
|
240
|
+
|
173
241
|
it "can be matched with a netblock that includes one of its addresses" do
|
174
242
|
expect( node ).to match_criteria( address: '192.168.66.0/24' )
|
175
243
|
expect( node ).to match_criteria( address: '10.0.0.0/8' )
|