flapjack 0.7.35 → 0.8.0
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/.gitignore +1 -1
- data/Gemfile +3 -4
- data/Guardfile +1 -1
- data/README.md +38 -19
- data/Rakefile +1 -3
- data/etc/flapjack_config.yaml.example +11 -1
- data/features/steps/cli_steps.rb +3 -3
- data/features/steps/events_steps.rb +7 -6
- data/features/steps/flapjack-netsaint-parser_steps.rb +8 -8
- data/features/steps/notifications_steps.rb +10 -10
- data/features/steps/packaging-lintian_steps.rb +5 -9
- data/features/steps/time_travel_steps.rb +1 -1
- data/flapjack.gemspec +4 -3
- data/lib/flapjack/data/contact.rb +78 -6
- data/lib/flapjack/data/entity.rb +11 -2
- data/lib/flapjack/data/notification_rule.rb +67 -59
- data/lib/flapjack/data/semaphore.rb +44 -0
- data/lib/flapjack/gateways/api.rb +24 -28
- data/lib/flapjack/gateways/api/contact_methods.rb +1 -2
- data/lib/flapjack/gateways/api/entity_methods.rb +3 -3
- data/lib/flapjack/gateways/jsonapi.rb +249 -0
- data/lib/flapjack/gateways/jsonapi/contact_methods.rb +544 -0
- data/lib/flapjack/gateways/jsonapi/entity_check_presenter.rb +217 -0
- data/lib/flapjack/gateways/jsonapi/entity_methods.rb +350 -0
- data/lib/flapjack/gateways/jsonapi/entity_presenter.rb +75 -0
- data/lib/flapjack/gateways/jsonapi/rack/json_params_parser.rb +32 -0
- data/lib/flapjack/gateways/web.rb +78 -12
- data/lib/flapjack/gateways/web/public/css/bootstrap-theme.css +397 -0
- data/lib/flapjack/gateways/web/public/css/bootstrap-theme.min.css +7 -0
- data/lib/flapjack/gateways/web/public/css/bootstrap.css +7118 -0
- data/lib/flapjack/gateways/web/public/css/bootstrap.min.css +6 -8
- data/lib/flapjack/gateways/web/public/css/font-awesome.css +1338 -0
- data/lib/flapjack/gateways/web/public/css/font-awesome.min.css +4 -0
- data/lib/flapjack/gateways/web/public/css/screen.css +80 -0
- data/lib/flapjack/gateways/web/public/css/select2-bootstrap.css +87 -0
- data/lib/flapjack/gateways/web/public/css/select2.css +615 -0
- data/lib/flapjack/gateways/web/public/fonts/FontAwesome.otf +0 -0
- data/lib/flapjack/gateways/web/public/fonts/fontawesome-webfont.eot +0 -0
- data/lib/flapjack/gateways/web/public/fonts/fontawesome-webfont.svg +414 -0
- data/lib/flapjack/gateways/web/public/fonts/fontawesome-webfont.ttf +0 -0
- data/lib/flapjack/gateways/web/public/fonts/fontawesome-webfont.woff +0 -0
- data/lib/flapjack/gateways/web/public/fonts/glyphicons-halflings-regular.eot +0 -0
- data/lib/flapjack/gateways/web/public/fonts/glyphicons-halflings-regular.svg +229 -0
- data/lib/flapjack/gateways/web/public/fonts/glyphicons-halflings-regular.ttf +0 -0
- data/lib/flapjack/gateways/web/public/fonts/glyphicons-halflings-regular.woff +0 -0
- data/lib/flapjack/gateways/web/public/img/flapjack-2013-notext-transparent-300-300.png +0 -0
- data/lib/flapjack/gateways/web/public/img/select2.png +0 -0
- data/lib/flapjack/gateways/web/public/img/select2x2.png +0 -0
- data/lib/flapjack/gateways/web/public/js/backbone-min.js +2 -0
- data/lib/flapjack/gateways/web/public/js/backbone.js +1581 -0
- data/lib/flapjack/gateways/web/public/js/backbone.jsonapi.js +75 -0
- data/lib/flapjack/gateways/web/public/js/bootstrap.js +2276 -0
- data/lib/flapjack/gateways/web/public/js/contacts.js +225 -0
- data/lib/flapjack/gateways/web/public/js/jquery-1.10.2.js +9789 -0
- data/lib/flapjack/gateways/web/public/js/jquery-1.10.2.min.js +6 -0
- data/lib/flapjack/gateways/web/public/js/select2.js +3255 -0
- data/lib/flapjack/gateways/web/public/js/select2.min.js +22 -0
- data/lib/flapjack/gateways/web/public/js/underscore-min.js +6 -0
- data/lib/flapjack/gateways/web/public/js/underscore.js +1276 -0
- data/lib/flapjack/gateways/web/views/check.html.erb +423 -193
- data/lib/flapjack/gateways/web/views/checks.html.erb +51 -71
- data/lib/flapjack/gateways/web/views/contact.html.erb +142 -164
- data/lib/flapjack/gateways/web/views/contacts.html.erb +20 -40
- data/lib/flapjack/gateways/web/views/edit_contacts.html.erb +83 -0
- data/lib/flapjack/gateways/web/views/entities.html.erb +18 -37
- data/lib/flapjack/gateways/web/views/entity.html.erb +46 -65
- data/lib/flapjack/gateways/web/views/index.html.erb +6 -27
- data/lib/flapjack/gateways/web/views/layout.erb +95 -0
- data/lib/flapjack/gateways/web/views/self_stats.html.erb +100 -114
- data/lib/flapjack/pikelet.rb +4 -2
- data/lib/flapjack/version.rb +1 -1
- data/spec/lib/flapjack/coordinator_spec.rb +120 -120
- data/spec/lib/flapjack/data/contact_spec.rb +66 -58
- data/spec/lib/flapjack/data/entity_check_spec.rb +179 -179
- data/spec/lib/flapjack/data/entity_spec.rb +71 -71
- data/spec/lib/flapjack/data/event_spec.rb +34 -30
- data/spec/lib/flapjack/data/message_spec.rb +6 -6
- data/spec/lib/flapjack/data/notification_rule_spec.rb +24 -24
- data/spec/lib/flapjack/data/notification_spec.rb +19 -19
- data/spec/lib/flapjack/data/semaphore_spec.rb +24 -0
- data/spec/lib/flapjack/data/tag_spec.rb +11 -10
- data/spec/lib/flapjack/gateways/api/contact_methods_spec.rb +201 -201
- data/spec/lib/flapjack/gateways/api/entity_check_presenter_spec.rb +55 -55
- data/spec/lib/flapjack/gateways/api/entity_methods_spec.rb +257 -257
- data/spec/lib/flapjack/gateways/api/entity_presenter_spec.rb +26 -26
- data/spec/lib/flapjack/gateways/api_spec.rb +1 -1
- data/spec/lib/flapjack/gateways/email_spec.rb +4 -4
- data/spec/lib/flapjack/gateways/jabber_spec.rb +77 -77
- data/spec/lib/flapjack/gateways/jsonapi/contact_methods_spec.rb +830 -0
- data/spec/lib/flapjack/gateways/jsonapi/entity_check_presenter_spec.rb +211 -0
- data/spec/lib/flapjack/gateways/jsonapi/entity_methods_spec.rb +863 -0
- data/spec/lib/flapjack/gateways/jsonapi/entity_presenter_spec.rb +108 -0
- data/spec/lib/flapjack/gateways/jsonapi_spec.rb +8 -0
- data/spec/lib/flapjack/gateways/oobetet_spec.rb +35 -35
- data/spec/lib/flapjack/gateways/pagerduty_spec.rb +40 -40
- data/spec/lib/flapjack/gateways/sms_messagenet_spec.rb +3 -3
- data/spec/lib/flapjack/gateways/web/views/check.html.erb_spec.rb +1 -1
- data/spec/lib/flapjack/gateways/web/views/contact.html.erb_spec.rb +5 -5
- data/spec/lib/flapjack/gateways/web/views/index.html.erb_spec.rb +1 -1
- data/spec/lib/flapjack/gateways/web_spec.rb +73 -74
- data/spec/lib/flapjack/logger_spec.rb +13 -13
- data/spec/lib/flapjack/pikelet_spec.rb +33 -33
- data/spec/lib/flapjack/processor_spec.rb +22 -22
- data/spec/lib/flapjack/redis_pool_spec.rb +1 -1
- data/spec/lib/flapjack/utility_spec.rb +12 -12
- data/spec/spec_helper.rb +9 -9
- data/spec/support/erb_view_helper.rb +4 -0
- metadata +107 -96
- data/lib/flapjack/gateways/web/public/css/flapjack.css +0 -49
- data/lib/flapjack/gateways/web/views/_css.html.erb +0 -42
- data/lib/flapjack/gateways/web/views/_foot.html.erb +0 -3
- data/lib/flapjack/gateways/web/views/_head.html.erb +0 -5
- data/lib/flapjack/gateways/web/views/_nav.html.erb +0 -10
data/lib/flapjack/pikelet.rb
CHANGED
|
@@ -20,6 +20,7 @@ require 'thin'
|
|
|
20
20
|
require 'flapjack/notifier'
|
|
21
21
|
require 'flapjack/processor'
|
|
22
22
|
require 'flapjack/gateways/api'
|
|
23
|
+
require 'flapjack/gateways/jsonapi'
|
|
23
24
|
require 'flapjack/gateways/jabber'
|
|
24
25
|
require 'flapjack/gateways/oobetet'
|
|
25
26
|
require 'flapjack/gateways/pagerduty'
|
|
@@ -216,8 +217,9 @@ module Flapjack
|
|
|
216
217
|
|
|
217
218
|
class Thin < Flapjack::Pikelet::Base
|
|
218
219
|
|
|
219
|
-
PIKELET_TYPES = {'web'
|
|
220
|
-
'api'
|
|
220
|
+
PIKELET_TYPES = {'web' => Flapjack::Gateways::Web,
|
|
221
|
+
'api' => Flapjack::Gateways::API,
|
|
222
|
+
'jsonapi' => Flapjack::Gateways::JSONAPI}
|
|
221
223
|
|
|
222
224
|
def self.create(type, opts = {})
|
|
223
225
|
::Thin::Logging.silent = true
|
data/lib/flapjack/version.rb
CHANGED
|
@@ -12,30 +12,30 @@ describe Flapjack::Coordinator do
|
|
|
12
12
|
let!(:time) { Time.now }
|
|
13
13
|
|
|
14
14
|
it "starts and stops a pikelet" do
|
|
15
|
-
Flapjack::Logger.
|
|
15
|
+
expect(Flapjack::Logger).to receive(:new).and_return(logger)
|
|
16
16
|
|
|
17
17
|
cfg = {'processor' => {'enabled' => true}}
|
|
18
|
-
EM.
|
|
19
|
-
config.
|
|
20
|
-
config.
|
|
18
|
+
expect(EM).to receive(:synchrony).and_yield
|
|
19
|
+
expect(config).to receive(:for_redis).and_return({})
|
|
20
|
+
expect(config).to receive(:all).twice.and_return(cfg)
|
|
21
21
|
|
|
22
22
|
processor = double('processor')
|
|
23
|
-
processor.
|
|
24
|
-
processor.
|
|
25
|
-
processor.
|
|
26
|
-
processor.
|
|
23
|
+
expect(processor).to receive(:start)
|
|
24
|
+
expect(processor).to receive(:stop)
|
|
25
|
+
expect(processor).to receive(:update_status)
|
|
26
|
+
expect(processor).to receive(:status).exactly(3).times.and_return('stopped')
|
|
27
27
|
|
|
28
|
-
Time.
|
|
28
|
+
expect(Time).to receive(:now).and_return(time)
|
|
29
29
|
|
|
30
30
|
fc = Flapjack::Coordinator.new(config)
|
|
31
|
-
Flapjack::Pikelet.
|
|
31
|
+
expect(Flapjack::Pikelet).to receive(:create).with('processor',
|
|
32
32
|
:config => cfg['processor'], :redis_config => {}, :boot_time => time, :coordinator => fc).
|
|
33
33
|
and_return(processor)
|
|
34
34
|
|
|
35
|
-
fiber.
|
|
36
|
-
Fiber.
|
|
35
|
+
expect(fiber).to receive(:resume)
|
|
36
|
+
expect(Fiber).to receive(:new).and_yield.and_return(fiber)
|
|
37
37
|
|
|
38
|
-
EM.
|
|
38
|
+
expect(EM).to receive(:stop)
|
|
39
39
|
|
|
40
40
|
# Syslog.should_receive(:opened?).and_return(true)
|
|
41
41
|
# Syslog.should_receive(:close)
|
|
@@ -45,31 +45,31 @@ describe Flapjack::Coordinator do
|
|
|
45
45
|
end
|
|
46
46
|
|
|
47
47
|
it "handles an exception raised by a pikelet and shuts down" do
|
|
48
|
-
Flapjack::Logger.
|
|
49
|
-
logger.
|
|
48
|
+
expect(Flapjack::Logger).to receive(:new).and_return(logger)
|
|
49
|
+
expect(logger).to receive(:fatal)
|
|
50
50
|
|
|
51
51
|
cfg = {'processor' => {'enabled' => true}}
|
|
52
|
-
EM.
|
|
53
|
-
config.
|
|
54
|
-
config.
|
|
52
|
+
expect(EM).to receive(:synchrony).and_yield
|
|
53
|
+
expect(config).to receive(:for_redis).and_return({})
|
|
54
|
+
expect(config).to receive(:all).twice.and_return(cfg)
|
|
55
55
|
|
|
56
56
|
processor = double('processor')
|
|
57
|
-
processor.
|
|
58
|
-
processor.
|
|
59
|
-
processor.
|
|
60
|
-
processor.
|
|
57
|
+
expect(processor).to receive(:start).and_raise(RuntimeError)
|
|
58
|
+
expect(processor).to receive(:stop)
|
|
59
|
+
expect(processor).to receive(:update_status)
|
|
60
|
+
expect(processor).to receive(:status).exactly(3).times.and_return('stopped')
|
|
61
61
|
|
|
62
|
-
Time.
|
|
62
|
+
expect(Time).to receive(:now).and_return(time)
|
|
63
63
|
|
|
64
64
|
fc = Flapjack::Coordinator.new(config)
|
|
65
|
-
Flapjack::Pikelet.
|
|
65
|
+
expect(Flapjack::Pikelet).to receive(:create).with('processor',
|
|
66
66
|
:config => cfg['processor'], :redis_config => {}, :boot_time => time, :coordinator => fc)
|
|
67
67
|
.and_return(processor)
|
|
68
68
|
|
|
69
|
-
fiber.
|
|
70
|
-
Fiber.
|
|
69
|
+
expect(fiber).to receive(:resume)
|
|
70
|
+
expect(Fiber).to receive(:new).and_yield.and_return(fiber)
|
|
71
71
|
|
|
72
|
-
EM.
|
|
72
|
+
expect(EM).to receive(:stop)
|
|
73
73
|
|
|
74
74
|
# Syslog.should_receive(:opened?).and_return(true)
|
|
75
75
|
# Syslog.should_receive(:close)
|
|
@@ -80,36 +80,36 @@ describe Flapjack::Coordinator do
|
|
|
80
80
|
|
|
81
81
|
it "loads an old executive pikelet config block with no new data" do
|
|
82
82
|
cfg = {'executive' => {'enabled' => true}}
|
|
83
|
-
EM.
|
|
84
|
-
config.
|
|
85
|
-
config.
|
|
83
|
+
expect(EM).to receive(:synchrony).and_yield
|
|
84
|
+
expect(config).to receive(:for_redis).and_return({})
|
|
85
|
+
expect(config).to receive(:all).twice.and_return(cfg)
|
|
86
86
|
|
|
87
87
|
processor = double('processor')
|
|
88
|
-
processor.
|
|
89
|
-
processor.
|
|
90
|
-
processor.
|
|
91
|
-
processor.
|
|
88
|
+
expect(processor).to receive(:start)
|
|
89
|
+
expect(processor).to receive(:stop)
|
|
90
|
+
expect(processor).to receive(:update_status)
|
|
91
|
+
expect(processor).to receive(:status).exactly(3).times.and_return('stopped')
|
|
92
92
|
|
|
93
93
|
notifier = double('processor')
|
|
94
|
-
notifier.
|
|
95
|
-
notifier.
|
|
96
|
-
notifier.
|
|
97
|
-
notifier.
|
|
94
|
+
expect(notifier).to receive(:start)
|
|
95
|
+
expect(notifier).to receive(:stop)
|
|
96
|
+
expect(notifier).to receive(:update_status)
|
|
97
|
+
expect(notifier).to receive(:status).exactly(3).times.and_return('stopped')
|
|
98
98
|
|
|
99
|
-
Time.
|
|
99
|
+
expect(Time).to receive(:now).and_return(time)
|
|
100
100
|
|
|
101
101
|
fc = Flapjack::Coordinator.new(config)
|
|
102
|
-
Flapjack::Pikelet.
|
|
102
|
+
expect(Flapjack::Pikelet).to receive(:create).with('processor',
|
|
103
103
|
:config => cfg['executive'], :redis_config => {}, :boot_time => time, :coordinator => fc).
|
|
104
104
|
and_return(processor)
|
|
105
|
-
Flapjack::Pikelet.
|
|
105
|
+
expect(Flapjack::Pikelet).to receive(:create).with('notifier',
|
|
106
106
|
:config => cfg['executive'], :redis_config => {}, :boot_time => time, :coordinator => fc).
|
|
107
107
|
and_return(notifier)
|
|
108
108
|
|
|
109
|
-
fiber.
|
|
110
|
-
Fiber.
|
|
109
|
+
expect(fiber).to receive(:resume)
|
|
110
|
+
expect(Fiber).to receive(:new).and_yield.and_return(fiber)
|
|
111
111
|
|
|
112
|
-
EM.
|
|
112
|
+
expect(EM).to receive(:stop)
|
|
113
113
|
|
|
114
114
|
# Syslog.should_receive(:opened?).and_return(true)
|
|
115
115
|
# Syslog.should_receive(:close)
|
|
@@ -123,28 +123,28 @@ describe Flapjack::Coordinator do
|
|
|
123
123
|
'processor' => {'foo' => 'bar'},
|
|
124
124
|
'notifier' => {'enabled' => false}
|
|
125
125
|
}
|
|
126
|
-
EM.
|
|
127
|
-
config.
|
|
128
|
-
config.
|
|
126
|
+
expect(EM).to receive(:synchrony).and_yield
|
|
127
|
+
expect(config).to receive(:for_redis).and_return({})
|
|
128
|
+
expect(config).to receive(:all).twice.and_return(cfg)
|
|
129
129
|
|
|
130
130
|
processor = double('processor')
|
|
131
|
-
processor.
|
|
132
|
-
processor.
|
|
133
|
-
processor.
|
|
134
|
-
processor.
|
|
131
|
+
expect(processor).to receive(:start)
|
|
132
|
+
expect(processor).to receive(:stop)
|
|
133
|
+
expect(processor).to receive(:update_status)
|
|
134
|
+
expect(processor).to receive(:status).exactly(3).times.and_return('stopped')
|
|
135
135
|
|
|
136
|
-
Time.
|
|
136
|
+
expect(Time).to receive(:now).and_return(time)
|
|
137
137
|
|
|
138
138
|
fc = Flapjack::Coordinator.new(config)
|
|
139
|
-
Flapjack::Pikelet.
|
|
139
|
+
expect(Flapjack::Pikelet).to receive(:create).with('processor',
|
|
140
140
|
:config => cfg['executive'].merge(cfg['processor']),
|
|
141
141
|
:redis_config => {}, :boot_time => time, :coordinator => fc).
|
|
142
142
|
and_return(processor)
|
|
143
143
|
|
|
144
|
-
fiber.
|
|
145
|
-
Fiber.
|
|
144
|
+
expect(fiber).to receive(:resume)
|
|
145
|
+
expect(Fiber).to receive(:new).and_yield.and_return(fiber)
|
|
146
146
|
|
|
147
|
-
EM.
|
|
147
|
+
expect(EM).to receive(:stop)
|
|
148
148
|
|
|
149
149
|
# Syslog.should_receive(:opened?).and_return(true)
|
|
150
150
|
# Syslog.should_receive(:close)
|
|
@@ -154,44 +154,44 @@ describe Flapjack::Coordinator do
|
|
|
154
154
|
end
|
|
155
155
|
|
|
156
156
|
it "traps system signals and shuts down" do
|
|
157
|
-
Flapjack::Logger.
|
|
157
|
+
expect(Flapjack::Logger).to receive(:new).and_return(logger)
|
|
158
158
|
|
|
159
|
-
RbConfig::CONFIG.
|
|
159
|
+
expect(RbConfig::CONFIG).to receive(:[]).with('host_os').and_return('darwin12.0.0')
|
|
160
160
|
|
|
161
|
-
Kernel.
|
|
162
|
-
Kernel.
|
|
163
|
-
Kernel.
|
|
164
|
-
Kernel.
|
|
161
|
+
expect(Kernel).to receive(:trap).with('INT').and_yield
|
|
162
|
+
expect(Kernel).to receive(:trap).with('TERM').and_yield
|
|
163
|
+
expect(Kernel).to receive(:trap).with('QUIT').and_yield
|
|
164
|
+
expect(Kernel).to receive(:trap).with('HUP').and_yield
|
|
165
165
|
|
|
166
|
-
config.
|
|
167
|
-
config.
|
|
166
|
+
expect(config).to receive(:all).and_return({})
|
|
167
|
+
expect(config).to receive(:for_redis).and_return({})
|
|
168
168
|
fc = Flapjack::Coordinator.new(config)
|
|
169
|
-
fc.
|
|
170
|
-
fc.
|
|
169
|
+
expect(fc).to receive(:stop).exactly(3).times
|
|
170
|
+
expect(fc).to receive(:reload)
|
|
171
171
|
|
|
172
172
|
fc.send(:setup_signals)
|
|
173
173
|
end
|
|
174
174
|
|
|
175
175
|
it "only traps two system signals on Windows" do
|
|
176
|
-
Flapjack::Logger.
|
|
176
|
+
expect(Flapjack::Logger).to receive(:new).and_return(logger)
|
|
177
177
|
|
|
178
|
-
RbConfig::CONFIG.
|
|
178
|
+
expect(RbConfig::CONFIG).to receive(:[]).with('host_os').and_return('mswin')
|
|
179
179
|
|
|
180
|
-
Kernel.
|
|
181
|
-
Kernel.
|
|
182
|
-
Kernel.
|
|
183
|
-
Kernel.
|
|
180
|
+
expect(Kernel).to receive(:trap).with('INT').and_yield
|
|
181
|
+
expect(Kernel).to receive(:trap).with('TERM').and_yield
|
|
182
|
+
expect(Kernel).not_to receive(:trap).with('QUIT')
|
|
183
|
+
expect(Kernel).not_to receive(:trap).with('HUP')
|
|
184
184
|
|
|
185
|
-
config.
|
|
186
|
-
config.
|
|
185
|
+
expect(config).to receive(:all).and_return({})
|
|
186
|
+
expect(config).to receive(:for_redis).and_return({})
|
|
187
187
|
fc = Flapjack::Coordinator.new(config)
|
|
188
|
-
fc.
|
|
188
|
+
expect(fc).to receive(:stop).twice
|
|
189
189
|
|
|
190
190
|
fc.send(:setup_signals)
|
|
191
191
|
end
|
|
192
192
|
|
|
193
193
|
it "stops one pikelet and starts another on reload" do
|
|
194
|
-
Flapjack::Logger.
|
|
194
|
+
expect(Flapjack::Logger).to receive(:new).and_return(logger)
|
|
195
195
|
|
|
196
196
|
old_cfg = {'processor' => {'enabled' => true}}
|
|
197
197
|
new_cfg = {'gateways' => {'jabber' => {'enabled' => true}}}
|
|
@@ -199,42 +199,42 @@ describe Flapjack::Coordinator do
|
|
|
199
199
|
new_config = double('new_config')
|
|
200
200
|
filename = double('filename')
|
|
201
201
|
|
|
202
|
-
config.
|
|
203
|
-
config.
|
|
202
|
+
expect(config).to receive(:all).twice.and_return(old_cfg)
|
|
203
|
+
expect(config).to receive(:filename).and_return(filename)
|
|
204
204
|
|
|
205
|
-
Flapjack::Configuration.
|
|
206
|
-
new_config.
|
|
207
|
-
new_config.
|
|
205
|
+
expect(Flapjack::Configuration).to receive(:new).and_return(new_config)
|
|
206
|
+
expect(new_config).to receive(:load).with(filename)
|
|
207
|
+
expect(new_config).to receive(:all).and_return(new_cfg)
|
|
208
208
|
|
|
209
209
|
processor = double('processor')
|
|
210
|
-
processor.
|
|
211
|
-
processor.
|
|
212
|
-
processor.
|
|
213
|
-
processor.
|
|
210
|
+
expect(processor).to receive(:type).twice.and_return('processor')
|
|
211
|
+
expect(processor).to receive(:stop)
|
|
212
|
+
expect(processor).to receive(:update_status)
|
|
213
|
+
expect(processor).to receive(:status).exactly(3).times.and_return('stopped')
|
|
214
214
|
|
|
215
|
-
config.
|
|
215
|
+
expect(config).to receive(:for_redis).and_return({})
|
|
216
216
|
fc = Flapjack::Coordinator.new(config)
|
|
217
217
|
|
|
218
218
|
jabber = double('jabber')
|
|
219
|
-
Flapjack::Pikelet.
|
|
219
|
+
expect(Flapjack::Pikelet).to receive(:create).
|
|
220
220
|
with('jabber', :config => {"enabled" => true}, :redis_config => {},
|
|
221
221
|
:boot_time => time, :coordinator => fc).
|
|
222
222
|
and_return(jabber)
|
|
223
|
-
jabber.
|
|
223
|
+
expect(jabber).to receive(:start)
|
|
224
224
|
|
|
225
|
-
fiber.
|
|
226
|
-
Fiber.
|
|
225
|
+
expect(fiber).to receive(:resume)
|
|
226
|
+
expect(Fiber).to receive(:new).and_yield.and_return(fiber)
|
|
227
227
|
|
|
228
228
|
fc.instance_variable_set('@boot_time', time)
|
|
229
229
|
fc.instance_variable_set('@pikelets', [processor])
|
|
230
230
|
fc.reload
|
|
231
|
-
fc.instance_variable_get('@pikelets').
|
|
231
|
+
expect(fc.instance_variable_get('@pikelets')).to eq([jabber])
|
|
232
232
|
|
|
233
233
|
|
|
234
234
|
end
|
|
235
235
|
|
|
236
236
|
it "reloads a pikelet config without restarting it" do
|
|
237
|
-
Flapjack::Logger.
|
|
237
|
+
expect(Flapjack::Logger).to receive(:new).and_return(logger)
|
|
238
238
|
|
|
239
239
|
old_cfg = {'processor' => {'enabled' => true, 'foo' => 'bar'}}
|
|
240
240
|
new_cfg = {'processor' => {'enabled' => true, 'foo' => 'baz'}}
|
|
@@ -242,29 +242,29 @@ describe Flapjack::Coordinator do
|
|
|
242
242
|
new_config = double('new_config')
|
|
243
243
|
filename = double('filename')
|
|
244
244
|
|
|
245
|
-
config.
|
|
246
|
-
config.
|
|
245
|
+
expect(config).to receive(:all).twice.and_return(old_cfg)
|
|
246
|
+
expect(config).to receive(:filename).and_return(filename)
|
|
247
247
|
|
|
248
|
-
Flapjack::Configuration.
|
|
249
|
-
new_config.
|
|
250
|
-
new_config.
|
|
248
|
+
expect(Flapjack::Configuration).to receive(:new).and_return(new_config)
|
|
249
|
+
expect(new_config).to receive(:load).with(filename)
|
|
250
|
+
expect(new_config).to receive(:all).and_return(new_cfg)
|
|
251
251
|
|
|
252
252
|
processor = double('processor')
|
|
253
|
-
processor.
|
|
254
|
-
processor.
|
|
255
|
-
processor.
|
|
256
|
-
processor.
|
|
253
|
+
expect(processor).not_to receive(:start)
|
|
254
|
+
expect(processor).to receive(:type).exactly(3).times.and_return('processor')
|
|
255
|
+
expect(processor).to receive(:reload).with(new_cfg['processor']).and_return(true)
|
|
256
|
+
expect(processor).not_to receive(:stop)
|
|
257
257
|
|
|
258
|
-
config.
|
|
258
|
+
expect(config).to receive(:for_redis).and_return({})
|
|
259
259
|
fc = Flapjack::Coordinator.new(config)
|
|
260
260
|
fc.instance_variable_set('@boot_time', time)
|
|
261
261
|
fc.instance_variable_set('@pikelets', [processor])
|
|
262
262
|
fc.reload
|
|
263
|
-
fc.instance_variable_get('@pikelets').
|
|
263
|
+
expect(fc.instance_variable_get('@pikelets')).to eq([processor])
|
|
264
264
|
end
|
|
265
265
|
|
|
266
266
|
it "reloads a pikelet config while restarting it" do
|
|
267
|
-
Flapjack::Logger.
|
|
267
|
+
expect(Flapjack::Logger).to receive(:new).and_return(logger)
|
|
268
268
|
|
|
269
269
|
old_cfg = {'processor' => {'enabled' => true, 'foo' => 'bar'}}
|
|
270
270
|
new_cfg = {'processor' => {'enabled' => true, 'baz' => 'qux'}}
|
|
@@ -272,30 +272,30 @@ describe Flapjack::Coordinator do
|
|
|
272
272
|
new_config = double('new_config')
|
|
273
273
|
filename = double('filename')
|
|
274
274
|
|
|
275
|
-
config.
|
|
276
|
-
config.
|
|
275
|
+
expect(config).to receive(:all).twice.and_return(old_cfg)
|
|
276
|
+
expect(config).to receive(:filename).and_return(filename)
|
|
277
277
|
|
|
278
|
-
Flapjack::Configuration.
|
|
279
|
-
new_config.
|
|
280
|
-
new_config.
|
|
278
|
+
expect(Flapjack::Configuration).to receive(:new).and_return(new_config)
|
|
279
|
+
expect(new_config).to receive(:load).with(filename)
|
|
280
|
+
expect(new_config).to receive(:all).and_return(new_cfg)
|
|
281
281
|
|
|
282
282
|
processor = double('processor')
|
|
283
|
-
processor.
|
|
284
|
-
processor.
|
|
285
|
-
processor.
|
|
286
|
-
processor.
|
|
287
|
-
processor.
|
|
283
|
+
expect(processor).to receive(:type).exactly(5).times.and_return('processor')
|
|
284
|
+
expect(processor).to receive(:reload).with(new_cfg['processor']).and_return(false)
|
|
285
|
+
expect(processor).to receive(:stop)
|
|
286
|
+
expect(processor).to receive(:update_status)
|
|
287
|
+
expect(processor).to receive(:status).exactly(3).times.and_return('stopped')
|
|
288
288
|
|
|
289
|
-
fiber.
|
|
290
|
-
Fiber.
|
|
289
|
+
expect(fiber).to receive(:resume)
|
|
290
|
+
expect(Fiber).to receive(:new).and_yield.and_return(fiber)
|
|
291
291
|
|
|
292
292
|
new_exec = double('new_executive')
|
|
293
|
-
new_exec.
|
|
293
|
+
expect(new_exec).to receive(:start)
|
|
294
294
|
|
|
295
|
-
config.
|
|
295
|
+
expect(config).to receive(:for_redis).and_return({})
|
|
296
296
|
fc = Flapjack::Coordinator.new(config)
|
|
297
297
|
|
|
298
|
-
Flapjack::Pikelet.
|
|
298
|
+
expect(Flapjack::Pikelet).to receive(:create).
|
|
299
299
|
with('processor', :config => new_cfg['processor'], :redis_config => {},
|
|
300
300
|
:boot_time => time, :coordinator => fc).
|
|
301
301
|
and_return(new_exec)
|
|
@@ -303,7 +303,7 @@ describe Flapjack::Coordinator do
|
|
|
303
303
|
fc.instance_variable_set('@boot_time', time)
|
|
304
304
|
fc.instance_variable_set('@pikelets', [processor])
|
|
305
305
|
fc.reload
|
|
306
|
-
fc.instance_variable_get('@pikelets').
|
|
306
|
+
expect(fc.instance_variable_get('@pikelets')).to eq([new_exec])
|
|
307
307
|
end
|
|
308
308
|
|
|
309
309
|
end
|
|
@@ -70,28 +70,36 @@ describe Flapjack::Data::Contact, :redis => true do
|
|
|
70
70
|
|
|
71
71
|
it "returns a list of all contacts" do
|
|
72
72
|
contacts = Flapjack::Data::Contact.all(:redis => @redis)
|
|
73
|
-
contacts.
|
|
74
|
-
contacts.
|
|
75
|
-
contacts.
|
|
76
|
-
contacts[0].name.
|
|
77
|
-
contacts[1].name.
|
|
73
|
+
expect(contacts).not_to be_nil
|
|
74
|
+
expect(contacts).to be_an(Array)
|
|
75
|
+
expect(contacts.size).to eq(2)
|
|
76
|
+
expect(contacts[0].name).to eq('Jane Janeley')
|
|
77
|
+
expect(contacts[1].name).to eq('John Johnson')
|
|
78
78
|
end
|
|
79
79
|
|
|
80
80
|
it "finds a contact by id" do
|
|
81
81
|
contact = Flapjack::Data::Contact.find_by_id('c362', :redis => @redis)
|
|
82
|
-
contact.
|
|
83
|
-
contact.name.
|
|
82
|
+
expect(contact).not_to be_nil
|
|
83
|
+
expect(contact.name).to eq("John Johnson")
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
it "finds contacts by ids" do
|
|
87
|
+
contacts = Flapjack::Data::Contact.find_by_ids(['c362','c363_a-f@42%*'], :redis => @redis)
|
|
88
|
+
expect(contacts).not_to be_nil
|
|
89
|
+
expect(contacts.length).to eq(2)
|
|
90
|
+
contact = contacts.first
|
|
91
|
+
expect(contact.name).to eq("John Johnson")
|
|
84
92
|
end
|
|
85
93
|
|
|
86
94
|
it "adds a contact with the same id as an existing one, clears notification rules" do
|
|
87
95
|
contact = Flapjack::Data::Contact.find_by_id('c363_a-f@42%*', :redis => @redis)
|
|
88
|
-
contact.
|
|
96
|
+
expect(contact).not_to be_nil
|
|
89
97
|
|
|
90
98
|
contact.add_notification_rule(notification_rule_data)
|
|
91
99
|
|
|
92
100
|
nr = contact.notification_rules
|
|
93
|
-
nr.
|
|
94
|
-
nr.
|
|
101
|
+
expect(nr).not_to be_nil
|
|
102
|
+
expect(nr.size).to eq(2)
|
|
95
103
|
|
|
96
104
|
Flapjack::Data::Contact.add({'id' => 'c363_a-f@42%*',
|
|
97
105
|
'first_name' => 'Smithy',
|
|
@@ -100,44 +108,44 @@ describe Flapjack::Data::Contact, :redis => true do
|
|
|
100
108
|
:redis => @redis)
|
|
101
109
|
|
|
102
110
|
contact = Flapjack::Data::Contact.find_by_id('c363_a-f@42%*', :redis => @redis)
|
|
103
|
-
contact.
|
|
104
|
-
contact.name.
|
|
111
|
+
expect(contact).not_to be_nil
|
|
112
|
+
expect(contact.name).to eq('Smithy Smith')
|
|
105
113
|
rules = contact.notification_rules
|
|
106
|
-
rules.
|
|
107
|
-
nr.map(&:id).
|
|
114
|
+
expect(rules.size).to eq(1)
|
|
115
|
+
expect(nr.map(&:id)).not_to include(rules.first.id)
|
|
108
116
|
end
|
|
109
117
|
|
|
110
118
|
it "updates a contact and clears their media settings" do
|
|
111
119
|
contact = Flapjack::Data::Contact.find_by_id('c363_a-f@42%*', :redis => @redis)
|
|
112
120
|
|
|
113
121
|
contact.update('media' => {})
|
|
114
|
-
contact.media.
|
|
122
|
+
expect(contact.media).to be_empty
|
|
115
123
|
end
|
|
116
124
|
|
|
117
125
|
it "updates a contact, does not clear notification rules" do
|
|
118
126
|
contact = Flapjack::Data::Contact.find_by_id('c363_a-f@42%*', :redis => @redis)
|
|
119
|
-
contact.
|
|
127
|
+
expect(contact).not_to be_nil
|
|
120
128
|
|
|
121
129
|
contact.add_notification_rule(notification_rule_data)
|
|
122
130
|
|
|
123
131
|
nr1 = contact.notification_rules
|
|
124
|
-
nr1.
|
|
125
|
-
nr1.
|
|
132
|
+
expect(nr1).not_to be_nil
|
|
133
|
+
expect(nr1.size).to eq(2)
|
|
126
134
|
|
|
127
135
|
contact.update('first_name' => 'John',
|
|
128
136
|
'last_name' => 'Smith',
|
|
129
137
|
'email' => 'johns@example.com')
|
|
130
|
-
contact.name.
|
|
138
|
+
expect(contact.name).to eq('John Smith')
|
|
131
139
|
|
|
132
140
|
nr2 = contact.notification_rules
|
|
133
|
-
nr2.
|
|
134
|
-
nr2.
|
|
135
|
-
nr1.map(&:id).
|
|
141
|
+
expect(nr2).not_to be_nil
|
|
142
|
+
expect(nr2.size).to eq(2)
|
|
143
|
+
expect(nr1.map(&:id)).to eq(nr2.map(&:id))
|
|
136
144
|
end
|
|
137
145
|
|
|
138
146
|
it "adds a notification rule for a contact" do
|
|
139
147
|
contact = Flapjack::Data::Contact.find_by_id('c363_a-f@42%*', :redis => @redis)
|
|
140
|
-
contact.
|
|
148
|
+
expect(contact).not_to be_nil
|
|
141
149
|
|
|
142
150
|
expect {
|
|
143
151
|
contact.add_notification_rule(notification_rule_data)
|
|
@@ -146,7 +154,7 @@ describe Flapjack::Data::Contact, :redis => true do
|
|
|
146
154
|
|
|
147
155
|
it "removes a notification rule from a contact" do
|
|
148
156
|
contact = Flapjack::Data::Contact.find_by_id('c363_a-f@42%*', :redis => @redis)
|
|
149
|
-
contact.
|
|
157
|
+
expect(contact).not_to be_nil
|
|
150
158
|
|
|
151
159
|
rule = contact.add_notification_rule(notification_rule_data)
|
|
152
160
|
|
|
@@ -161,29 +169,29 @@ describe Flapjack::Data::Contact, :redis => true do
|
|
|
161
169
|
@redis.smembers("contact_notification_rules:c363_a-f@42%*").each do |rule_id|
|
|
162
170
|
@redis.srem("contact_notification_rules:c363_a-f@42%*", rule_id)
|
|
163
171
|
end
|
|
164
|
-
@redis.smembers("contact_notification_rules:c363_a-f@42%*").
|
|
172
|
+
expect(@redis.smembers("contact_notification_rules:c363_a-f@42%*")).to be_empty
|
|
165
173
|
|
|
166
174
|
rules = contact.notification_rules
|
|
167
|
-
rules.
|
|
175
|
+
expect(rules.size).to eq(1)
|
|
168
176
|
rule = rules.first
|
|
169
177
|
[:entities, :tags, :time_restrictions,
|
|
170
178
|
:warning_media, :critical_media,
|
|
171
179
|
:warning_blackhole, :critical_blackhole].each do |k|
|
|
172
|
-
rule.send(k).
|
|
180
|
+
expect(rule.send(k)).to eq(general_notification_rule_data[k])
|
|
173
181
|
end
|
|
174
182
|
end
|
|
175
183
|
|
|
176
184
|
it "creates a general notification rule for a pre-existing contact if the existing general one was changed" do
|
|
177
185
|
contact = Flapjack::Data::Contact.find_by_id('c363_a-f@42%*', :redis => @redis)
|
|
178
186
|
rules = contact.notification_rules
|
|
179
|
-
rules.
|
|
187
|
+
expect(rules.size).to eq(1)
|
|
180
188
|
rule = rules.first
|
|
181
189
|
|
|
182
190
|
rule.update(notification_rule_data)
|
|
183
191
|
|
|
184
192
|
rules = contact.notification_rules
|
|
185
|
-
rules.
|
|
186
|
-
rules.select {|r| r.is_specific? }.
|
|
193
|
+
expect(rules.size).to eq(2)
|
|
194
|
+
expect(rules.select {|r| r.is_specific? }.size).to eq(1)
|
|
187
195
|
end
|
|
188
196
|
|
|
189
197
|
it "deletes a contact by id, including linked entities, checks, tags and notification rules" do
|
|
@@ -223,30 +231,30 @@ describe Flapjack::Data::Contact, :redis => true do
|
|
|
223
231
|
|
|
224
232
|
contact = Flapjack::Data::Contact.find_by_id('c362', :redis => @redis)
|
|
225
233
|
eandcs = contact.entities(:checks => true)
|
|
226
|
-
eandcs.
|
|
227
|
-
eandcs.
|
|
228
|
-
eandcs.
|
|
234
|
+
expect(eandcs).not_to be_nil
|
|
235
|
+
expect(eandcs).to be_an(Array)
|
|
236
|
+
expect(eandcs.size).to eq(1)
|
|
229
237
|
|
|
230
238
|
eandc = eandcs.first
|
|
231
|
-
eandc.
|
|
239
|
+
expect(eandc).to be_a(Hash)
|
|
232
240
|
|
|
233
241
|
entity = eandc[:entity]
|
|
234
|
-
entity.name.
|
|
242
|
+
expect(entity.name).to eq(entity_name)
|
|
235
243
|
checks = eandc[:checks]
|
|
236
|
-
checks.
|
|
237
|
-
checks.
|
|
238
|
-
checks.
|
|
244
|
+
expect(checks).to be_a(Set)
|
|
245
|
+
expect(checks.size).to eq(1)
|
|
246
|
+
expect(checks).to include('PING')
|
|
239
247
|
end
|
|
240
248
|
|
|
241
249
|
it "returns pagerduty credentials for a contact" do
|
|
242
250
|
contact = Flapjack::Data::Contact.find_by_id('c362', :redis => @redis)
|
|
243
251
|
credentials = contact.pagerduty_credentials
|
|
244
|
-
credentials.
|
|
245
|
-
credentials.
|
|
246
|
-
credentials.
|
|
252
|
+
expect(credentials).not_to be_nil
|
|
253
|
+
expect(credentials).to be_a(Hash)
|
|
254
|
+
expect(credentials).to eq({'service_key' => '123456789012345678901234',
|
|
247
255
|
'subdomain' => 'flpjck',
|
|
248
256
|
'username' => 'flapjack',
|
|
249
|
-
'password' => 'very_secure'}
|
|
257
|
+
'password' => 'very_secure'})
|
|
250
258
|
end
|
|
251
259
|
|
|
252
260
|
it "sets pagerduty credentials for a contact" do
|
|
@@ -256,78 +264,78 @@ describe Flapjack::Data::Contact, :redis => true do
|
|
|
256
264
|
'username' => 'flapjack',
|
|
257
265
|
'password' => 'tomato')
|
|
258
266
|
|
|
259
|
-
@redis.hget('contact_media:c362', 'pagerduty').
|
|
260
|
-
@redis.hgetall('contact_pagerduty:c362').
|
|
267
|
+
expect(@redis.hget('contact_media:c362', 'pagerduty')).to eq('567890123456789012345678')
|
|
268
|
+
expect(@redis.hgetall('contact_pagerduty:c362')).to eq({
|
|
261
269
|
'subdomain' => 'eggs',
|
|
262
270
|
'username' => 'flapjack',
|
|
263
271
|
'password' => 'tomato'
|
|
264
|
-
}
|
|
272
|
+
})
|
|
265
273
|
end
|
|
266
274
|
|
|
267
275
|
it "sets the interval for a contact's media" do
|
|
268
276
|
contact = Flapjack::Data::Contact.find_by_id('c362', :redis => @redis)
|
|
269
277
|
contact.set_interval_for_media('email', 42)
|
|
270
278
|
email_interval_raw = @redis.hget("contact_media_intervals:#{contact.id}", 'email')
|
|
271
|
-
email_interval_raw.
|
|
279
|
+
expect(email_interval_raw).to eq('42')
|
|
272
280
|
end
|
|
273
281
|
|
|
274
282
|
it "returns the interval for a contact's media" do
|
|
275
283
|
contact = Flapjack::Data::Contact.find_by_id('c363_a-f@42%*', :redis => @redis)
|
|
276
284
|
email_interval = contact.interval_for_media('email')
|
|
277
|
-
email_interval.
|
|
285
|
+
expect(email_interval).to eq(60)
|
|
278
286
|
end
|
|
279
287
|
|
|
280
288
|
it "returns default 15 mins for interval for a contact's media that has no set interval" do
|
|
281
289
|
contact = Flapjack::Data::Contact.find_by_id('c362', :redis => @redis)
|
|
282
290
|
email_interval = contact.interval_for_media('email')
|
|
283
|
-
email_interval.
|
|
291
|
+
expect(email_interval).to eq(900)
|
|
284
292
|
end
|
|
285
293
|
|
|
286
294
|
it "removes the interval for a contact's media" do
|
|
287
295
|
contact = Flapjack::Data::Contact.find_by_id('c363_a-f@42%*', :redis => @redis)
|
|
288
296
|
contact.set_interval_for_media('email', nil)
|
|
289
297
|
email_interval_raw = @redis.hget("contact_media_intervals:#{contact.id}", 'email')
|
|
290
|
-
email_interval_raw.
|
|
298
|
+
expect(email_interval_raw).to be_nil
|
|
291
299
|
end
|
|
292
300
|
|
|
293
301
|
it "sets the rollup threshold for a contact's media" do
|
|
294
302
|
contact = Flapjack::Data::Contact.find_by_id('c362', :redis => @redis)
|
|
295
303
|
email_rollup_threshold = contact.set_rollup_threshold_for_media('email', 3)
|
|
296
304
|
email_rollup_threshold_raw = @redis.hget("contact_media_rollup_thresholds:#{contact.id}", 'email')
|
|
297
|
-
email_rollup_threshold_raw.
|
|
305
|
+
expect(email_rollup_threshold_raw).to eq('3')
|
|
298
306
|
end
|
|
299
307
|
|
|
300
308
|
it "returns the rollup threshold for a contact's media" do
|
|
301
309
|
contact = Flapjack::Data::Contact.find_by_id('c363_a-f@42%*', :redis => @redis)
|
|
302
310
|
email_rollup_threshold = contact.rollup_threshold_for_media('email')
|
|
303
|
-
email_rollup_threshold.
|
|
304
|
-
email_rollup_threshold.
|
|
305
|
-
email_rollup_threshold.
|
|
311
|
+
expect(email_rollup_threshold).not_to be_nil
|
|
312
|
+
expect(email_rollup_threshold).to be_a(Integer)
|
|
313
|
+
expect(email_rollup_threshold).to eq(5)
|
|
306
314
|
end
|
|
307
315
|
|
|
308
316
|
it "removes the rollup threshold for a contact's media" do
|
|
309
317
|
contact = Flapjack::Data::Contact.find_by_id('c363_a-f@42%*', :redis => @redis)
|
|
310
318
|
email_rollup_threshold = contact.set_rollup_threshold_for_media('email', nil)
|
|
311
319
|
email_rollup_threshold_raw = @redis.hget("contact_media_rollup_thresholds:#{contact.id}", 'email')
|
|
312
|
-
email_rollup_threshold_raw.
|
|
320
|
+
expect(email_rollup_threshold_raw).to be_nil
|
|
313
321
|
end
|
|
314
322
|
|
|
315
323
|
it "sets the address for a contact's media" do
|
|
316
324
|
contact = Flapjack::Data::Contact.find_by_id('c362', :redis => @redis)
|
|
317
325
|
contact.set_address_for_media('email', 'spongebob@example.com')
|
|
318
326
|
email_address_raw = @redis.hget("contact_media:#{contact.id}", 'email')
|
|
319
|
-
email_address_raw.
|
|
327
|
+
expect(email_address_raw).to eq('spongebob@example.com')
|
|
320
328
|
end
|
|
321
329
|
|
|
322
330
|
it "removes a contact's media" do
|
|
323
331
|
contact = Flapjack::Data::Contact.find_by_id('c363_a-f@42%*', :redis => @redis)
|
|
324
332
|
contact.remove_media('email')
|
|
325
333
|
email_address_raw = @redis.hget("contac_media:#{contact.id}", 'email')
|
|
326
|
-
email_address_raw.
|
|
334
|
+
expect(email_address_raw).to be_nil
|
|
327
335
|
email_rollup_threshold_raw = @redis.hget("contact_media_rollup_thresholds:#{contact.id}", 'email')
|
|
328
|
-
email_rollup_threshold_raw.
|
|
336
|
+
expect(email_rollup_threshold_raw).to be_nil
|
|
329
337
|
email_interval_raw = @redis.hget("contact_media_intervals:#{contact.id}", 'email')
|
|
330
|
-
email_interval_raw.
|
|
338
|
+
expect(email_interval_raw).to be_nil
|
|
331
339
|
end
|
|
332
340
|
|
|
333
341
|
end
|