arborist 0.0.1.pre20160106113421
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 +7 -0
- data/.document +4 -0
- data/.simplecov +9 -0
- data/ChangeLog +417 -0
- data/Events.md +20 -0
- data/History.md +4 -0
- data/LICENSE +29 -0
- data/Manifest.txt +72 -0
- data/Monitors.md +141 -0
- data/Nodes.md +0 -0
- data/Observers.md +72 -0
- data/Protocol.md +214 -0
- data/README.md +75 -0
- data/Rakefile +81 -0
- data/TODO.md +24 -0
- data/bin/amanagerd +10 -0
- data/bin/amonitord +12 -0
- data/bin/aobserverd +12 -0
- data/lib/arborist.rb +182 -0
- data/lib/arborist/client.rb +191 -0
- data/lib/arborist/event.rb +61 -0
- data/lib/arborist/event/node_acked.rb +18 -0
- data/lib/arborist/event/node_delta.rb +20 -0
- data/lib/arborist/event/node_matching.rb +34 -0
- data/lib/arborist/event/node_update.rb +19 -0
- data/lib/arborist/event/sys_reloaded.rb +15 -0
- data/lib/arborist/exceptions.rb +21 -0
- data/lib/arborist/manager.rb +508 -0
- data/lib/arborist/manager/event_publisher.rb +97 -0
- data/lib/arborist/manager/tree_api.rb +207 -0
- data/lib/arborist/mixins.rb +363 -0
- data/lib/arborist/monitor.rb +377 -0
- data/lib/arborist/monitor/socket.rb +163 -0
- data/lib/arborist/monitor_runner.rb +217 -0
- data/lib/arborist/node.rb +700 -0
- data/lib/arborist/node/host.rb +87 -0
- data/lib/arborist/node/root.rb +60 -0
- data/lib/arborist/node/service.rb +112 -0
- data/lib/arborist/observer.rb +176 -0
- data/lib/arborist/observer/action.rb +125 -0
- data/lib/arborist/observer/summarize.rb +105 -0
- data/lib/arborist/observer_runner.rb +181 -0
- data/lib/arborist/subscription.rb +82 -0
- data/spec/arborist/client_spec.rb +282 -0
- data/spec/arborist/event/node_update_spec.rb +71 -0
- data/spec/arborist/event_spec.rb +64 -0
- data/spec/arborist/manager/event_publisher_spec.rb +66 -0
- data/spec/arborist/manager/tree_api_spec.rb +458 -0
- data/spec/arborist/manager_spec.rb +442 -0
- data/spec/arborist/mixins_spec.rb +195 -0
- data/spec/arborist/monitor/socket_spec.rb +195 -0
- data/spec/arborist/monitor_runner_spec.rb +152 -0
- data/spec/arborist/monitor_spec.rb +251 -0
- data/spec/arborist/node/host_spec.rb +104 -0
- data/spec/arborist/node/root_spec.rb +29 -0
- data/spec/arborist/node/service_spec.rb +98 -0
- data/spec/arborist/node_spec.rb +552 -0
- data/spec/arborist/observer/action_spec.rb +205 -0
- data/spec/arborist/observer/summarize_spec.rb +294 -0
- data/spec/arborist/observer_spec.rb +146 -0
- data/spec/arborist/subscription_spec.rb +71 -0
- data/spec/arborist_spec.rb +146 -0
- data/spec/data/monitors/pings.rb +80 -0
- data/spec/data/monitors/port_checks.rb +27 -0
- data/spec/data/monitors/system_resources.rb +30 -0
- data/spec/data/monitors/web_services.rb +17 -0
- data/spec/data/nodes/duir.rb +20 -0
- data/spec/data/nodes/localhost.rb +15 -0
- data/spec/data/nodes/sidonie.rb +29 -0
- data/spec/data/nodes/yevaud.rb +26 -0
- data/spec/data/observers/auditor.rb +23 -0
- data/spec/data/observers/webservices.rb +18 -0
- data/spec/spec_helper.rb +117 -0
- metadata +368 -0
@@ -0,0 +1,205 @@
|
|
1
|
+
#!/usr/bin/env rspec -cfd
|
2
|
+
|
3
|
+
require_relative '../../spec_helper'
|
4
|
+
|
5
|
+
require 'timecop'
|
6
|
+
require 'arborist/observer/action'
|
7
|
+
|
8
|
+
|
9
|
+
using Arborist::TimeRefinements
|
10
|
+
|
11
|
+
|
12
|
+
describe Arborist::Observer::Action do
|
13
|
+
|
14
|
+
let( :event ) {{ stuff: :woo }}
|
15
|
+
|
16
|
+
|
17
|
+
it "can be created with just a block" do
|
18
|
+
result = described_class.new {}
|
19
|
+
expect( result ).to be_a( described_class )
|
20
|
+
expect( result.block ).to respond_to( :call )
|
21
|
+
end
|
22
|
+
|
23
|
+
|
24
|
+
it "is supplied the event history if the block has a second argument" do
|
25
|
+
history_arg = nil
|
26
|
+
action = described_class.new( after: 2 ) do |event, history|
|
27
|
+
history_arg = history
|
28
|
+
end
|
29
|
+
|
30
|
+
action.handle_event( event )
|
31
|
+
action.handle_event( event )
|
32
|
+
|
33
|
+
expect( history_arg ).to be_a( Hash )
|
34
|
+
end
|
35
|
+
|
36
|
+
|
37
|
+
it "clears the event history when the block is called" do
|
38
|
+
action = described_class.new( after: 2 ) {}
|
39
|
+
2.times { action.handle_event(event) }
|
40
|
+
|
41
|
+
expect( action.event_history ).to be_empty
|
42
|
+
end
|
43
|
+
|
44
|
+
|
45
|
+
it "requires a block" do
|
46
|
+
expect { described_class.new }.to raise_exception( ArgumentError, /requires a block/i )
|
47
|
+
end
|
48
|
+
|
49
|
+
|
50
|
+
context "without any other criteria" do
|
51
|
+
|
52
|
+
before( :each ) do
|
53
|
+
@call_count = 0
|
54
|
+
@last_call_arguments = nil
|
55
|
+
end
|
56
|
+
|
57
|
+
let( :action ) do
|
58
|
+
described_class.new do |args|
|
59
|
+
@call_count += 1
|
60
|
+
@last_call_arguments = args
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
|
65
|
+
it "calls its block immediately when handling an event" do
|
66
|
+
expect { action.handle_event(event) }.to change { @call_count }.by( 1 ).and(
|
67
|
+
change { @last_call_arguments }.to( event )
|
68
|
+
)
|
69
|
+
end
|
70
|
+
|
71
|
+
|
72
|
+
end
|
73
|
+
|
74
|
+
|
75
|
+
# within: 0, after: 1, during: nil
|
76
|
+
|
77
|
+
|
78
|
+
context "with a time threshold" do
|
79
|
+
|
80
|
+
before( :each ) do
|
81
|
+
@call_count = 0
|
82
|
+
@last_call_arguments = nil
|
83
|
+
end
|
84
|
+
|
85
|
+
let( :action ) do
|
86
|
+
described_class.new( within: 1.minute ) do |args|
|
87
|
+
@call_count += 1
|
88
|
+
@last_call_arguments = args
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
|
93
|
+
it "calls its block if two events arrive within the specified time" do
|
94
|
+
Timecop.freeze do
|
95
|
+
expect { action.handle_event(event) }.to_not change { @call_count }
|
96
|
+
Timecop.travel( 5.seconds ) do
|
97
|
+
expect { action.handle_event(event) }.to change { @call_count }.by( 1 )
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
|
103
|
+
it "calls its block if three events arrive, and the last two are within the specified time" do
|
104
|
+
Timecop.freeze do
|
105
|
+
expect { action.handle_event(event) }.to_not change { @call_count }
|
106
|
+
Timecop.travel( 65.seconds ) do
|
107
|
+
expect { action.handle_event(event) }.to_not change { @call_count }
|
108
|
+
Timecop.travel( 5.seconds ) do
|
109
|
+
expect { action.handle_event(event) }.to change { @call_count }.by( 1 )
|
110
|
+
end
|
111
|
+
end
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
|
116
|
+
it "doesn't call its block if two events arrive with more than the specified time between them" do
|
117
|
+
Timecop.freeze do
|
118
|
+
expect { action.handle_event(event) }.to_not change { @call_count }
|
119
|
+
Timecop.travel( 65.seconds ) do
|
120
|
+
expect { action.handle_event(event) }.to_not change { @call_count }
|
121
|
+
end
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
|
126
|
+
context "and a count threshold" do
|
127
|
+
|
128
|
+
let( :action ) do
|
129
|
+
described_class.new( within: 1.minute, after: 3 ) do |args|
|
130
|
+
@call_count += 1
|
131
|
+
@last_call_arguments = args
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
135
|
+
it "calls its block if the threshold number of events arrive within the specified time" do
|
136
|
+
Timecop.freeze do
|
137
|
+
expect { action.handle_event(event) }.to_not change { @call_count }
|
138
|
+
Timecop.travel( 5.seconds ) do
|
139
|
+
expect { action.handle_event(event) }.to_not change { @call_count }
|
140
|
+
Timecop.travel( 5.seconds ) do
|
141
|
+
expect { action.handle_event(event) }.to change { @call_count }.by( 1 )
|
142
|
+
end
|
143
|
+
end
|
144
|
+
end
|
145
|
+
end
|
146
|
+
|
147
|
+
|
148
|
+
it "doesn't call the block if the threshold number of events arrive with more than " +
|
149
|
+
"the specified time between them" do
|
150
|
+
Timecop.freeze do
|
151
|
+
expect { action.handle_event(event) }.to_not change { @call_count }
|
152
|
+
Timecop.travel( 5.seconds ) do
|
153
|
+
expect { action.handle_event(event) }.to_not change { @call_count }
|
154
|
+
Timecop.travel( 65.seconds ) do
|
155
|
+
expect { action.handle_event(event) }.to_not change { @call_count }
|
156
|
+
end
|
157
|
+
end
|
158
|
+
end
|
159
|
+
end
|
160
|
+
|
161
|
+
end
|
162
|
+
|
163
|
+
end
|
164
|
+
|
165
|
+
|
166
|
+
context "with a count threshold" do
|
167
|
+
before( :each ) do
|
168
|
+
@call_count = 0
|
169
|
+
@last_call_arguments = nil
|
170
|
+
end
|
171
|
+
|
172
|
+
let( :action ) do
|
173
|
+
described_class.new( after: 2 ) do |args|
|
174
|
+
@call_count += 1
|
175
|
+
@last_call_arguments = args
|
176
|
+
end
|
177
|
+
end
|
178
|
+
|
179
|
+
|
180
|
+
it "calls the block if more events than count threshold have arrived" do
|
181
|
+
expect { action.handle_event(event) }.to_not change { @call_count }
|
182
|
+
expect { action.handle_event(event) }.to change { @call_count }.by( 1 )
|
183
|
+
end
|
184
|
+
|
185
|
+
end
|
186
|
+
|
187
|
+
|
188
|
+
context "with a schedule" do
|
189
|
+
|
190
|
+
|
191
|
+
context "with a time threshold" do
|
192
|
+
|
193
|
+
context "and a count threshold"
|
194
|
+
|
195
|
+
end
|
196
|
+
|
197
|
+
|
198
|
+
context "and a count threshold"
|
199
|
+
|
200
|
+
end
|
201
|
+
|
202
|
+
|
203
|
+
end
|
204
|
+
|
205
|
+
|
@@ -0,0 +1,294 @@
|
|
1
|
+
#!/usr/bin/env rspec -cfd
|
2
|
+
|
3
|
+
require_relative '../../spec_helper'
|
4
|
+
|
5
|
+
require 'timecop'
|
6
|
+
require 'arborist/observer/summarize'
|
7
|
+
|
8
|
+
|
9
|
+
using Arborist::TimeRefinements
|
10
|
+
|
11
|
+
|
12
|
+
describe Arborist::Observer::Summarize do
|
13
|
+
|
14
|
+
before( :all ) do
|
15
|
+
@actual_zone = ENV['TZ']
|
16
|
+
ENV['TZ'] = 'GMT'
|
17
|
+
end
|
18
|
+
|
19
|
+
after( :all ) do
|
20
|
+
ENV['TZ'] = @actual_zone
|
21
|
+
end
|
22
|
+
|
23
|
+
|
24
|
+
let( :event ) {{ stuff: :woo }}
|
25
|
+
|
26
|
+
|
27
|
+
it "can be created with just a block and a count" do
|
28
|
+
result = described_class.new( every: 1.minute ) {}
|
29
|
+
expect( result ).to be_a( described_class )
|
30
|
+
expect( result.block ).to respond_to( :call )
|
31
|
+
expect( result.time_threshold ).to eq( 1.minute )
|
32
|
+
end
|
33
|
+
|
34
|
+
|
35
|
+
it "errors if created with just a block" do
|
36
|
+
expect {
|
37
|
+
described_class.new {}
|
38
|
+
}.to raise_error( ArgumentError, /requires a value/i )
|
39
|
+
end
|
40
|
+
|
41
|
+
|
42
|
+
it "is supplied the event history if the block has a second argument" do
|
43
|
+
history_arg = nil
|
44
|
+
summarize = described_class.new( count: 2 ) do |history|
|
45
|
+
history_arg = history
|
46
|
+
end
|
47
|
+
|
48
|
+
summarize.handle_event( event )
|
49
|
+
summarize.handle_event( event )
|
50
|
+
|
51
|
+
expect( history_arg ).to be_a( Hash )
|
52
|
+
end
|
53
|
+
|
54
|
+
|
55
|
+
it "clears the event history when the block is called" do
|
56
|
+
summarize = described_class.new( count: 2 ) {}
|
57
|
+
2.times { summarize.handle_event(event) }
|
58
|
+
|
59
|
+
expect( summarize.event_history ).to be_empty
|
60
|
+
end
|
61
|
+
|
62
|
+
|
63
|
+
it "requires a block" do
|
64
|
+
expect {
|
65
|
+
described_class.new( count: 2 )
|
66
|
+
}.to raise_exception( ArgumentError, /requires a block/i )
|
67
|
+
end
|
68
|
+
|
69
|
+
|
70
|
+
|
71
|
+
# every: 0, count: 1, during: nil
|
72
|
+
|
73
|
+
|
74
|
+
context "with a time threshold" do
|
75
|
+
|
76
|
+
before( :each ) do
|
77
|
+
@call_count = 0
|
78
|
+
@last_call_arguments = nil
|
79
|
+
end
|
80
|
+
|
81
|
+
let( :summarize ) do
|
82
|
+
described_class.new( every: 1.minute ) do |args|
|
83
|
+
@call_count += 1
|
84
|
+
@last_call_arguments = args
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
|
89
|
+
it "calls its block if any events have arrived within the specified time" do
|
90
|
+
Timecop.freeze do
|
91
|
+
expect { summarize.handle_event(event) }.to_not change { @call_count }
|
92
|
+
Timecop.travel( 5.seconds ) do
|
93
|
+
expect { summarize.handle_event(event) }.to_not change { @call_count }
|
94
|
+
Timecop.travel( 55.seconds ) do
|
95
|
+
expect { summarize.on_timer }.to change { @call_count }.by( 1 )
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
|
102
|
+
it "doesn't call its block if no events arrive with the specified time" do
|
103
|
+
expect { summarize.on_timer }.to_not change { @call_count }
|
104
|
+
end
|
105
|
+
|
106
|
+
|
107
|
+
context "and a count threshold" do
|
108
|
+
|
109
|
+
let( :summarize ) do
|
110
|
+
described_class.new( every: 1.minute, count: 3 ) do |args|
|
111
|
+
@call_count += 1
|
112
|
+
@last_call_arguments = args
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
it "calls its block if the threshold number of events arrive before the specified time threshold" do
|
117
|
+
Timecop.freeze do
|
118
|
+
expect { summarize.handle_event(event) }.to_not change { @call_count }
|
119
|
+
Timecop.travel( 5.seconds ) do
|
120
|
+
expect { summarize.handle_event(event) }.to_not change { @call_count }
|
121
|
+
Timecop.travel( 5.seconds ) do
|
122
|
+
expect { summarize.handle_event(event) }.to change { @call_count }.by( 1 )
|
123
|
+
end
|
124
|
+
end
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
|
129
|
+
it "calls the block if the time threshold is met before the count threshold" do
|
130
|
+
Timecop.freeze do
|
131
|
+
expect { summarize.handle_event(event) }.to_not change { @call_count }
|
132
|
+
Timecop.travel( 5.seconds ) do
|
133
|
+
expect { summarize.handle_event(event) }.to_not change { @call_count }
|
134
|
+
Timecop.travel( 55.seconds ) do
|
135
|
+
expect { summarize.on_timer }.to change { @call_count }
|
136
|
+
end
|
137
|
+
end
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
141
|
+
end
|
142
|
+
|
143
|
+
end
|
144
|
+
|
145
|
+
|
146
|
+
context "with a count threshold" do
|
147
|
+
before( :each ) do
|
148
|
+
@call_count = 0
|
149
|
+
@last_call_arguments = nil
|
150
|
+
end
|
151
|
+
|
152
|
+
let( :summarize ) do
|
153
|
+
described_class.new( count: 2 ) do |args|
|
154
|
+
@call_count += 1
|
155
|
+
@last_call_arguments = args
|
156
|
+
end
|
157
|
+
end
|
158
|
+
|
159
|
+
|
160
|
+
it "calls the block if more events than count threshold have arrived" do
|
161
|
+
expect { summarize.handle_event(event) }.to_not change { @call_count }
|
162
|
+
expect { summarize.handle_event(event) }.to change { @call_count }.by( 1 )
|
163
|
+
end
|
164
|
+
|
165
|
+
end
|
166
|
+
|
167
|
+
|
168
|
+
context "with a schedule" do
|
169
|
+
|
170
|
+
before( :each ) do
|
171
|
+
@call_count = 0
|
172
|
+
@last_call_arguments = nil
|
173
|
+
end
|
174
|
+
|
175
|
+
let( :summarize ) do
|
176
|
+
# Count or every threshold is mandatory with a summary, so just use 1
|
177
|
+
described_class.new( count: 1, during: 'hr {9am-5pm} wd {Mon-Fri}' ) do |args|
|
178
|
+
@call_count += 1
|
179
|
+
@last_call_arguments = args
|
180
|
+
end
|
181
|
+
end
|
182
|
+
|
183
|
+
|
184
|
+
it "calls its block if any events arrive within the specified schedule" do
|
185
|
+
Timecop.freeze( '2015-11-11T08:00:00-00:00' ) do
|
186
|
+
expect { summarize.handle_event(event) }.to_not change { @call_count }
|
187
|
+
Timecop.travel( 2.hours ) do
|
188
|
+
expect { summarize.handle_event(event) }.to change { @call_count }.by( 1 )
|
189
|
+
Timecop.travel( 9.hours ) do
|
190
|
+
expect { summarize.on_timer }.to_not change { @call_count }
|
191
|
+
end
|
192
|
+
end
|
193
|
+
end
|
194
|
+
end
|
195
|
+
|
196
|
+
|
197
|
+
it "doesn't call its block if no events arrive with the specified time" do
|
198
|
+
expect { summarize.on_timer }.to_not change { @call_count }
|
199
|
+
end
|
200
|
+
|
201
|
+
|
202
|
+
context "and a count threshold" do
|
203
|
+
|
204
|
+
let( :summarize ) do
|
205
|
+
# Count or every threshold is mandatory with a summary, so just use 1
|
206
|
+
described_class.new( count: 3, during: 'hr {9am-5pm} wd {Mon-Fri}' ) do |args|
|
207
|
+
@call_count += 1
|
208
|
+
@last_call_arguments = args
|
209
|
+
end
|
210
|
+
end
|
211
|
+
|
212
|
+
|
213
|
+
it "calls its block if any events arrive within the specified schedule" do
|
214
|
+
Timecop.freeze( '2015-11-11T08:00:00-00:00' ) do
|
215
|
+
expect { summarize.handle_event(event) }.to_not change { @call_count }
|
216
|
+
|
217
|
+
Timecop.travel( 2.hours )
|
218
|
+
expect { summarize.handle_event(event) }.to_not change { @call_count }
|
219
|
+
|
220
|
+
Timecop.travel( 2.hours )
|
221
|
+
expect { summarize.handle_event(event) }.to_not change { @call_count }
|
222
|
+
|
223
|
+
Timecop.travel( 2.hours )
|
224
|
+
expect { summarize.handle_event(event) }.to change { @call_count }.by( 1 )
|
225
|
+
|
226
|
+
Timecop.travel( 6.hours )
|
227
|
+
expect { summarize.on_timer }.to_not change { @call_count }
|
228
|
+
end
|
229
|
+
end
|
230
|
+
|
231
|
+
end
|
232
|
+
|
233
|
+
|
234
|
+
context "and a time threshold" do
|
235
|
+
|
236
|
+
let( :summarize ) do
|
237
|
+
described_class.new( every: 5.minutes, during: 'hr {9am-5pm} wd {Mon-Fri}' ) do |args|
|
238
|
+
@call_count += 1
|
239
|
+
@last_call_arguments = args
|
240
|
+
end
|
241
|
+
end
|
242
|
+
|
243
|
+
|
244
|
+
it "calls its block on the timer if any events arrived within the specified schedule" do
|
245
|
+
Timecop.freeze( '2015-11-11T09:00:00-00:00' ) do
|
246
|
+
expect { summarize.handle_event(event) }.to_not change { @call_count }
|
247
|
+
Timecop.travel( 1.minute )
|
248
|
+
expect { summarize.handle_event(event) }.to_not change { @call_count }
|
249
|
+
Timecop.travel( 4.minutes )
|
250
|
+
expect { summarize.on_timer }.to change { @call_count }.by( 1 )
|
251
|
+
end
|
252
|
+
end
|
253
|
+
|
254
|
+
|
255
|
+
|
256
|
+
context "and a count threshold" do
|
257
|
+
|
258
|
+
let( :summarize ) do
|
259
|
+
described_class.new( every: 5.minutes, count: 2, during: 'hr {9am-5pm}' ) do |args|
|
260
|
+
@call_count += 1
|
261
|
+
@last_call_arguments = args
|
262
|
+
end
|
263
|
+
end
|
264
|
+
|
265
|
+
|
266
|
+
it "calls its block on the timer if any events arrived within the specified schedule" do
|
267
|
+
Timecop.freeze( '2015-11-11T09:00:00-00:00' ) do
|
268
|
+
expect { summarize.handle_event(event) }.to_not change { @call_count }
|
269
|
+
Timecop.travel( 5.minutes )
|
270
|
+
expect { summarize.on_timer }.to change { @call_count }.by( 1 )
|
271
|
+
end
|
272
|
+
end
|
273
|
+
|
274
|
+
|
275
|
+
it "calls its block on the event if it arrives within the specified schedule and " +
|
276
|
+
"exceeds the count threshold" do
|
277
|
+
Timecop.freeze( '2015-11-11T09:00:00-00:00' ) do
|
278
|
+
expect { summarize.handle_event(event) }.to_not change { @call_count }
|
279
|
+
Timecop.travel( 1.minute )
|
280
|
+
expect { summarize.handle_event(event) }.to change { @call_count }.by( 1 )
|
281
|
+
end
|
282
|
+
end
|
283
|
+
|
284
|
+
end
|
285
|
+
|
286
|
+
end
|
287
|
+
|
288
|
+
|
289
|
+
end
|
290
|
+
|
291
|
+
|
292
|
+
end
|
293
|
+
|
294
|
+
|