arborist 0.0.1.pre20160128152542 → 0.0.1.pre20160606141735
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 +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
|
|