arborist 0.0.1.pre20160128152542 → 0.0.1.pre20160606141735
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 +2 -0
- data/ChangeLog +426 -1
- data/Manifest.txt +17 -2
- data/Nodes.md +70 -0
- data/Protocol.md +68 -9
- data/README.md +3 -5
- data/Rakefile +4 -1
- data/TODO.md +52 -20
- data/lib/arborist.rb +19 -6
- data/lib/arborist/cli.rb +39 -25
- data/lib/arborist/client.rb +97 -4
- data/lib/arborist/command/client.rb +2 -1
- data/lib/arborist/command/start.rb +51 -5
- data/lib/arborist/dependency.rb +286 -0
- data/lib/arborist/event.rb +7 -2
- data/lib/arborist/event/{node_matching.rb → node.rb} +11 -5
- data/lib/arborist/event/node_acked.rb +5 -7
- data/lib/arborist/event/node_delta.rb +30 -3
- data/lib/arborist/event/node_disabled.rb +16 -0
- data/lib/arborist/event/node_down.rb +10 -0
- data/lib/arborist/event/node_quieted.rb +11 -0
- data/lib/arborist/event/node_unknown.rb +10 -0
- data/lib/arborist/event/node_up.rb +10 -0
- data/lib/arborist/event/node_update.rb +2 -11
- data/lib/arborist/event/sys_node_added.rb +10 -0
- data/lib/arborist/event/sys_node_removed.rb +10 -0
- data/lib/arborist/exceptions.rb +4 -0
- data/lib/arborist/manager.rb +188 -18
- data/lib/arborist/manager/event_publisher.rb +1 -1
- data/lib/arborist/manager/tree_api.rb +92 -13
- data/lib/arborist/mixins.rb +17 -0
- data/lib/arborist/monitor.rb +10 -1
- data/lib/arborist/monitor/socket.rb +123 -2
- data/lib/arborist/monitor_runner.rb +6 -5
- data/lib/arborist/node.rb +420 -94
- data/lib/arborist/node/ack.rb +72 -0
- data/lib/arborist/node/host.rb +43 -8
- data/lib/arborist/node/resource.rb +73 -0
- data/lib/arborist/node/root.rb +6 -0
- data/lib/arborist/node/service.rb +89 -22
- data/lib/arborist/observer.rb +1 -1
- data/lib/arborist/subscription.rb +11 -6
- data/spec/arborist/client_spec.rb +93 -5
- data/spec/arborist/dependency_spec.rb +375 -0
- data/spec/arborist/event/node_delta_spec.rb +66 -0
- data/spec/arborist/event/node_down_spec.rb +84 -0
- data/spec/arborist/event/node_spec.rb +59 -0
- data/spec/arborist/event/node_update_spec.rb +14 -3
- data/spec/arborist/event_spec.rb +3 -3
- data/spec/arborist/manager/tree_api_spec.rb +295 -3
- data/spec/arborist/manager_spec.rb +240 -57
- data/spec/arborist/monitor_spec.rb +26 -3
- data/spec/arborist/node/ack_spec.rb +74 -0
- data/spec/arborist/node/host_spec.rb +79 -0
- data/spec/arborist/node/resource_spec.rb +56 -0
- data/spec/arborist/node/service_spec.rb +68 -2
- data/spec/arborist/node_spec.rb +288 -11
- data/spec/arborist/subscription_spec.rb +23 -14
- data/spec/arborist_spec.rb +0 -4
- data/spec/data/observers/webservices.rb +10 -2
- data/spec/spec_helper.rb +8 -0
- metadata +58 -15
- metadata.gz.sig +0 -0
- data/LICENSE +0 -29
@@ -4,10 +4,16 @@ require_relative '../spec_helper'
|
|
4
4
|
|
5
5
|
require 'timecop'
|
6
6
|
require 'arborist/manager'
|
7
|
-
|
7
|
+
require 'arborist/node/host'
|
8
8
|
|
9
9
|
describe Arborist::Manager do
|
10
10
|
|
11
|
+
after( :all ) do
|
12
|
+
Arborist::Manager.state_file = nil
|
13
|
+
end
|
14
|
+
before( :each ) do
|
15
|
+
Arborist::Manager.configure
|
16
|
+
end
|
11
17
|
after( :each ) do
|
12
18
|
Arborist::Node::Root.reset
|
13
19
|
end
|
@@ -49,6 +55,148 @@ describe Arborist::Manager do
|
|
49
55
|
end
|
50
56
|
|
51
57
|
|
58
|
+
describe "state-saving" do
|
59
|
+
|
60
|
+
before( :each ) do
|
61
|
+
Arborist::Manager.state_file = nil
|
62
|
+
end
|
63
|
+
|
64
|
+
let( :router_node ) { Arborist::Host('router') }
|
65
|
+
let( :host_node ) { Arborist::Host( 'host-a', router_node ) }
|
66
|
+
let( :tree ) {[ router_node, host_node ]}
|
67
|
+
|
68
|
+
let( :manager ) do
|
69
|
+
instance = described_class.new
|
70
|
+
instance.load_tree( tree )
|
71
|
+
instance
|
72
|
+
end
|
73
|
+
|
74
|
+
|
75
|
+
it "saves the state of its node tree if the state file is configured" do
|
76
|
+
statefile = Pathname( './arborist.tree' )
|
77
|
+
Arborist::Manager.state_file = statefile
|
78
|
+
|
79
|
+
tempfile = instance_double( Tempfile,
|
80
|
+
path: './arborist20160224-31449-zevoz2.tree', unlink: nil )
|
81
|
+
|
82
|
+
expect( Tempfile ).to receive( :create ).
|
83
|
+
with( ['arborist', '.tree'], '.', encoding: 'binary' ).
|
84
|
+
and_return( tempfile )
|
85
|
+
expect( Marshal ).to receive( :dump ).with( manager.nodes, tempfile )
|
86
|
+
expect( tempfile ).to receive( :close )
|
87
|
+
expect( File ).to receive( :rename ).
|
88
|
+
with( './arborist20160224-31449-zevoz2.tree', './arborist.tree' )
|
89
|
+
|
90
|
+
manager.save_node_states
|
91
|
+
end
|
92
|
+
|
93
|
+
|
94
|
+
it "cleans up the tempfile created by checkpointing if renaming the file fails" do
|
95
|
+
statefile = Pathname( './arborist.tree' )
|
96
|
+
Arborist::Manager.state_file = statefile
|
97
|
+
|
98
|
+
tempfile = instance_double( Tempfile, path: './arborist20160224-31449-zevoz2.tree' )
|
99
|
+
|
100
|
+
expect( Tempfile ).to receive( :create ).
|
101
|
+
with( ['arborist', '.tree'], '.', encoding: 'binary' ).
|
102
|
+
and_return( tempfile )
|
103
|
+
expect( Marshal ).to receive( :dump ).with( manager.nodes, tempfile )
|
104
|
+
expect( tempfile ).to receive( :close )
|
105
|
+
expect( File ).to receive( :rename ).
|
106
|
+
and_raise( Errno::ENOENT.new("no such file or directory") )
|
107
|
+
expect( File ).to receive( :exist? ).with( tempfile.path ).and_return( true )
|
108
|
+
expect( File ).to receive( :unlink ).with( tempfile.path )
|
109
|
+
|
110
|
+
manager.save_node_states
|
111
|
+
end
|
112
|
+
|
113
|
+
|
114
|
+
it "doesn't try to save state if the state file is not configured" do
|
115
|
+
Arborist::Manager.state_file = nil
|
116
|
+
|
117
|
+
expect( Tempfile ).to_not receive( :create )
|
118
|
+
expect( Marshal ).to_not receive( :dump )
|
119
|
+
expect( File ).to_not receive( :rename )
|
120
|
+
|
121
|
+
manager.save_node_states
|
122
|
+
end
|
123
|
+
|
124
|
+
|
125
|
+
it "restores the state of loaded nodes if the state file is configured" do
|
126
|
+
_ = manager
|
127
|
+
|
128
|
+
statefile = Pathname( './arborist.tree' )
|
129
|
+
Arborist::Manager.state_file = statefile
|
130
|
+
state_file_io = instance_double( File )
|
131
|
+
|
132
|
+
saved_router_node = Marshal.load( Marshal.dump(router_node) )
|
133
|
+
saved_router_node.instance_variable_set( :@status, 'up' )
|
134
|
+
saved_host_node = Marshal.load( Marshal.dump(host_node) )
|
135
|
+
saved_host_node.instance_variable_set( :@status, 'down' )
|
136
|
+
saved_host_node.error = 'Stuff happened and it was not good.'
|
137
|
+
|
138
|
+
expect( statefile ).to receive( :readable? ).and_return( true )
|
139
|
+
expect( statefile ).to receive( :open ).with( 'r:binary' ).
|
140
|
+
and_return( state_file_io )
|
141
|
+
expect( Marshal ).to receive( :load ).with( state_file_io ).
|
142
|
+
and_return({ 'router' => saved_router_node, 'host-a' => saved_host_node })
|
143
|
+
|
144
|
+
expect( manager.restore_node_states ).to be_truthy
|
145
|
+
|
146
|
+
expect( manager.nodes['router'].status ).to eq( 'up' )
|
147
|
+
expect( manager.nodes['host-a'].status ).to eq( 'down' )
|
148
|
+
expect( manager.nodes['host-a'].error ).to eq( 'Stuff happened and it was not good.' )
|
149
|
+
|
150
|
+
end
|
151
|
+
|
152
|
+
|
153
|
+
it "doesn't error if the configured state file isn't readable" do
|
154
|
+
_ = manager
|
155
|
+
|
156
|
+
statefile = Pathname( './arborist.tree' )
|
157
|
+
Arborist::Manager.state_file = statefile
|
158
|
+
|
159
|
+
expect( statefile ).to receive( :readable? ).and_return( false )
|
160
|
+
expect( statefile ).to_not receive( :open )
|
161
|
+
|
162
|
+
expect( manager.restore_node_states ).to be_falsey
|
163
|
+
end
|
164
|
+
|
165
|
+
|
166
|
+
it "checkpoints the state file periodically if an interval is configured" do
|
167
|
+
described_class.configure( manager: {checkpoint_frequency: 20, state_file: 'arb.tree'} )
|
168
|
+
|
169
|
+
timer = instance_double( ZMQ::Timer, "checkpoint timer" )
|
170
|
+
expect( ZMQ::Timer ).to receive( :new ).with( 20, 0 ).and_return( timer )
|
171
|
+
|
172
|
+
expect( manager.start_state_checkpointing ).to eq( timer )
|
173
|
+
end
|
174
|
+
|
175
|
+
|
176
|
+
it "doesn't checkpoint if no interval is configured" do
|
177
|
+
described_class.configure( manager: {checkpoint_frequency: nil, state_file: 'arb.tree'} )
|
178
|
+
|
179
|
+
expect( ZMQ::Timer ).to_not receive( :new )
|
180
|
+
|
181
|
+
expect( manager.start_state_checkpointing ).to be_nil
|
182
|
+
end
|
183
|
+
|
184
|
+
|
185
|
+
it "doesn't checkpoint if no state file is configured" do
|
186
|
+
described_class.configure( manager: {checkpoint_frequency: 20, state_file: nil} )
|
187
|
+
|
188
|
+
expect( ZMQ::Timer ).to_not receive( :new )
|
189
|
+
|
190
|
+
expect( manager.start_state_checkpointing ).to be_nil
|
191
|
+
end
|
192
|
+
|
193
|
+
|
194
|
+
it "writes a checkpoint if it receives a SIGUSR1"
|
195
|
+
|
196
|
+
|
197
|
+
end
|
198
|
+
|
199
|
+
|
52
200
|
context "a new empty manager" do
|
53
201
|
|
54
202
|
let( :node ) do
|
@@ -206,16 +354,21 @@ describe Arborist::Manager do
|
|
206
354
|
|
207
355
|
[
|
208
356
|
testing_node( 'router' ),
|
209
|
-
testing_node( '
|
210
|
-
testing_node( '
|
211
|
-
testing_node( '
|
212
|
-
testing_node( '
|
213
|
-
testing_node( '
|
214
|
-
testing_node( '
|
215
|
-
testing_node( '
|
216
|
-
testing_node( '
|
217
|
-
testing_node( '
|
218
|
-
testing_node( '
|
357
|
+
testing_node( 'host-a', 'router' ),
|
358
|
+
testing_node( 'host-a-www', 'host-a' ),
|
359
|
+
testing_node( 'host-a-smtp', 'host-a' ),
|
360
|
+
testing_node( 'host-a-imap', 'host-a' ),
|
361
|
+
testing_node( 'host-b', 'router' ),
|
362
|
+
testing_node( 'host-b-www', 'host-b' ),
|
363
|
+
testing_node( 'host-b-nfs', 'host-b' ),
|
364
|
+
testing_node( 'host-b-ssh', 'host-b' ),
|
365
|
+
testing_node( 'host-c', 'router' ),
|
366
|
+
testing_node( 'host-c-www', 'host-c' ),
|
367
|
+
testing_node( 'host-d', 'router' ),
|
368
|
+
testing_node( 'host-d-ssh', 'host-d' ),
|
369
|
+
testing_node( 'host-d-amqp', 'host-d' ),
|
370
|
+
testing_node( 'host-d-database', 'host-d' ),
|
371
|
+
testing_node( 'host-d-memcached', 'host-d' ),
|
219
372
|
]
|
220
373
|
end
|
221
374
|
|
@@ -234,15 +387,11 @@ describe Arborist::Manager do
|
|
234
387
|
|
235
388
|
|
236
389
|
it "can traverse all nodes whose status is 'up'" do
|
237
|
-
manager.nodes.each {|_, node| node.status =
|
238
|
-
manager.nodes[ '
|
239
|
-
|
240
|
-
manager.nodes[ '
|
241
|
-
|
242
|
-
manager.nodes[ 'host_b_nfs' ].
|
243
|
-
update( ack: {sender: 'nancy_kerrigan', message: 'bad case of disk rot'} )
|
244
|
-
expect( manager.nodes[ 'host_b_nfs' ] ).to be_disabled
|
245
|
-
expect( manager.nodes[ 'host_b_nfs' ] ).to_not be_down
|
390
|
+
manager.nodes.each {|_, node| node.status = 'up' }
|
391
|
+
manager.nodes[ 'host-a' ].status = 'down'
|
392
|
+
manager.nodes[ 'host-c' ].status = 'down'
|
393
|
+
manager.nodes[ 'host-b-nfs' ].status = 'disabled'
|
394
|
+
manager.nodes[ 'host-b-www' ].status = 'quieted'
|
246
395
|
|
247
396
|
iter = manager.reachable_nodes
|
248
397
|
|
@@ -252,23 +401,32 @@ describe Arborist::Manager do
|
|
252
401
|
expect( nodes ).to include(
|
253
402
|
"_",
|
254
403
|
"router",
|
255
|
-
"
|
256
|
-
"
|
257
|
-
"
|
404
|
+
"host-b",
|
405
|
+
"host-b-ssh",
|
406
|
+
"host-d",
|
407
|
+
"host-d-ssh",
|
408
|
+
"host-d-amqp",
|
409
|
+
"host-d-database",
|
410
|
+
"host-d-memcached",
|
258
411
|
)
|
259
412
|
expect( nodes ).to_not include(
|
260
|
-
"
|
261
|
-
"
|
262
|
-
"
|
263
|
-
"
|
264
|
-
|
265
|
-
|
266
|
-
|
413
|
+
"host-b-www",
|
414
|
+
"host-b-nfs",
|
415
|
+
"host-c",
|
416
|
+
"host-c-www",
|
417
|
+
"host-a",
|
418
|
+
"host-a-www",
|
419
|
+
"host-a-smtp",
|
420
|
+
"host-a-imap",
|
267
421
|
)
|
268
422
|
end
|
269
423
|
|
270
424
|
|
271
|
-
it "can create an Enumerator for all of
|
425
|
+
it "can create an Enumerator for all of its children to a specified depth" do
|
426
|
+
nodes = manager.depth_limited_enumerator_for( manager.nodes['_'], 2 ).to_a
|
427
|
+
expect( nodes.length ).to eq( 6 )
|
428
|
+
expect( nodes.map(&:identifier) ).to eq( %w[_ router host-a host-b host-c host-d] )
|
429
|
+
end
|
272
430
|
|
273
431
|
end
|
274
432
|
|
@@ -282,16 +440,16 @@ describe Arborist::Manager do
|
|
282
440
|
|
283
441
|
[
|
284
442
|
testing_node( 'router' ),
|
285
|
-
testing_node( '
|
286
|
-
testing_node( '
|
287
|
-
testing_node( '
|
288
|
-
testing_node( '
|
289
|
-
testing_node( '
|
290
|
-
testing_node( '
|
291
|
-
testing_node( '
|
292
|
-
testing_node( '
|
293
|
-
testing_node( '
|
294
|
-
testing_node( '
|
443
|
+
testing_node( 'host-a', 'router' ),
|
444
|
+
testing_node( 'host-a-www', 'host-a' ) { tags :home, :church },
|
445
|
+
testing_node( 'host-a-smtp', 'host-a' ) { tags :home },
|
446
|
+
testing_node( 'host-a-imap', 'host-a' ),
|
447
|
+
testing_node( 'host-b', 'router' ),
|
448
|
+
testing_node( 'host-b-www', 'host-b' ) { tags :church },
|
449
|
+
testing_node( 'host-b-nfs', 'host-b' ),
|
450
|
+
testing_node( 'host-b-ssh', 'host-b' ) { tags :work },
|
451
|
+
testing_node( 'host-c', 'router' ),
|
452
|
+
testing_node( 'host-c-www', 'host-c' ) { tags :work, :home },
|
295
453
|
]
|
296
454
|
end
|
297
455
|
|
@@ -305,24 +463,50 @@ describe Arborist::Manager do
|
|
305
463
|
it "can fetch a Hash of node states" do
|
306
464
|
states = manager.fetch_matching_node_states( {}, [] )
|
307
465
|
expect( states.size ).to eq( manager.nodes.size )
|
308
|
-
expect( states ).to include( '
|
309
|
-
expect( states['
|
310
|
-
expect( states['
|
466
|
+
expect( states ).to include( 'host-b-nfs', 'host-c', 'router' )
|
467
|
+
expect( states['host-b-nfs'] ).to be_a( Hash )
|
468
|
+
expect( states['host-c'] ).to be_a( Hash )
|
311
469
|
expect( states['router'] ).to be_a( Hash )
|
312
470
|
end
|
313
471
|
|
314
472
|
|
473
|
+
it "can fetch a Hash of node states for nodes which match specified criteria" do
|
474
|
+
states = manager.fetch_matching_node_states( {'identifier' => 'host-c'}, [] )
|
475
|
+
expect( states.size ).to eq( 1 )
|
476
|
+
expect( states.keys.first ).to eq( 'host-c' )
|
477
|
+
expect( states['host-c'] ).to be_a( Hash )
|
478
|
+
end
|
479
|
+
|
480
|
+
|
481
|
+
it "can fetch a Hash of node states for nodes which don't match specified negative criteria" do
|
482
|
+
states = manager.fetch_matching_node_states( {}, [], false, {'identifier' => 'host-c'} )
|
483
|
+
expect( states.size ).to eq( manager.nodes.size - 1 )
|
484
|
+
expect( states ).to_not include( 'host-c' )
|
485
|
+
end
|
486
|
+
|
487
|
+
|
488
|
+
it "can fetch a Hash of node states for nodes combining positive and negative criteria" do
|
489
|
+
positive = {'tag' => 'home'}
|
490
|
+
negative = {'identifier' => 'host-a-www'}
|
491
|
+
|
492
|
+
states = manager.fetch_matching_node_states( positive, [], false, negative )
|
493
|
+
|
494
|
+
expect( states.size ).to eq( 2 )
|
495
|
+
expect( states ).to_not include( 'host-a-www' )
|
496
|
+
end
|
497
|
+
|
498
|
+
|
315
499
|
it "can update an event by identifier" do
|
316
|
-
manager.update_node( '
|
500
|
+
manager.update_node( 'host-b-www', http: { status: 200 } )
|
317
501
|
expect(
|
318
|
-
manager.nodes['
|
502
|
+
manager.nodes['host-b-www'].properties
|
319
503
|
).to include( 'http' => { 'status' => 200 } )
|
320
504
|
end
|
321
505
|
|
322
506
|
|
323
507
|
it "ignores updates to an identifier that is not (any longer) in the tree" do
|
324
508
|
expect {
|
325
|
-
manager.update_node( '
|
509
|
+
manager.update_node( 'host-y', asset_tag: '2by-n86y7t' )
|
326
510
|
}.to_not raise_error
|
327
511
|
end
|
328
512
|
|
@@ -331,10 +515,10 @@ describe Arborist::Manager do
|
|
331
515
|
expect( manager.root ).to receive( :publish_events ).
|
332
516
|
at_least( :once ).
|
333
517
|
and_call_original
|
334
|
-
expect( manager.nodes['
|
518
|
+
expect( manager.nodes['host-c'] ).to receive( :publish_events ).
|
335
519
|
at_least( :once ).
|
336
520
|
and_call_original
|
337
|
-
manager.update_node( '
|
521
|
+
manager.update_node( 'host-c-www', response_status: 504, error: 'Timeout talking to web service.' )
|
338
522
|
end
|
339
523
|
|
340
524
|
|
@@ -342,9 +526,9 @@ describe Arborist::Manager do
|
|
342
526
|
expect( manager.root ).to receive( :publish_events ).
|
343
527
|
at_least( :once ).
|
344
528
|
and_call_original
|
345
|
-
expect( manager.nodes['
|
529
|
+
expect( manager.nodes['host-c'] ).to_not receive( :publish_events )
|
346
530
|
|
347
|
-
manager.update_node( '
|
531
|
+
manager.update_node( 'host-b-www', response_status: 504, error: 'Timeout talking to web service.' )
|
348
532
|
end
|
349
533
|
|
350
534
|
end
|
@@ -352,7 +536,7 @@ describe Arborist::Manager do
|
|
352
536
|
|
353
537
|
describe "subscriptions" do
|
354
538
|
|
355
|
-
let( :tree ) {[ testing_node('
|
539
|
+
let( :tree ) {[ testing_node('host-c') ]}
|
356
540
|
let( :manager ) do
|
357
541
|
instance = described_class.new
|
358
542
|
instance.load_tree( tree )
|
@@ -363,24 +547,24 @@ describe Arborist::Manager do
|
|
363
547
|
it "can attach subscriptions to a node by its identifier" do
|
364
548
|
sub = subid = nil
|
365
549
|
expect {
|
366
|
-
sub = manager.create_subscription( '
|
550
|
+
sub = manager.create_subscription( 'host-c', 'node.update', type: 'host' )
|
367
551
|
}.to change { manager.subscriptions.size }.by( 1 )
|
368
552
|
|
369
553
|
node = manager.subscriptions[ sub.id ]
|
370
554
|
|
371
555
|
expect( sub ).to be_a( Arborist::Subscription )
|
372
|
-
expect( node ).to be( manager.nodes['
|
556
|
+
expect( node ).to be( manager.nodes['host-c'] )
|
373
557
|
end
|
374
558
|
|
375
559
|
|
376
560
|
it "can detach subscriptions from a node given the subscription ID" do
|
377
|
-
sub = manager.create_subscription( '
|
561
|
+
sub = manager.create_subscription( 'host-c', 'node.ack', type: 'service' )
|
378
562
|
rval = nil
|
379
563
|
|
380
564
|
expect {
|
381
565
|
rval = manager.remove_subscription( sub.id )
|
382
566
|
}.to change { manager.subscriptions.size }.by( -1 ).and(
|
383
|
-
change { manager.nodes['
|
567
|
+
change { manager.nodes['host-c'].subscriptions.size }.by( -1 )
|
384
568
|
)
|
385
569
|
|
386
570
|
expect( rval ).to be( sub )
|
@@ -415,7 +599,6 @@ describe Arborist::Manager do
|
|
415
599
|
end
|
416
600
|
|
417
601
|
|
418
|
-
|
419
602
|
it "sets up its sockets with handlers and starts the ZMQ loop when started" do
|
420
603
|
expect( tree_sock ).to receive( :bind ).with( Arborist.tree_api_url )
|
421
604
|
expect( tree_sock ).to receive( :linger= ).with( 0 )
|
@@ -26,9 +26,9 @@ describe Arborist::Monitor do
|
|
26
26
|
|
27
27
|
|
28
28
|
let( :testing_nodes ) {{
|
29
|
-
'trunk' => trunk_node.
|
30
|
-
'branch' => branch_node.
|
31
|
-
'leaf' => leaf_node.
|
29
|
+
'trunk' => trunk_node.to_h,
|
30
|
+
'branch' => branch_node.to_h,
|
31
|
+
'leaf' => leaf_node.to_h
|
32
32
|
}}
|
33
33
|
|
34
34
|
|
@@ -181,6 +181,29 @@ describe Arborist::Monitor do
|
|
181
181
|
end
|
182
182
|
|
183
183
|
|
184
|
+
it "handles system call errors while running the monitor command" do
|
185
|
+
mon = described_class.new( "the description" ) do
|
186
|
+
|
187
|
+
exec 'the_command'
|
188
|
+
|
189
|
+
handle_results {|*| }
|
190
|
+
exec_input {|*| }
|
191
|
+
exec_arguments do |nodes|
|
192
|
+
Loggability[ Arborist ].debug "In the argument-builder."
|
193
|
+
nodes.keys
|
194
|
+
end
|
195
|
+
end
|
196
|
+
|
197
|
+
expect( Process ).to receive( :spawn ) do |*args|
|
198
|
+
raise Errno::EPIPE, "broken pipe"
|
199
|
+
end
|
200
|
+
|
201
|
+
expect {
|
202
|
+
mon.run( testing_nodes )
|
203
|
+
}.to_not raise_error
|
204
|
+
end
|
205
|
+
|
206
|
+
|
184
207
|
it "can provide a function for providing input to its command" do
|
185
208
|
mon = described_class.new( "the description" ) do
|
186
209
|
|