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
@@ -0,0 +1,59 @@
|
|
1
|
+
#!/usr/bin/env rspec -cfd
|
2
|
+
|
3
|
+
require_relative '../../spec_helper'
|
4
|
+
|
5
|
+
require 'arborist/node'
|
6
|
+
require 'arborist/subscription'
|
7
|
+
require 'arborist/event/node'
|
8
|
+
|
9
|
+
|
10
|
+
describe Arborist::Event::Node do
|
11
|
+
|
12
|
+
let( :node ) do
|
13
|
+
TestNode.new( 'foo' ) do
|
14
|
+
parent 'bar'
|
15
|
+
description "A testing node"
|
16
|
+
tags :yelp, :yank, :yore, :yandex
|
17
|
+
|
18
|
+
update(
|
19
|
+
"tcp_socket_connect" => {
|
20
|
+
"time" => "2016-02-25 16:04:35 -0800",
|
21
|
+
"duration" => 0.020619
|
22
|
+
}
|
23
|
+
)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
let( :event ) { described_class.new(node) }
|
27
|
+
|
28
|
+
|
29
|
+
|
30
|
+
it "matches match-anything subscriptions" do
|
31
|
+
sub = Arborist::Subscription.new {}
|
32
|
+
expect( event ).to match( sub )
|
33
|
+
end
|
34
|
+
|
35
|
+
|
36
|
+
it "matches subscriptions which have matching criteria" do
|
37
|
+
criteria = {
|
38
|
+
tag: node.tags.last,
|
39
|
+
status: node.status
|
40
|
+
}
|
41
|
+
sub = Arborist::Subscription.new( nil, criteria ) {}
|
42
|
+
|
43
|
+
expect( event ).to match( sub )
|
44
|
+
end
|
45
|
+
|
46
|
+
|
47
|
+
it "matches subscriptions which have non-matching negative criteria" do
|
48
|
+
pending "Adding negative criteria to subscriptions"
|
49
|
+
negative_criteria = {
|
50
|
+
tag: 'nope'
|
51
|
+
}
|
52
|
+
sub = Arborist::Subscription.new( nil, {}, negative_criteria ) {}
|
53
|
+
|
54
|
+
expect( event ).to match( sub )
|
55
|
+
end
|
56
|
+
|
57
|
+
|
58
|
+
end
|
59
|
+
|
@@ -41,7 +41,7 @@ describe Arborist::Event::NodeUpdate do
|
|
41
41
|
describe "subscription support" do
|
42
42
|
|
43
43
|
it "matches a subscription with only an event type if the type is the same" do
|
44
|
-
sub = Arborist::Subscription.new(
|
44
|
+
sub = Arborist::Subscription.new( 'node.update' ) {}
|
45
45
|
event = described_class.new( node )
|
46
46
|
|
47
47
|
expect( event ).to match( sub )
|
@@ -49,7 +49,7 @@ describe Arborist::Event::NodeUpdate do
|
|
49
49
|
|
50
50
|
|
51
51
|
it "matches a subscription with a matching event type and matching criteria" do
|
52
|
-
sub = Arborist::Subscription.new(
|
52
|
+
sub = Arborist::Subscription.new( 'node.update', 'tag' => 'chunker' ) {}
|
53
53
|
event = described_class.new( node )
|
54
54
|
|
55
55
|
expect( event ).to match( sub )
|
@@ -57,7 +57,7 @@ describe Arborist::Event::NodeUpdate do
|
|
57
57
|
|
58
58
|
|
59
59
|
it "doesn't match a subscription with a matching event type if the criteria don't match" do
|
60
|
-
sub = Arborist::Subscription.new(
|
60
|
+
sub = Arborist::Subscription.new( 'node.update', 'tag' => 'looper' ) {}
|
61
61
|
event = described_class.new( node )
|
62
62
|
|
63
63
|
expect( event ).to_not match( sub )
|
@@ -67,5 +67,16 @@ describe Arborist::Event::NodeUpdate do
|
|
67
67
|
end
|
68
68
|
|
69
69
|
|
70
|
+
describe "payload" do
|
71
|
+
|
72
|
+
it "includes its attributes" do
|
73
|
+
event = described_class.new( node )
|
74
|
+
|
75
|
+
expect( event.payload ).to be_a( Hash )
|
76
|
+
expect( event.payload ).to include( :status, :properties, :type )
|
77
|
+
end
|
78
|
+
|
79
|
+
end
|
80
|
+
|
70
81
|
end
|
71
82
|
|
data/spec/arborist/event_spec.rb
CHANGED
@@ -26,7 +26,7 @@ describe Arborist::Event do
|
|
26
26
|
describe "subscription support" do
|
27
27
|
|
28
28
|
it "matches a subscription with only an event type if the type is the same" do
|
29
|
-
sub = Arborist::Subscription.new(
|
29
|
+
sub = Arborist::Subscription.new( 'test.event' ) {}
|
30
30
|
event = described_class.create( TestEvent, [] )
|
31
31
|
|
32
32
|
expect( event ).to match( sub )
|
@@ -34,7 +34,7 @@ describe Arborist::Event do
|
|
34
34
|
|
35
35
|
|
36
36
|
it "always matches a subscription with a nil event type" do
|
37
|
-
sub = Arborist::Subscription.new
|
37
|
+
sub = Arborist::Subscription.new {}
|
38
38
|
event = described_class.create( TestEvent, [] )
|
39
39
|
|
40
40
|
expect( event ).to match( sub )
|
@@ -49,7 +49,7 @@ describe Arborist::Event do
|
|
49
49
|
payload = { 'status' => ['up', 'down'] }
|
50
50
|
ev = TestEvent.create( TestEvent, payload )
|
51
51
|
|
52
|
-
result = ev.
|
52
|
+
result = ev.to_h
|
53
53
|
|
54
54
|
expect( result ).to include( 'type', 'data' )
|
55
55
|
|
@@ -122,14 +122,14 @@ describe Arborist::Manager::TreeAPI, :testing_manager do
|
|
122
122
|
end
|
123
123
|
|
124
124
|
|
125
|
-
it "send an error response if the request's body is not a Map or
|
125
|
+
it "send an error response if the request's body is not Nil, a Map, or an Array of Maps" do
|
126
126
|
sock.send( MessagePack.pack([{version: 1, action: 'list'}, 18]) )
|
127
127
|
resmsg = sock.recv
|
128
128
|
|
129
129
|
hdr, body = unpack_message( resmsg )
|
130
130
|
expect( hdr ).to include(
|
131
131
|
'success' => false,
|
132
|
-
'reason' => /invalid request.*body must be a map or
|
132
|
+
'reason' => /invalid request.*body must be nil, a map, or an array of maps/i,
|
133
133
|
'category' => 'client'
|
134
134
|
)
|
135
135
|
expect( body ).to be_nil
|
@@ -217,6 +217,40 @@ describe Arborist::Manager::TreeAPI, :testing_manager do
|
|
217
217
|
end
|
218
218
|
|
219
219
|
|
220
|
+
it "returns an array of full state maps for nodes not matching specified negative criteria" do
|
221
|
+
msg = pack_message( :fetch, [ {}, {type: 'service', port: 22} ] )
|
222
|
+
|
223
|
+
sock.send( msg )
|
224
|
+
resmsg = sock.recv
|
225
|
+
|
226
|
+
hdr, body = unpack_message( resmsg )
|
227
|
+
expect( hdr ).to include( 'success' => true )
|
228
|
+
|
229
|
+
expect( body ).to be_a( Hash )
|
230
|
+
expect( body.length ).to eq( manager.nodes.length - 3 )
|
231
|
+
|
232
|
+
expect( body.values ).to all( be_a(Hash) )
|
233
|
+
expect( body.values ).to all( include('status', 'type') )
|
234
|
+
end
|
235
|
+
|
236
|
+
|
237
|
+
it "returns an array of full state maps for nodes combining positive and negative criteria" do
|
238
|
+
msg = pack_message( :fetch, [ {type: 'service'}, {port: 22} ] )
|
239
|
+
|
240
|
+
sock.send( msg )
|
241
|
+
resmsg = sock.recv
|
242
|
+
|
243
|
+
hdr, body = unpack_message( resmsg )
|
244
|
+
expect( hdr ).to include( 'success' => true )
|
245
|
+
|
246
|
+
expect( body ).to be_a( Hash )
|
247
|
+
expect( body.length ).to eq( 16 )
|
248
|
+
|
249
|
+
expect( body.values ).to all( be_a(Hash) )
|
250
|
+
expect( body.values ).to all( include('status', 'type') )
|
251
|
+
end
|
252
|
+
|
253
|
+
|
220
254
|
it "doesn't return nodes beneath downed nodes by default" do
|
221
255
|
manager.nodes['sidonie'].update( error: 'sunspots' )
|
222
256
|
msg = pack_message( :fetch, type: 'service', port: 22 )
|
@@ -276,6 +310,7 @@ describe Arborist::Manager::TreeAPI, :testing_manager do
|
|
276
310
|
expect( body.values.map(&:keys) ).to all( contain_exactly('status', 'tags', 'addresses') )
|
277
311
|
end
|
278
312
|
|
313
|
+
|
279
314
|
end
|
280
315
|
|
281
316
|
|
@@ -292,11 +327,25 @@ describe Arborist::Manager::TreeAPI, :testing_manager do
|
|
292
327
|
expect( body ).to all( be_a(Hash) )
|
293
328
|
expect( body ).to include( hash_including('identifier' => '_') )
|
294
329
|
expect( body ).to include( hash_including('identifier' => 'duir') )
|
330
|
+
expect( body ).to include( hash_including('identifier' => 'sidonie') )
|
295
331
|
expect( body ).to include( hash_including('identifier' => 'sidonie-ssh') )
|
296
332
|
expect( body ).to include( hash_including('identifier' => 'sidonie-demon-http') )
|
297
333
|
expect( body ).to include( hash_including('identifier' => 'yevaud') )
|
298
334
|
end
|
299
335
|
|
336
|
+
it "can be limited by depth" do
|
337
|
+
msg = pack_message( :list, {depth: 1}, nil )
|
338
|
+
sock.send( msg )
|
339
|
+
resmsg = sock.recv
|
340
|
+
|
341
|
+
hdr, body = unpack_message( resmsg )
|
342
|
+
expect( hdr ).to include( 'success' => true )
|
343
|
+
expect( body.length ).to eq( 3 )
|
344
|
+
expect( body ).to all( be_a(Hash) )
|
345
|
+
expect( body ).to include( hash_including('identifier' => '_') )
|
346
|
+
expect( body ).to include( hash_including('identifier' => 'duir') )
|
347
|
+
expect( body ).to_not include( hash_including('identifier' => 'duir-ssh') )
|
348
|
+
end
|
300
349
|
end
|
301
350
|
|
302
351
|
|
@@ -456,4 +505,247 @@ describe Arborist::Manager::TreeAPI, :testing_manager do
|
|
456
505
|
|
457
506
|
end
|
458
507
|
|
459
|
-
|
508
|
+
|
509
|
+
describe "prune" do
|
510
|
+
|
511
|
+
it "removes a single node" do
|
512
|
+
msg = pack_message( :prune, {identifier: 'duir-ssh'}, nil )
|
513
|
+
sock.send( msg )
|
514
|
+
resmsg = sock.recv
|
515
|
+
|
516
|
+
hdr, body = unpack_message( resmsg )
|
517
|
+
expect( hdr ).to include( 'success' => true )
|
518
|
+
expect( body ).to eq( true )
|
519
|
+
expect( manager.nodes ).to_not include( 'duir-ssh' )
|
520
|
+
end
|
521
|
+
|
522
|
+
|
523
|
+
it "returns Nil without error if the node to prune didn't exist" do
|
524
|
+
msg = pack_message( :prune, {identifier: 'shemp-ssh'}, nil )
|
525
|
+
sock.send( msg )
|
526
|
+
resmsg = sock.recv
|
527
|
+
|
528
|
+
hdr, body = unpack_message( resmsg )
|
529
|
+
expect( hdr ).to include( 'success' => true )
|
530
|
+
expect( body ).to be_nil
|
531
|
+
end
|
532
|
+
|
533
|
+
|
534
|
+
it "removes children nodes along with the parent" do
|
535
|
+
msg = pack_message( :prune, {identifier: 'duir'}, nil )
|
536
|
+
sock.send( msg )
|
537
|
+
resmsg = sock.recv
|
538
|
+
|
539
|
+
hdr, body = unpack_message( resmsg )
|
540
|
+
expect( hdr ).to include( 'success' => true )
|
541
|
+
expect( body ).to eq( true )
|
542
|
+
expect( manager.nodes ).to_not include( 'duir' )
|
543
|
+
expect( manager.nodes ).to_not include( 'duir-ssh' )
|
544
|
+
end
|
545
|
+
|
546
|
+
|
547
|
+
it "returns an error to the client when missing required attributes" do
|
548
|
+
msg = pack_message( :prune )
|
549
|
+
sock.send( msg )
|
550
|
+
resmsg = sock.recv
|
551
|
+
|
552
|
+
hdr, body = unpack_message( resmsg )
|
553
|
+
expect( hdr ).to include( 'success' => false )
|
554
|
+
expect( hdr['reason'] ).to match( /no identifier/i )
|
555
|
+
end
|
556
|
+
end
|
557
|
+
|
558
|
+
|
559
|
+
describe "graft" do
|
560
|
+
|
561
|
+
it "can add a node with no explicit parent" do
|
562
|
+
header = {
|
563
|
+
identifier: 'guenter',
|
564
|
+
type: 'host',
|
565
|
+
}
|
566
|
+
attributes = {
|
567
|
+
description: 'The evil penguin node of doom.',
|
568
|
+
addresses: ['10.2.66.8'],
|
569
|
+
tags: ['internal', 'football']
|
570
|
+
}
|
571
|
+
msg = pack_message( :graft, header, attributes )
|
572
|
+
|
573
|
+
sock.send( msg )
|
574
|
+
resmsg = sock.recv
|
575
|
+
|
576
|
+
hdr, body = unpack_message( resmsg )
|
577
|
+
expect( hdr ).to include( 'success' => true )
|
578
|
+
expect( body ).to eq( 'guenter' )
|
579
|
+
|
580
|
+
new_node = manager.nodes[ 'guenter' ]
|
581
|
+
expect( new_node ).to be_a( Arborist::Node::Host )
|
582
|
+
expect( new_node.identifier ).to eq( header[:identifier] )
|
583
|
+
expect( new_node.description ).to eq( attributes[:description] )
|
584
|
+
expect( new_node.addresses ).to eq([ IPAddr.new(attributes[:addresses].first) ])
|
585
|
+
expect( new_node.tags ).to include( *attributes[:tags] )
|
586
|
+
end
|
587
|
+
|
588
|
+
|
589
|
+
it "can add a node with a parent specified" do
|
590
|
+
header = {
|
591
|
+
identifier: 'orgalorg',
|
592
|
+
type: 'host',
|
593
|
+
parent: 'duir'
|
594
|
+
}
|
595
|
+
attributes = {
|
596
|
+
description: 'The true form of the evil penguin node of doom.',
|
597
|
+
addresses: ['192.168.22.8'],
|
598
|
+
tags: ['evil', 'space', 'entity']
|
599
|
+
}
|
600
|
+
msg = pack_message( :graft, header, attributes )
|
601
|
+
|
602
|
+
sock.send( msg )
|
603
|
+
resmsg = sock.recv
|
604
|
+
|
605
|
+
hdr, body = unpack_message( resmsg )
|
606
|
+
expect( hdr ).to include( 'success' => true )
|
607
|
+
expect( body ).to eq( 'orgalorg' )
|
608
|
+
|
609
|
+
new_node = manager.nodes[ 'orgalorg' ]
|
610
|
+
expect( new_node ).to be_a( Arborist::Node::Host )
|
611
|
+
expect( new_node.identifier ).to eq( header[:identifier] )
|
612
|
+
expect( new_node.parent ).to eq( header[:parent] )
|
613
|
+
expect( new_node.description ).to eq( attributes[:description] )
|
614
|
+
expect( new_node.addresses ).to eq([ IPAddr.new(attributes[:addresses].first) ])
|
615
|
+
expect( new_node.tags ).to include( *attributes[:tags] )
|
616
|
+
end
|
617
|
+
|
618
|
+
|
619
|
+
it "can add a subordinate node" do
|
620
|
+
header = {
|
621
|
+
identifier: 'echo',
|
622
|
+
type: 'service',
|
623
|
+
parent: 'duir'
|
624
|
+
}
|
625
|
+
attributes = {
|
626
|
+
description: 'Mmmmm AppleTalk.'
|
627
|
+
}
|
628
|
+
msg = pack_message( :graft, header, attributes )
|
629
|
+
|
630
|
+
sock.send( msg )
|
631
|
+
resmsg = sock.recv
|
632
|
+
|
633
|
+
hdr, body = unpack_message( resmsg )
|
634
|
+
expect( hdr ).to include( 'success' => true )
|
635
|
+
expect( body ).to eq( 'duir-echo' )
|
636
|
+
|
637
|
+
new_node = manager.nodes[ 'duir-echo' ]
|
638
|
+
expect( new_node ).to be_a( Arborist::Node::Service )
|
639
|
+
expect( new_node.identifier ).to eq( 'duir-echo' )
|
640
|
+
expect( new_node.parent ).to eq( header[:parent] )
|
641
|
+
expect( new_node.description ).to eq( attributes[:description] )
|
642
|
+
expect( new_node.port ).to eq( 7 )
|
643
|
+
expect( new_node.protocol ).to eq( 'tcp' )
|
644
|
+
expect( new_node.app_protocol ).to eq( 'echo' )
|
645
|
+
end
|
646
|
+
|
647
|
+
|
648
|
+
it "errors if adding a subordinate node with no parent" do
|
649
|
+
header = {
|
650
|
+
identifier: 'echo',
|
651
|
+
type: 'service'
|
652
|
+
}
|
653
|
+
attributes = {
|
654
|
+
description: 'Mmmmm AppleTalk.'
|
655
|
+
}
|
656
|
+
msg = pack_message( :graft, header, attributes )
|
657
|
+
|
658
|
+
sock.send( msg )
|
659
|
+
resmsg = sock.recv
|
660
|
+
|
661
|
+
hdr, body = unpack_message( resmsg )
|
662
|
+
expect( hdr ).to include( 'success' => false )
|
663
|
+
expect( hdr['reason'] ).to match( /no host given/i )
|
664
|
+
end
|
665
|
+
|
666
|
+
end
|
667
|
+
|
668
|
+
|
669
|
+
describe "modify" do
|
670
|
+
|
671
|
+
it "can change operational attributes of a node" do
|
672
|
+
header = {
|
673
|
+
identifier: 'sidonie',
|
674
|
+
}
|
675
|
+
attributes = {
|
676
|
+
parent: '_',
|
677
|
+
addresses: ['192.168.32.32', '10.2.2.28']
|
678
|
+
}
|
679
|
+
msg = pack_message( :modify, header, attributes )
|
680
|
+
|
681
|
+
sock.send( msg )
|
682
|
+
resmsg = sock.recv
|
683
|
+
|
684
|
+
hdr, body = unpack_message( resmsg )
|
685
|
+
expect( hdr ).to include( 'success' => true )
|
686
|
+
|
687
|
+
node = manager.nodes[ 'sidonie' ]
|
688
|
+
expect(
|
689
|
+
node.addresses
|
690
|
+
).to eq( [IPAddr.new('192.168.32.32'), IPAddr.new('10.2.2.28')] )
|
691
|
+
expect( node.parent ).to eq( '_' )
|
692
|
+
end
|
693
|
+
|
694
|
+
|
695
|
+
it "ignores modifications to unsupported attributes" do
|
696
|
+
header = {
|
697
|
+
identifier: 'sidonie',
|
698
|
+
}
|
699
|
+
attributes = {
|
700
|
+
identifier: 'somethingelse'
|
701
|
+
}
|
702
|
+
msg = pack_message( :modify, header, attributes )
|
703
|
+
|
704
|
+
sock.send( msg )
|
705
|
+
resmsg = sock.recv
|
706
|
+
|
707
|
+
hdr, body = unpack_message( resmsg )
|
708
|
+
expect( hdr ).to include( 'success' => true )
|
709
|
+
|
710
|
+
expect( manager.nodes['sidonie'] ).to be_an( Arborist::Node )
|
711
|
+
expect( manager.nodes['sidonie'].identifier ).to eq( 'sidonie' )
|
712
|
+
end
|
713
|
+
|
714
|
+
|
715
|
+
it "errors on modifications to the root node" do
|
716
|
+
header = {
|
717
|
+
identifier: '_',
|
718
|
+
}
|
719
|
+
attributes = {
|
720
|
+
identifier: 'somethingelse'
|
721
|
+
}
|
722
|
+
msg = pack_message( :modify, header, attributes )
|
723
|
+
|
724
|
+
sock.send( msg )
|
725
|
+
resmsg = sock.recv
|
726
|
+
|
727
|
+
hdr, body = unpack_message( resmsg )
|
728
|
+
expect( hdr ).to include( 'success' => false )
|
729
|
+
expect( manager.nodes['_'].identifier ).to eq( '_' )
|
730
|
+
end
|
731
|
+
|
732
|
+
|
733
|
+
it "errors on modifications to nonexistent nodes" do
|
734
|
+
header = {
|
735
|
+
identifier: 'nopenopenope',
|
736
|
+
}
|
737
|
+
attributes = {
|
738
|
+
identifier: 'somethingelse'
|
739
|
+
}
|
740
|
+
msg = pack_message( :modify, header, attributes )
|
741
|
+
|
742
|
+
sock.send( msg )
|
743
|
+
resmsg = sock.recv
|
744
|
+
|
745
|
+
hdr, body = unpack_message( resmsg )
|
746
|
+
expect( hdr ).to include( 'success' => false )
|
747
|
+
end
|
748
|
+
end
|
749
|
+
|
750
|
+
end
|
751
|
+
|