arborist 0.0.1.pre20160606141735 → 0.0.1.pre20160829140603
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
- data/ChangeLog +81 -2
- data/Events.md +11 -11
- data/Manifest.txt +2 -4
- data/TODO.md +9 -29
- data/lib/arborist.rb +6 -2
- data/lib/arborist/command/watch.rb +59 -8
- data/lib/arborist/loader/file.rb +1 -1
- data/lib/arborist/manager.rb +139 -50
- data/lib/arborist/manager/event_publisher.rb +29 -0
- data/lib/arborist/manager/tree_api.rb +16 -1
- data/lib/arborist/mixins.rb +36 -1
- data/lib/arborist/monitor.rb +12 -0
- data/lib/arborist/monitor/socket.rb +8 -9
- data/lib/arborist/monitor_runner.rb +2 -2
- data/lib/arborist/node.rb +16 -3
- data/lib/arborist/node/host.rb +25 -22
- data/lib/arborist/node/resource.rb +28 -14
- data/lib/arborist/node/service.rb +21 -2
- data/lib/arborist/observer_runner.rb +68 -7
- data/spec/arborist/client_spec.rb +3 -3
- data/spec/arborist/manager/event_publisher_spec.rb +0 -1
- data/spec/arborist/manager/tree_api_spec.rb +6 -5
- data/spec/arborist/manager_spec.rb +53 -24
- data/spec/arborist/node/resource_spec.rb +9 -0
- data/spec/arborist/node/service_spec.rb +16 -1
- data/spec/arborist/node_spec.rb +22 -12
- data/spec/arborist/observer_runner_spec.rb +58 -0
- data/spec/arborist/observer_spec.rb +15 -15
- data/spec/arborist/subscription_spec.rb +1 -1
- data/spec/data/nodes/{duir.rb → sub/duir.rb} +0 -0
- data/spec/data/observers/auditor.rb +2 -2
- data/spec/spec_helper.rb +1 -0
- metadata +30 -27
- checksums.yaml.gz.sig +0 -0
- data.tar.gz.sig +0 -2
- data/lib/arborist/event/sys_node_added.rb +0 -10
- data/lib/arborist/event/sys_node_removed.rb +0 -10
- data/lib/arborist/event/sys_reloaded.rb +0 -15
- metadata.gz.sig +0 -0
@@ -7,11 +7,13 @@ require 'socket'
|
|
7
7
|
|
8
8
|
require 'arborist/node'
|
9
9
|
require 'arborist/mixins'
|
10
|
+
require 'arborist/exceptions'
|
10
11
|
|
11
12
|
|
12
13
|
# A node type for Arborist trees that represent services running on hosts.
|
13
14
|
class Arborist::Node::Service < Arborist::Node
|
14
|
-
include Arborist::HashUtilities
|
15
|
+
include Arborist::HashUtilities,
|
16
|
+
Arborist::NetworkUtilities
|
15
17
|
|
16
18
|
|
17
19
|
# The default transport layer protocol to use for services that don't specify
|
@@ -29,6 +31,7 @@ class Arborist::Node::Service < Arborist::Node
|
|
29
31
|
qualified_identifier = "%s-%s" % [ host.identifier, identifier ]
|
30
32
|
|
31
33
|
@host = host
|
34
|
+
@addresses = nil
|
32
35
|
@app_protocol = nil
|
33
36
|
@protocol = nil
|
34
37
|
@port = nil
|
@@ -84,9 +87,25 @@ class Arborist::Node::Service < Arborist::Node
|
|
84
87
|
end
|
85
88
|
|
86
89
|
|
90
|
+
### Set an IP address of the service. This must be one of the addresses of its
|
91
|
+
### containing host.
|
92
|
+
def address( new_address )
|
93
|
+
self.log.debug "Adding address %p to %p" % [ new_address, self ]
|
94
|
+
normalized_addresses = normalize_address( new_address )
|
95
|
+
|
96
|
+
unless normalized_addresses.all? {|addr| @host.addresses.include?(addr) }
|
97
|
+
raise Arborist::ConfigError, "%s is not one of %s's addresses" %
|
98
|
+
[ new_address, @host.identifier ]
|
99
|
+
end
|
100
|
+
|
101
|
+
@addresses ||= []
|
102
|
+
@addresses += normalized_addresses
|
103
|
+
end
|
104
|
+
|
105
|
+
|
87
106
|
### Delegate the service's address to its host.
|
88
107
|
def addresses
|
89
|
-
return @host.addresses
|
108
|
+
return @addresses || @host.addresses
|
90
109
|
end
|
91
110
|
|
92
111
|
|
@@ -31,7 +31,8 @@ class Arborist::ObserverRunner
|
|
31
31
|
|
32
32
|
### Create a ZMQ::Handler that acts as the agent that runs the specified
|
33
33
|
### +observer+.
|
34
|
-
def initialize( reactor )
|
34
|
+
def initialize( runner, reactor )
|
35
|
+
@runner = runner
|
35
36
|
@client = Arborist::Client.new
|
36
37
|
@pollitem = ZMQ::Pollitem.new( @client.event_api, ZMQ::POLLIN )
|
37
38
|
@pollitem.handler = self
|
@@ -45,6 +46,9 @@ class Arborist::ObserverRunner
|
|
45
46
|
public
|
46
47
|
######
|
47
48
|
|
49
|
+
# The Arborist::ObserverRunner that owns this handler.
|
50
|
+
attr_reader :runner
|
51
|
+
|
48
52
|
# The Arborist::Client that will be used for creating and tearing down subscriptions
|
49
53
|
attr_reader :client
|
50
54
|
|
@@ -52,6 +56,16 @@ class Arborist::ObserverRunner
|
|
52
56
|
attr_reader :subscriptions
|
53
57
|
|
54
58
|
|
59
|
+
### Unsubscribe from and clear all current subscriptions.
|
60
|
+
def reset
|
61
|
+
self.log.warn "Resetting the observer handler."
|
62
|
+
self.subscriptions.keys.each do |subid|
|
63
|
+
self.client.event_api.unsubscribe( subid )
|
64
|
+
end
|
65
|
+
self.subscriptions.clear
|
66
|
+
end
|
67
|
+
|
68
|
+
|
55
69
|
### Add the specified +observer+ and subscribe to the events it wishes to receive.
|
56
70
|
def add_observer( observer )
|
57
71
|
self.log.info "Adding observer: %s" % [ observer.description ]
|
@@ -85,10 +99,13 @@ class Arborist::ObserverRunner
|
|
85
99
|
subid = self.recv
|
86
100
|
raise "Partial write?!" unless self.pollitem.pollable.rcvmore?
|
87
101
|
raw_event = self.recv
|
102
|
+
event = MessagePack.unpack( raw_event )
|
88
103
|
|
89
104
|
if (( observer = self.subscriptions[subid] ))
|
90
|
-
event = MessagePack.unpack( raw_event )
|
91
105
|
observer.handle_event( subid, event )
|
106
|
+
elsif subid.start_with?( 'sys.' )
|
107
|
+
self.log.debug "System event! %p" % [ event ]
|
108
|
+
self.runner.handle_system_event( subid, event )
|
92
109
|
else
|
93
110
|
self.log.warn "Ignoring event %p for which we have no observer." % [ subid ]
|
94
111
|
end
|
@@ -105,6 +122,7 @@ class Arborist::ObserverRunner
|
|
105
122
|
@timers = []
|
106
123
|
@handler = nil
|
107
124
|
@reactor = ZMQ::Loop.new
|
125
|
+
@manager_last_runid = nil
|
108
126
|
end
|
109
127
|
|
110
128
|
|
@@ -133,12 +151,11 @@ class Arborist::ObserverRunner
|
|
133
151
|
|
134
152
|
### Run the specified +observers+
|
135
153
|
def run
|
136
|
-
self.handler = Arborist::ObserverRunner::Handler.new( self.reactor )
|
154
|
+
self.handler = Arborist::ObserverRunner::Handler.new( self, self.reactor )
|
137
155
|
|
138
|
-
self.
|
139
|
-
|
140
|
-
|
141
|
-
end
|
156
|
+
self.register_observers
|
157
|
+
self.register_observer_timers
|
158
|
+
self.subscribe_to_system_events
|
142
159
|
|
143
160
|
self.reactor.start
|
144
161
|
rescue Interrupt
|
@@ -158,6 +175,28 @@ class Arborist::ObserverRunner
|
|
158
175
|
end
|
159
176
|
|
160
177
|
|
178
|
+
### Register each of the runner's Observers with its handler.
|
179
|
+
def register_observers
|
180
|
+
self.observers.each do |observer|
|
181
|
+
self.handler.add_observer( observer )
|
182
|
+
end
|
183
|
+
end
|
184
|
+
|
185
|
+
|
186
|
+
### Register timers for each Observer.
|
187
|
+
def register_observer_timers
|
188
|
+
self.observers.each do |observer|
|
189
|
+
self.add_timers_for( observer )
|
190
|
+
end
|
191
|
+
end
|
192
|
+
|
193
|
+
|
194
|
+
### Subscribe the runner to system events published by the Manager.
|
195
|
+
def subscribe_to_system_events
|
196
|
+
self.handler.client.event_api.subscribe( 'sys.' )
|
197
|
+
end
|
198
|
+
|
199
|
+
|
161
200
|
### Register a timer for the specified +observer+.
|
162
201
|
def add_timers_for( observer )
|
163
202
|
observer.timers.each do |interval, callback|
|
@@ -177,5 +216,27 @@ class Arborist::ObserverRunner
|
|
177
216
|
end
|
178
217
|
end
|
179
218
|
|
219
|
+
|
220
|
+
### Handle a `sys.` event from the Manager being observed.
|
221
|
+
def handle_system_event( event_type, event )
|
222
|
+
self.log.debug "Got a %s event from the Manager: %p" % [ event_type, event ]
|
223
|
+
|
224
|
+
case event_type
|
225
|
+
when 'sys.heartbeat'
|
226
|
+
this_runid = event['run_id']
|
227
|
+
if @manager_last_runid && this_runid != @manager_last_runid
|
228
|
+
self.log.warn "Manager run ID changed: re-subscribing"
|
229
|
+
self.handler.reset
|
230
|
+
self.register_observers
|
231
|
+
end
|
232
|
+
|
233
|
+
@manager_last_runid = this_runid
|
234
|
+
when 'sys.node_added', 'sys.node_removed'
|
235
|
+
# no-op
|
236
|
+
else
|
237
|
+
# no-op
|
238
|
+
end
|
239
|
+
end
|
240
|
+
|
180
241
|
end # class Arborist::ObserverRunner
|
181
242
|
|
@@ -12,15 +12,15 @@ describe Arborist::Client do
|
|
12
12
|
describe "synchronous API", :testing_manager do
|
13
13
|
|
14
14
|
before( :each ) do
|
15
|
-
@manager = make_testing_manager()
|
16
15
|
@manager_thread = Thread.new do
|
16
|
+
@manager = make_testing_manager()
|
17
17
|
Thread.current.abort_on_exception = true
|
18
18
|
@manager.run
|
19
19
|
Loggability[ Arborist ].info "Stopped the test manager"
|
20
20
|
end
|
21
21
|
|
22
22
|
count = 0
|
23
|
-
until @manager.running? || count > 30
|
23
|
+
until (@manager && @manager.running?) || count > 30
|
24
24
|
sleep 0.1
|
25
25
|
count += 1
|
26
26
|
end
|
@@ -28,7 +28,7 @@ describe Arborist::Client do
|
|
28
28
|
end
|
29
29
|
|
30
30
|
after( :each ) do
|
31
|
-
@manager.
|
31
|
+
@manager.simulate_signal( :TERM )
|
32
32
|
@manager_thread.join
|
33
33
|
|
34
34
|
count = 0
|
@@ -6,23 +6,24 @@ require_relative '../../spec_helper'
|
|
6
6
|
describe Arborist::Manager::TreeAPI, :testing_manager do
|
7
7
|
|
8
8
|
before( :each ) do
|
9
|
-
@manager =
|
9
|
+
@manager = nil
|
10
10
|
@manager_thread = Thread.new do
|
11
|
+
@manager = make_testing_manager()
|
11
12
|
Thread.current.abort_on_exception = true
|
12
|
-
manager.run
|
13
|
+
@manager.run
|
13
14
|
Loggability[ Arborist ].info "Stopped the test manager"
|
14
15
|
end
|
15
16
|
|
16
17
|
count = 0
|
17
|
-
until manager.running? || count > 30
|
18
|
+
until (@manager && @manager.running?) || count > 30
|
18
19
|
sleep 0.1
|
19
20
|
count += 1
|
20
21
|
end
|
21
|
-
raise "Manager didn't start up" unless manager.running?
|
22
|
+
raise "Manager didn't start up" unless @manager.running?
|
22
23
|
end
|
23
24
|
|
24
25
|
after( :each ) do
|
25
|
-
@manager.
|
26
|
+
@manager.simulate_signal( :TERM )
|
26
27
|
unless @manager_thread.join( 5 )
|
27
28
|
$stderr.puts "Manager thread didn't exit on its own; killing it."
|
28
29
|
@manager_thread.kill
|
@@ -164,30 +164,32 @@ describe Arborist::Manager do
|
|
164
164
|
|
165
165
|
|
166
166
|
it "checkpoints the state file periodically if an interval is configured" do
|
167
|
-
described_class.configure( manager: {checkpoint_frequency:
|
167
|
+
described_class.configure( manager: {checkpoint_frequency: 20_000, state_file: 'arb.tree'} )
|
168
168
|
|
169
|
+
zloop = instance_double( ZMQ::Loop, register: nil, :verbose= => nil )
|
169
170
|
timer = instance_double( ZMQ::Timer, "checkpoint timer" )
|
170
|
-
expect( ZMQ::
|
171
|
+
expect( ZMQ::Loop ).to receive( :new ).and_return( zloop )
|
172
|
+
allow( ZMQ::Timer ).to receive( :new ).and_call_original
|
173
|
+
expect( ZMQ::Timer ).to receive( :new ).with( 20.0, 0 ).and_return( timer )
|
171
174
|
|
172
|
-
|
175
|
+
manager = described_class.new
|
176
|
+
expect( manager.checkpoint_timer ).to eq( timer )
|
173
177
|
end
|
174
178
|
|
175
179
|
|
176
180
|
it "doesn't checkpoint if no interval is configured" do
|
177
181
|
described_class.configure( manager: {checkpoint_frequency: nil, state_file: 'arb.tree'} )
|
178
182
|
|
179
|
-
|
180
|
-
|
181
|
-
expect( manager.start_state_checkpointing ).to be_nil
|
183
|
+
manager = described_class.new
|
184
|
+
expect( manager.checkpoint_timer ).to be_nil
|
182
185
|
end
|
183
186
|
|
184
187
|
|
185
188
|
it "doesn't checkpoint if no state file is configured" do
|
186
189
|
described_class.configure( manager: {checkpoint_frequency: 20, state_file: nil} )
|
187
190
|
|
188
|
-
|
189
|
-
|
190
|
-
expect( manager.start_state_checkpointing ).to be_nil
|
191
|
+
manager = described_class.new
|
192
|
+
expect( manager.checkpoint_timer ).to be_nil
|
191
193
|
end
|
192
194
|
|
193
195
|
|
@@ -197,6 +199,20 @@ describe Arborist::Manager do
|
|
197
199
|
end
|
198
200
|
|
199
201
|
|
202
|
+
context "heartbeat event" do
|
203
|
+
|
204
|
+
it "errors if configured with a heartbeat of 0" do
|
205
|
+
expect {
|
206
|
+
described_class.configure( manager: {heartbeat_frequency: 0} )
|
207
|
+
}.to raise_error( Arborist::ConfigError, /positive non-zero/i )
|
208
|
+
end
|
209
|
+
|
210
|
+
|
211
|
+
it "is sent at the configured "
|
212
|
+
|
213
|
+
end
|
214
|
+
|
215
|
+
|
200
216
|
context "a new empty manager" do
|
201
217
|
|
202
218
|
let( :node ) do
|
@@ -583,12 +599,14 @@ describe Arborist::Manager do
|
|
583
599
|
let( :event_pollitem ) { instance_double(ZMQ::Pollitem, "event API pollitem") }
|
584
600
|
let( :signal_timer ) { instance_double(ZMQ::Timer, "signal timer") }
|
585
601
|
|
602
|
+
|
586
603
|
before( :each ) do
|
587
604
|
allow( ZMQ::Loop ).to receive( :new ).and_return( zmq_loop )
|
588
605
|
|
589
606
|
allow( zmq_context ).to receive( :socket ).with( :REP ).and_return( tree_sock )
|
590
607
|
allow( zmq_context ).to receive( :socket ).with( :PUB ).and_return( event_sock )
|
591
608
|
|
609
|
+
allow( zmq_loop ).to receive( :verbose= )
|
592
610
|
allow( zmq_loop ).to receive( :remove ).with( tree_pollitem )
|
593
611
|
allow( zmq_loop ).to receive( :remove ).with( event_pollitem )
|
594
612
|
|
@@ -596,41 +614,52 @@ describe Arborist::Manager do
|
|
596
614
|
allow( tree_sock ).to receive( :close )
|
597
615
|
allow( event_pollitem ).to receive( :pollable ).and_return( event_sock )
|
598
616
|
allow( event_sock ).to receive( :close )
|
599
|
-
end
|
600
|
-
|
601
617
|
|
602
|
-
|
603
|
-
|
604
|
-
expect( tree_sock ).to receive( :linger= ).with( 0 )
|
618
|
+
allow( tree_sock ).to receive( :bind ).with( Arborist.tree_api_url )
|
619
|
+
allow( tree_sock ).to receive( :linger= )
|
605
620
|
|
606
|
-
|
607
|
-
|
621
|
+
allow( event_sock ).to receive( :bind ).with( Arborist.event_api_url )
|
622
|
+
allow( event_sock ).to receive( :linger= )
|
608
623
|
|
609
|
-
|
624
|
+
allow( ZMQ::Pollitem ).to receive( :new ).with( tree_sock, ZMQ::POLLIN|ZMQ::POLLOUT ).
|
610
625
|
and_return( tree_pollitem )
|
611
|
-
|
626
|
+
allow( ZMQ::Pollitem ).to receive( :new ).with( event_sock, ZMQ::POLLOUT ).
|
612
627
|
and_return( event_pollitem )
|
613
628
|
|
614
|
-
|
629
|
+
allow( tree_pollitem ).to receive( :handler= ).
|
615
630
|
with( an_instance_of(Arborist::Manager::TreeAPI) )
|
616
|
-
|
617
|
-
|
631
|
+
allow( zmq_loop ).to receive( :register ).with( tree_pollitem )
|
632
|
+
allow( event_pollitem ).to receive( :handler= ).
|
618
633
|
with( an_instance_of(Arborist::Manager::EventPublisher) )
|
619
|
-
|
634
|
+
allow( zmq_loop ).to receive( :register ).with( event_pollitem )
|
635
|
+
end
|
636
|
+
|
620
637
|
|
638
|
+
it "starts handling signals and events when started" do
|
621
639
|
expect( ZMQ::Timer ).to receive( :new ).
|
622
640
|
with( described_class::SIGNAL_INTERVAL, 0, manager.method(:process_signal_queue) ).
|
623
641
|
and_return( signal_timer )
|
624
642
|
expect( zmq_loop ).to receive( :register_timer ).with( signal_timer )
|
643
|
+
expect( zmq_loop ).to receive( :register_timer ).with( manager.heartbeat_timer )
|
625
644
|
expect( zmq_loop ).to receive( :start )
|
626
645
|
|
627
646
|
expect( zmq_loop ).to receive( :remove ).with( tree_pollitem )
|
628
647
|
expect( zmq_loop ).to receive( :remove ).with( event_pollitem )
|
629
648
|
|
630
649
|
manager.run
|
631
|
-
end
|
632
|
-
end
|
633
650
|
|
651
|
+
expect( manager.event_publisher.event_queue.length ).to eq( 1 )
|
652
|
+
|
653
|
+
event = manager.event_publisher.event_queue.first
|
654
|
+
expect( event.first ).to eq( 'sys.startup' )
|
655
|
+
|
656
|
+
payload = unpack_message( event.last )
|
657
|
+
expect( payload ).to include(
|
658
|
+
'start_time' => an_instance_of(String),
|
659
|
+
'version' => an_instance_of(String)
|
660
|
+
)
|
661
|
+
end
|
634
662
|
|
663
|
+
end
|
635
664
|
end
|
636
665
|
|
@@ -19,6 +19,10 @@ describe Arborist::Node::Resource do
|
|
19
19
|
expect( result.identifier ).to eq( "testhost-disk" )
|
20
20
|
end
|
21
21
|
|
22
|
+
it "defaults the category to the identifier" do
|
23
|
+
result = described_class.new( 'load', host )
|
24
|
+
expect( result.category ).to eq( 'load' )
|
25
|
+
end
|
22
26
|
|
23
27
|
it "raises a sensible error when created without a host" do
|
24
28
|
expect {
|
@@ -51,6 +55,11 @@ describe Arborist::Node::Resource do
|
|
51
55
|
expect( node ).to_not match_criteria( address: '192.168.66.64/27' )
|
52
56
|
expect( node ).to_not match_criteria( address: '127.0.0.0/8' )
|
53
57
|
end
|
58
|
+
|
59
|
+
it "can be matched with a category" do
|
60
|
+
expect( node ).to match_criteria( category: 'disk' )
|
61
|
+
expect( node ).to_not match_criteria( category: 'processes' )
|
62
|
+
end
|
54
63
|
end
|
55
64
|
end
|
56
65
|
|
@@ -122,12 +122,27 @@ describe Arborist::Node::Service do
|
|
122
122
|
end
|
123
123
|
|
124
124
|
|
125
|
-
it "
|
125
|
+
it "inherits its host's addresses" do
|
126
126
|
expect( node ).to match_criteria( address: '192.168.66.12' )
|
127
127
|
expect( node ).to_not match_criteria( address: '127.0.0.1' )
|
128
128
|
end
|
129
129
|
|
130
130
|
|
131
|
+
it "can be limited to a subset of its host's addresses" do
|
132
|
+
node.address( host.addresses.first )
|
133
|
+
expect( node ).to match_criteria( address: '192.168.66.12' )
|
134
|
+
expect( node ).to_not match_criteria( address: '10.1.33.8' )
|
135
|
+
expect( node ).to_not match_criteria( address: '127.0.0.1' )
|
136
|
+
end
|
137
|
+
|
138
|
+
|
139
|
+
it "errors if it specifies an address other than one of its host's addresses" do
|
140
|
+
expect {
|
141
|
+
node.address( '127.0.0.1' )
|
142
|
+
}.to raise_error( Arborist::ConfigError, /127.0.0.1 is not one of testhost's addresses/i )
|
143
|
+
end
|
144
|
+
|
145
|
+
|
131
146
|
it "can be matched with a netblock that includes one of its host's addresses" do
|
132
147
|
expect( node ).to match_criteria( address: '192.168.66.0/24' )
|
133
148
|
expect( node ).to match_criteria( address: '10.0.0.0/8' )
|
data/spec/arborist/node_spec.rb
CHANGED
@@ -356,6 +356,8 @@ describe Arborist::Node do
|
|
356
356
|
any_of('webproxy', on: ['fe-host1','fe-host2','fe-host3'])
|
357
357
|
)
|
358
358
|
|
359
|
+
config os: 'freebsd-10'
|
360
|
+
|
359
361
|
update( 'song' => 'Around the World', 'artist' => 'Daft Punk', 'length' => '7:09' )
|
360
362
|
end
|
361
363
|
end
|
@@ -400,6 +402,7 @@ describe Arborist::Node do
|
|
400
402
|
|
401
403
|
old_node.instance_variable_set( :@parent, 'foo' )
|
402
404
|
old_node.instance_variable_set( :@description, 'Some older description' )
|
405
|
+
old_node.instance_variable_set( :@config, {'os' => 'freebsd-8'} )
|
403
406
|
old_node.tags( :bunker, :lucky, :tickle, :trucker )
|
404
407
|
old_node.source = '/somewhere/else'
|
405
408
|
|
@@ -410,6 +413,7 @@ describe Arborist::Node do
|
|
410
413
|
expect( node.tags ).to eq( node_copy.tags )
|
411
414
|
expect( node.source ).to eq( node_copy.source )
|
412
415
|
expect( node.dependencies ).to eq( node_copy.dependencies )
|
416
|
+
expect( node.config ).to eq( node_copy.config )
|
413
417
|
end
|
414
418
|
|
415
419
|
|
@@ -465,26 +469,25 @@ describe Arborist::Node do
|
|
465
469
|
end
|
466
470
|
|
467
471
|
|
468
|
-
it "
|
472
|
+
it "can be marshalled" do
|
473
|
+
data = Marshal.dump( node )
|
474
|
+
cloned_node = Marshal.load( data )
|
475
|
+
|
476
|
+
expect( cloned_node ).to eq( node )
|
477
|
+
end
|
478
|
+
|
469
479
|
|
480
|
+
it "an ACKed node stays ACKed when serialized and restored" do
|
470
481
|
node.update( error: "there's a fire" )
|
471
482
|
node.update( ack: {
|
472
483
|
message: 'We know about the fire. It rages on.',
|
473
484
|
sender: '1986 Labyrinth David Bowie'
|
474
485
|
})
|
475
|
-
|
476
|
-
node_added_event = Arborist::Event.create( :sys_node_added, cloned_node )
|
477
|
-
cloned_node.handle_event( node_added_event )
|
478
|
-
|
479
|
-
expect( cloned_node ).to be_acked
|
480
|
-
end
|
481
|
-
|
486
|
+
expect( node ).to be_acked
|
482
487
|
|
483
|
-
|
484
|
-
data = Marshal.dump( node )
|
485
|
-
cloned_node = Marshal.load( data )
|
488
|
+
restored_node = Marshal.load( Marshal.dump(node) )
|
486
489
|
|
487
|
-
expect(
|
490
|
+
expect( restored_node ).to be_acked
|
488
491
|
end
|
489
492
|
|
490
493
|
|
@@ -639,6 +642,7 @@ describe Arborist::Node do
|
|
639
642
|
parent 'bar'
|
640
643
|
description "The prototypical node"
|
641
644
|
tags :chunker, :hunky, :flippin, :hippo
|
645
|
+
config os: 'freebsd-10'
|
642
646
|
|
643
647
|
update(
|
644
648
|
'song' => 'Around the World',
|
@@ -692,6 +696,12 @@ describe Arborist::Node do
|
|
692
696
|
end
|
693
697
|
|
694
698
|
|
699
|
+
it "can be matched with config values" do
|
700
|
+
expect( node ).to match_criteria( config: {os: 'freebsd-10'} )
|
701
|
+
expect( node ).to_not match_criteria( config: {os: 'macosx-10.11.3'} )
|
702
|
+
end
|
703
|
+
|
704
|
+
|
695
705
|
it "can be matched with its user properties" do
|
696
706
|
expect( node ).to match_criteria( song: 'Around the World' )
|
697
707
|
expect( node ).to match_criteria( artist: 'Daft Punk' )
|