flapjack 0.7.16 → 0.7.17
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.
- data/.gitignore +3 -0
- data/.travis.yml +1 -0
- data/CHANGELOG.md +9 -0
- data/lib/flapjack/data/entity_check.rb +13 -8
- data/lib/flapjack/data/notification_rule.rb +11 -7
- data/lib/flapjack/gateways/api.rb +28 -655
- data/lib/flapjack/gateways/api/contact_methods.rb +342 -0
- data/lib/flapjack/gateways/api/entity_methods.rb +364 -0
- data/lib/flapjack/gateways/api/entity_presenter.rb +6 -6
- data/lib/flapjack/gateways/api/rack/json_params_parser.rb +26 -0
- data/lib/flapjack/version.rb +1 -1
- data/spec/lib/flapjack/data/entity_check_spec.rb +21 -0
- data/spec/lib/flapjack/data/notification_rule_spec.rb +11 -6
- data/spec/lib/flapjack/gateways/api/contact_methods_spec.rb +709 -0
- data/spec/lib/flapjack/gateways/api/entity_check_presenter_spec.rb +1 -3
- data/spec/lib/flapjack/gateways/api/entity_methods_spec.rb +868 -0
- data/spec/lib/flapjack/gateways/api/entity_presenter_spec.rb +13 -12
- data/spec/lib/flapjack/gateways/api_spec.rb +1 -1520
- data/tmp/redis_find_spurious_unknown_states.rb +52 -0
- metadata +12 -6
- data/.rbenv-version +0 -1
- data/tmp/redis_delete_all_keys.rb +0 -11
@@ -23,33 +23,33 @@ module Flapjack
|
|
23
23
|
end
|
24
24
|
|
25
25
|
def status
|
26
|
-
checks.collect {|c| {:entity => @entity, :check => c,
|
26
|
+
checks.collect {|c| {:entity => @entity.name, :check => c,
|
27
27
|
:status => check_presenter(c).status } }
|
28
28
|
end
|
29
29
|
|
30
30
|
def outages(start_time, end_time)
|
31
31
|
checks.collect {|c|
|
32
|
-
{:entity => @entity, :check => c, :outages => check_presenter(c).outages(start_time, end_time)}
|
32
|
+
{:entity => @entity.name, :check => c, :outages => check_presenter(c).outages(start_time, end_time)}
|
33
33
|
}
|
34
34
|
end
|
35
35
|
|
36
36
|
def unscheduled_maintenances(start_time, end_time)
|
37
37
|
checks.collect {|c|
|
38
|
-
{:entity => @entity, :check => c, :unscheduled_maintenances =>
|
38
|
+
{:entity => @entity.name, :check => c, :unscheduled_maintenances =>
|
39
39
|
check_presenter(c).unscheduled_maintenances(start_time, end_time)}
|
40
40
|
}
|
41
41
|
end
|
42
42
|
|
43
43
|
def scheduled_maintenances(start_time, end_time)
|
44
44
|
checks.collect {|c|
|
45
|
-
{:entity => @entity, :check => c, :scheduled_maintenances =>
|
45
|
+
{:entity => @entity.name, :check => c, :scheduled_maintenances =>
|
46
46
|
check_presenter(c).scheduled_maintenances(start_time, end_time)}
|
47
47
|
}
|
48
48
|
end
|
49
49
|
|
50
50
|
def downtime(start_time, end_time)
|
51
51
|
checks.collect {|c|
|
52
|
-
{:entity => @entity, :check => c, :downtime =>
|
52
|
+
{:entity => @entity.name, :check => c, :downtime =>
|
53
53
|
check_presenter(c).downtime(start_time, end_time)}
|
54
54
|
}
|
55
55
|
end
|
@@ -72,4 +72,4 @@ module Flapjack
|
|
72
72
|
|
73
73
|
end
|
74
74
|
|
75
|
-
end
|
75
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'rack'
|
4
|
+
|
5
|
+
module Rack
|
6
|
+
class JsonParamsParser < Struct.new(:app)
|
7
|
+
def call(env)
|
8
|
+
if env['rack.input'] and not input_parsed?(env) and type_match?(env)
|
9
|
+
env['rack.request.form_input'] = env['rack.input']
|
10
|
+
data = env['rack.input'].read
|
11
|
+
env['rack.input'].rewind
|
12
|
+
env['rack.request.form_hash'] = data.empty? ? {} : JSON.parse(data)
|
13
|
+
end
|
14
|
+
app.call(env)
|
15
|
+
end
|
16
|
+
|
17
|
+
def input_parsed? env
|
18
|
+
env['rack.request.form_input'].eql? env['rack.input']
|
19
|
+
end
|
20
|
+
|
21
|
+
def type_match? env
|
22
|
+
type = env['CONTENT_TYPE'] and
|
23
|
+
type.split(/\s*[;,]\s*/, 2).first.downcase == 'application/json'
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
data/lib/flapjack/version.rb
CHANGED
@@ -385,6 +385,27 @@ describe Flapjack::Data::EntityCheck, :redis => true do
|
|
385
385
|
state.should == 'ok'
|
386
386
|
end
|
387
387
|
|
388
|
+
it "does not update state with a repeated state value" do
|
389
|
+
ec = Flapjack::Data::EntityCheck.for_entity_name(name, check, :redis => @redis)
|
390
|
+
ec.update_state('critical', :summary => 'small problem')
|
391
|
+
changed_at = @redis.hget("check:#{name}:#{check}", 'last_change')
|
392
|
+
summary = @redis.hget("check:#{name}:#{check}", 'summary')
|
393
|
+
|
394
|
+
ec.update_state('critical', :summary => 'big problem')
|
395
|
+
new_changed_at = @redis.hget("check:#{name}:#{check}", 'last_change')
|
396
|
+
new_summary = @redis.hget("check:#{name}:#{check}", 'summary')
|
397
|
+
|
398
|
+
changed_at.should_not be_nil
|
399
|
+
new_changed_at.should_not be_nil
|
400
|
+
new_changed_at.should == changed_at
|
401
|
+
|
402
|
+
summary.should_not be_nil
|
403
|
+
new_summary.should_not be_nil
|
404
|
+
new_summary.should_not == summary
|
405
|
+
summary.should == 'small problem'
|
406
|
+
new_summary.should == 'big problem'
|
407
|
+
end
|
408
|
+
|
388
409
|
def time_before(t, min, sec = 0)
|
389
410
|
t - ((60 * min) + sec)
|
390
411
|
end
|
@@ -52,8 +52,8 @@ describe Flapjack::Data::NotificationRule, :redis => true do
|
|
52
52
|
|
53
53
|
expect {
|
54
54
|
rule_data[:warning_blackhole] = true
|
55
|
-
|
56
|
-
|
55
|
+
errors = rule.update(rule_data)
|
56
|
+
errors.should be_nil
|
57
57
|
}.to change { rule.warning_blackhole }.from(false).to(true)
|
58
58
|
end
|
59
59
|
|
@@ -96,16 +96,21 @@ describe Flapjack::Data::NotificationRule, :redis => true do
|
|
96
96
|
|
97
97
|
it "fails to add a notification rule with invalid data" do
|
98
98
|
rule_data[:entities] = [1, {}]
|
99
|
-
|
100
|
-
|
99
|
+
rule_or_errors = Flapjack::Data::NotificationRule.add(rule_data, :redis => @redis)
|
100
|
+
rule_or_errors.should_not be_nil
|
101
|
+
rule_or_errors.should be_an(Array)
|
102
|
+
rule_or_errors.should have(1).error
|
103
|
+
rule_or_errors.should == ["Rule entities must be a list of strings"]
|
101
104
|
end
|
102
105
|
|
103
106
|
it "fails to update a notification rule with invalid data" do
|
104
107
|
rule = Flapjack::Data::NotificationRule.add(rule_data, :redis => @redis)
|
105
108
|
expect {
|
106
109
|
rule_data[:entities] = [57]
|
107
|
-
|
108
|
-
|
110
|
+
errors = rule.update(rule_data)
|
111
|
+
errors.should_not be_nil
|
112
|
+
errors.should have(1).error
|
113
|
+
errors.should == ["Rule entities must be a list of strings"]
|
109
114
|
}.not_to change { rule.entities }
|
110
115
|
end
|
111
116
|
|
@@ -0,0 +1,709 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'flapjack/gateways/api'
|
3
|
+
|
4
|
+
describe 'Flapjack::Gateways::API::ContactMethods', :sinatra => true, :logger => true, :json => true do
|
5
|
+
|
6
|
+
def app
|
7
|
+
Flapjack::Gateways::API
|
8
|
+
end
|
9
|
+
|
10
|
+
let(:contact) { mock(Flapjack::Data::Contact, :id => '21') }
|
11
|
+
let(:contact_core) {
|
12
|
+
{'id' => contact.id,
|
13
|
+
'first_name' => "Ada",
|
14
|
+
'last_name' => "Lovelace",
|
15
|
+
'email' => "ada@example.com",
|
16
|
+
'tags' => ["legend", "first computer programmer"]
|
17
|
+
}
|
18
|
+
}
|
19
|
+
|
20
|
+
let(:media) {
|
21
|
+
{'email' => 'ada@example.com',
|
22
|
+
'sms' => '04123456789'
|
23
|
+
}
|
24
|
+
}
|
25
|
+
|
26
|
+
let(:media_intervals) {
|
27
|
+
{'email' => 500,
|
28
|
+
'sms' => 300
|
29
|
+
}
|
30
|
+
}
|
31
|
+
|
32
|
+
let(:redis) { mock(::Redis) }
|
33
|
+
|
34
|
+
let(:notification_rule) {
|
35
|
+
mock(Flapjack::Data::NotificationRule, :id => '1', :contact_id => '21')
|
36
|
+
}
|
37
|
+
|
38
|
+
let(:notification_rule_data) {
|
39
|
+
{"contact_id" => "21",
|
40
|
+
"entity_tags" => ["database","physical"],
|
41
|
+
"entities" => ["foo-app-01.example.com"],
|
42
|
+
"time_restrictions" => nil,
|
43
|
+
"warning_media" => ["email"],
|
44
|
+
"critical_media" => ["sms", "email"],
|
45
|
+
"warning_blackhole" => false,
|
46
|
+
"critical_blackhole" => false
|
47
|
+
}
|
48
|
+
}
|
49
|
+
|
50
|
+
before(:all) do
|
51
|
+
Flapjack::Gateways::API.class_eval {
|
52
|
+
set :raise_errors, true
|
53
|
+
}
|
54
|
+
Flapjack::Gateways::API.instance_variable_get('@middleware').delete_if {|m|
|
55
|
+
m[0] == Rack::FiberPool
|
56
|
+
}
|
57
|
+
end
|
58
|
+
|
59
|
+
before(:each) do
|
60
|
+
Flapjack::RedisPool.should_receive(:new).and_return(redis)
|
61
|
+
Flapjack::Gateways::API.instance_variable_set('@config', {})
|
62
|
+
Flapjack::Gateways::API.instance_variable_set('@logger', @logger)
|
63
|
+
Flapjack::Gateways::API.start
|
64
|
+
end
|
65
|
+
|
66
|
+
it "creates contacts from a submitted list" do
|
67
|
+
contacts = {'contacts' =>
|
68
|
+
[{"id" => "0362",
|
69
|
+
"first_name" => "John",
|
70
|
+
"last_name" => "Smith",
|
71
|
+
"email" => "johns@example.dom",
|
72
|
+
"media" => {"email" => "johns@example.dom",
|
73
|
+
"jabber" => "johns@conference.localhost"}},
|
74
|
+
{"id" => "0363",
|
75
|
+
"first_name" => "Jane",
|
76
|
+
"last_name" => "Jones",
|
77
|
+
"email" => "jane@example.dom",
|
78
|
+
"media" => {"email" => "jane@example.dom"}}
|
79
|
+
]
|
80
|
+
}
|
81
|
+
|
82
|
+
Flapjack::Data::Contact.should_receive(:all).with(:redis => redis).and_return([])
|
83
|
+
Flapjack::Data::Contact.should_receive(:add).twice
|
84
|
+
|
85
|
+
post "/contacts", contacts.to_json, {'CONTENT_TYPE' => 'application/json'}
|
86
|
+
last_response.status.should == 204
|
87
|
+
end
|
88
|
+
|
89
|
+
it "does not create contacts if the data is improperly formatted" do
|
90
|
+
Flapjack::Data::Contact.should_not_receive(:add)
|
91
|
+
|
92
|
+
post "/contacts", {'contacts' => ["Hello", "again"]}.to_json,
|
93
|
+
{'CONTENT_TYPE' => 'application/json'}
|
94
|
+
last_response.status.should == 403
|
95
|
+
end
|
96
|
+
|
97
|
+
it "does not create contacts if they don't contain an id" do
|
98
|
+
contacts = {'contacts' =>
|
99
|
+
[{"id" => "0362",
|
100
|
+
"first_name" => "John",
|
101
|
+
"last_name" => "Smith",
|
102
|
+
"email" => "johns@example.dom",
|
103
|
+
"media" => {"email" => "johns@example.dom",
|
104
|
+
"jabber" => "johns@conference.localhost"}},
|
105
|
+
{"first_name" => "Jane",
|
106
|
+
"last_name" => "Jones",
|
107
|
+
"email" => "jane@example.dom",
|
108
|
+
"media" => {"email" => "jane@example.dom"}}
|
109
|
+
]
|
110
|
+
}
|
111
|
+
|
112
|
+
Flapjack::Data::Contact.should_receive(:all).with(:redis => redis).and_return([])
|
113
|
+
Flapjack::Data::Contact.should_receive(:add)
|
114
|
+
|
115
|
+
post "/contacts", contacts.to_json, {'CONTENT_TYPE' => 'application/json'}
|
116
|
+
last_response.status.should == 204
|
117
|
+
end
|
118
|
+
|
119
|
+
it "updates a contact if it is already present" do
|
120
|
+
contacts = {'contacts' =>
|
121
|
+
[{"id" => "0362",
|
122
|
+
"first_name" => "John",
|
123
|
+
"last_name" => "Smith",
|
124
|
+
"email" => "johns@example.dom",
|
125
|
+
"media" => {"email" => "johns@example.dom",
|
126
|
+
"jabber" => "johns@conference.localhost"}},
|
127
|
+
{"id" => "0363",
|
128
|
+
"first_name" => "Jane",
|
129
|
+
"last_name" => "Jones",
|
130
|
+
"email" => "jane@example.dom",
|
131
|
+
"media" => {"email" => "jane@example.dom"}}
|
132
|
+
]
|
133
|
+
}
|
134
|
+
|
135
|
+
existing = mock(Flapjack::Data::Contact)
|
136
|
+
existing.should_receive(:id).and_return("0363")
|
137
|
+
existing.should_receive(:update).with(contacts['contacts'][1])
|
138
|
+
|
139
|
+
Flapjack::Data::Contact.should_receive(:all).with(:redis => redis).and_return([existing])
|
140
|
+
Flapjack::Data::Contact.should_receive(:add).with(contacts['contacts'][0], :redis => redis)
|
141
|
+
|
142
|
+
post "/contacts", contacts.to_json, {'CONTENT_TYPE' => 'application/json'}
|
143
|
+
last_response.status.should == 204
|
144
|
+
end
|
145
|
+
|
146
|
+
it "deletes a contact not found in a bulk update list" do
|
147
|
+
contacts = {'contacts' =>
|
148
|
+
[{"id" => "0363",
|
149
|
+
"first_name" => "Jane",
|
150
|
+
"last_name" => "Jones",
|
151
|
+
"email" => "jane@example.dom",
|
152
|
+
"media" => {"email" => "jane@example.dom"}}
|
153
|
+
]
|
154
|
+
}
|
155
|
+
|
156
|
+
existing = mock(Flapjack::Data::Contact)
|
157
|
+
existing.should_receive(:id).twice.and_return("0362")
|
158
|
+
existing.should_receive(:delete!)
|
159
|
+
|
160
|
+
Flapjack::Data::Contact.should_receive(:all).with(:redis => redis).and_return([existing])
|
161
|
+
Flapjack::Data::Contact.should_receive(:add).with(contacts['contacts'][0], :redis => redis)
|
162
|
+
|
163
|
+
post "/contacts", contacts.to_json, {'CONTENT_TYPE' => 'application/json'}
|
164
|
+
last_response.status.should == 204
|
165
|
+
end
|
166
|
+
|
167
|
+
it "returns all the contacts" do
|
168
|
+
contact.should_receive(:to_json).and_return(contact_core.to_json)
|
169
|
+
Flapjack::Data::Contact.should_receive(:all).with(:redis => redis).
|
170
|
+
and_return([contact])
|
171
|
+
|
172
|
+
get '/contacts'
|
173
|
+
last_response.should be_ok
|
174
|
+
last_response.body.should be_json_eql([contact_core].to_json)
|
175
|
+
end
|
176
|
+
|
177
|
+
it "returns the core information of a specified contact" do
|
178
|
+
contact.should_receive(:to_json).and_return(contact_core.to_json)
|
179
|
+
Flapjack::Data::Contact.should_receive(:find_by_id).
|
180
|
+
with(contact.id, {:redis => redis, :logger => @logger}).and_return(contact)
|
181
|
+
|
182
|
+
get "/contacts/#{contact.id}"
|
183
|
+
last_response.should be_ok
|
184
|
+
last_response.body.should be_json_eql(contact_core.to_json)
|
185
|
+
end
|
186
|
+
|
187
|
+
it "does not return information for a contact that does not exist" do
|
188
|
+
Flapjack::Data::Contact.should_receive(:find_by_id).
|
189
|
+
with(contact.id, {:redis => redis, :logger => @logger}).and_return(nil)
|
190
|
+
|
191
|
+
get "/contacts/#{contact.id}"
|
192
|
+
last_response.should be_forbidden
|
193
|
+
end
|
194
|
+
|
195
|
+
it "lists a contact's notification rules" do
|
196
|
+
notification_rule_2 = mock(Flapjack::Data::NotificationRule, :id => '2', :contact_id => '21')
|
197
|
+
notification_rule.should_receive(:to_json).and_return('"rule_1"')
|
198
|
+
notification_rule_2.should_receive(:to_json).and_return('"rule_2"')
|
199
|
+
notification_rules = [ notification_rule, notification_rule_2 ]
|
200
|
+
|
201
|
+
contact.should_receive(:notification_rules).and_return(notification_rules)
|
202
|
+
Flapjack::Data::Contact.should_receive(:find_by_id).
|
203
|
+
with(contact.id, {:redis => redis, :logger => @logger}).and_return(contact)
|
204
|
+
|
205
|
+
get "/contacts/#{contact.id}/notification_rules"
|
206
|
+
last_response.should be_ok
|
207
|
+
last_response.body.should be_json_eql( '["rule_1", "rule_2"]' )
|
208
|
+
end
|
209
|
+
|
210
|
+
it "does not list notification rules for a contact that does not exist" do
|
211
|
+
Flapjack::Data::Contact.should_receive(:find_by_id).
|
212
|
+
with(contact.id, {:redis => redis, :logger => @logger}).and_return(nil)
|
213
|
+
|
214
|
+
get "/contacts/#{contact.id}/notification_rules"
|
215
|
+
last_response.should be_forbidden
|
216
|
+
end
|
217
|
+
|
218
|
+
it "returns a specified notification rule" do
|
219
|
+
notification_rule.should_receive(:to_json).and_return('"rule_1"')
|
220
|
+
Flapjack::Data::NotificationRule.should_receive(:find_by_id).
|
221
|
+
with(notification_rule.id, {:redis => redis, :logger => @logger}).and_return(notification_rule)
|
222
|
+
|
223
|
+
get "/notification_rules/#{notification_rule.id}"
|
224
|
+
last_response.should be_ok
|
225
|
+
last_response.body.should be_json_eql('"rule_1"')
|
226
|
+
end
|
227
|
+
|
228
|
+
it "does not return a notification rule that does not exist" do
|
229
|
+
Flapjack::Data::NotificationRule.should_receive(:find_by_id).
|
230
|
+
with(notification_rule.id, {:redis => redis, :logger => @logger}).and_return(nil)
|
231
|
+
|
232
|
+
get "/notification_rules/#{notification_rule.id}"
|
233
|
+
last_response.should be_forbidden
|
234
|
+
end
|
235
|
+
|
236
|
+
# POST /notification_rules
|
237
|
+
it "creates a new notification rule" do
|
238
|
+
Flapjack::Data::Contact.should_receive(:find_by_id).
|
239
|
+
with(contact.id, {:redis => redis, :logger => @logger}).and_return(contact)
|
240
|
+
notification_rule.should_receive(:respond_to?).with(:critical_media).and_return(true)
|
241
|
+
notification_rule.should_receive(:to_json).and_return('"rule_1"')
|
242
|
+
|
243
|
+
# symbolize the keys
|
244
|
+
notification_rule_data_sym = notification_rule_data.inject({}){|memo,(k,v)|
|
245
|
+
memo[k.to_sym] = v; memo
|
246
|
+
}
|
247
|
+
notification_rule_data_sym.delete(:contact_id)
|
248
|
+
|
249
|
+
contact.should_receive(:add_notification_rule).
|
250
|
+
with(notification_rule_data_sym, :logger => @logger).and_return(notification_rule)
|
251
|
+
|
252
|
+
post "/notification_rules", notification_rule_data.to_json,
|
253
|
+
{'CONTENT_TYPE' => 'application/json'}
|
254
|
+
last_response.should be_ok
|
255
|
+
last_response.body.should be_json_eql('"rule_1"')
|
256
|
+
end
|
257
|
+
|
258
|
+
it "does not create a notification_rule for a contact that's not present" do
|
259
|
+
Flapjack::Data::Contact.should_receive(:find_by_id).
|
260
|
+
with(contact.id, {:redis => redis, :logger => @logger}).and_return(nil)
|
261
|
+
|
262
|
+
post "/notification_rules", notification_rule_data.to_json,
|
263
|
+
{'CONTENT_TYPE' => 'application/json'}
|
264
|
+
last_response.should be_forbidden
|
265
|
+
end
|
266
|
+
|
267
|
+
it "does not create a notification_rule if a rule id is provided" do
|
268
|
+
contact.should_not_receive(:add_notification_rule)
|
269
|
+
|
270
|
+
post "/notification_rules", notification_rule_data.merge(:id => 1).to_json,
|
271
|
+
{'CONTENT_TYPE' => 'application/json'}
|
272
|
+
last_response.status.should == 403
|
273
|
+
end
|
274
|
+
|
275
|
+
# PUT /notification_rules/RULE_ID
|
276
|
+
it "updates a notification rule" do
|
277
|
+
Flapjack::Data::Contact.should_receive(:find_by_id).
|
278
|
+
with(contact.id, {:redis => redis, :logger => @logger}).and_return(contact)
|
279
|
+
notification_rule.should_receive(:to_json).and_return('"rule_1"')
|
280
|
+
Flapjack::Data::NotificationRule.should_receive(:find_by_id).
|
281
|
+
with(notification_rule.id, {:redis => redis, :logger => @logger}).and_return(notification_rule)
|
282
|
+
|
283
|
+
# symbolize the keys
|
284
|
+
notification_rule_data_sym = notification_rule_data.inject({}){|memo,(k,v)|
|
285
|
+
memo[k.to_sym] = v; memo
|
286
|
+
}
|
287
|
+
notification_rule_data_sym.delete(:contact_id)
|
288
|
+
|
289
|
+
notification_rule.should_receive(:update).with(notification_rule_data_sym, :logger => @logger).and_return(nil)
|
290
|
+
|
291
|
+
put "/notification_rules/#{notification_rule.id}", notification_rule_data.to_json,
|
292
|
+
{'CONTENT_TYPE' => 'application/json'}
|
293
|
+
last_response.should be_ok
|
294
|
+
last_response.body.should be_json_eql('"rule_1"')
|
295
|
+
end
|
296
|
+
|
297
|
+
it "does not update a notification rule that's not present" do
|
298
|
+
Flapjack::Data::NotificationRule.should_receive(:find_by_id).
|
299
|
+
with(notification_rule.id, {:redis => redis, :logger => @logger}).and_return(nil)
|
300
|
+
|
301
|
+
put "/notification_rules/#{notification_rule.id}", notification_rule_data
|
302
|
+
last_response.should be_forbidden
|
303
|
+
end
|
304
|
+
|
305
|
+
it "does not update a notification_rule for a contact that's not present" do
|
306
|
+
Flapjack::Data::NotificationRule.should_receive(:find_by_id).
|
307
|
+
with(notification_rule.id, {:redis => redis, :logger => @logger}).and_return(notification_rule)
|
308
|
+
Flapjack::Data::Contact.should_receive(:find_by_id).
|
309
|
+
with(contact.id, {:redis => redis, :logger => @logger}).and_return(nil)
|
310
|
+
|
311
|
+
put "/notification_rules/#{notification_rule.id}", notification_rule_data.to_json,
|
312
|
+
{'CONTENT_TYPE' => 'application/json'}
|
313
|
+
last_response.should be_forbidden
|
314
|
+
end
|
315
|
+
|
316
|
+
# DELETE /notification_rules/RULE_ID
|
317
|
+
it "deletes a notification rule" do
|
318
|
+
notification_rule.should_receive(:contact_id).and_return(contact.id)
|
319
|
+
Flapjack::Data::NotificationRule.should_receive(:find_by_id).
|
320
|
+
with(notification_rule.id, {:redis => redis, :logger => @logger}).and_return(notification_rule)
|
321
|
+
contact.should_receive(:delete_notification_rule).with(notification_rule)
|
322
|
+
Flapjack::Data::Contact.should_receive(:find_by_id).
|
323
|
+
with(contact.id, {:redis => redis, :logger => @logger}).and_return(contact)
|
324
|
+
|
325
|
+
delete "/notification_rules/#{notification_rule.id}"
|
326
|
+
last_response.status.should == 204
|
327
|
+
end
|
328
|
+
|
329
|
+
it "does not delete a notification rule that's not present" do
|
330
|
+
Flapjack::Data::NotificationRule.should_receive(:find_by_id).
|
331
|
+
with(notification_rule.id, {:redis => redis, :logger => @logger}).and_return(nil)
|
332
|
+
|
333
|
+
delete "/notification_rules/#{notification_rule.id}"
|
334
|
+
last_response.should be_forbidden
|
335
|
+
end
|
336
|
+
|
337
|
+
it "does not delete a notification rule if the contact is not present" do
|
338
|
+
notification_rule.should_receive(:contact_id).and_return(contact.id)
|
339
|
+
Flapjack::Data::NotificationRule.should_receive(:find_by_id).
|
340
|
+
with(notification_rule.id, {:redis => redis, :logger => @logger}).and_return(notification_rule)
|
341
|
+
Flapjack::Data::Contact.should_receive(:find_by_id).
|
342
|
+
with(contact.id, {:redis => redis, :logger => @logger}).and_return(nil)
|
343
|
+
|
344
|
+
delete "/notification_rules/#{notification_rule.id}"
|
345
|
+
last_response.should be_forbidden
|
346
|
+
end
|
347
|
+
|
348
|
+
# GET /contacts/CONTACT_ID/media
|
349
|
+
it "returns the media of a contact" do
|
350
|
+
contact.should_receive(:media).and_return(media)
|
351
|
+
contact.should_receive(:media_intervals).and_return(media_intervals)
|
352
|
+
Flapjack::Data::Contact.should_receive(:find_by_id).
|
353
|
+
with(contact.id, {:redis => redis, :logger => @logger}).and_return(contact)
|
354
|
+
result = Hash[ *(media.keys.collect {|m|
|
355
|
+
[m, {'address' => media[m],
|
356
|
+
'interval' => media_intervals[m] }]
|
357
|
+
}).flatten(1)].to_json
|
358
|
+
|
359
|
+
get "/contacts/#{contact.id}/media"
|
360
|
+
last_response.should be_ok
|
361
|
+
last_response.body.should be_json_eql(result)
|
362
|
+
end
|
363
|
+
|
364
|
+
it "does not return the media of a contact if the contact is not present" do
|
365
|
+
Flapjack::Data::Contact.should_receive(:find_by_id).
|
366
|
+
with(contact.id, {:redis => redis, :logger => @logger}).and_return(nil)
|
367
|
+
|
368
|
+
get "/contacts/#{contact.id}/media"
|
369
|
+
last_response.should be_forbidden
|
370
|
+
end
|
371
|
+
|
372
|
+
# GET /contacts/CONTACT_ID/media/MEDIA
|
373
|
+
it "returns the specified media of a contact" do
|
374
|
+
contact.should_receive(:media).and_return(media)
|
375
|
+
contact.should_receive(:media_intervals).and_return(media_intervals)
|
376
|
+
Flapjack::Data::Contact.should_receive(:find_by_id).
|
377
|
+
with(contact.id, {:redis => redis, :logger => @logger}).and_return(contact)
|
378
|
+
|
379
|
+
result = {'address' => media['sms'], 'interval' => media_intervals['sms']}
|
380
|
+
|
381
|
+
get "/contacts/#{contact.id}/media/sms"
|
382
|
+
last_response.should be_ok
|
383
|
+
last_response.body.should be_json_eql(result.to_json)
|
384
|
+
end
|
385
|
+
|
386
|
+
it "does not return the media of a contact if the contact is not present" do
|
387
|
+
Flapjack::Data::Contact.should_receive(:find_by_id).
|
388
|
+
with(contact.id, {:redis => redis, :logger => @logger}).and_return(nil)
|
389
|
+
|
390
|
+
get "/contacts/#{contact.id}/media/sms"
|
391
|
+
last_response.should be_forbidden
|
392
|
+
end
|
393
|
+
|
394
|
+
it "does not return the media of a contact if the media is not present" do
|
395
|
+
contact.should_receive(:media).and_return(media)
|
396
|
+
Flapjack::Data::Contact.should_receive(:find_by_id).
|
397
|
+
with(contact.id, {:redis => redis, :logger => @logger}).and_return(contact)
|
398
|
+
|
399
|
+
get "/contacts/#{contact.id}/media/telepathy"
|
400
|
+
last_response.should be_forbidden
|
401
|
+
end
|
402
|
+
|
403
|
+
# PUT, DELETE /contacts/CONTACT_ID/media/MEDIA
|
404
|
+
it "creates/updates a media of a contact" do
|
405
|
+
# as far as API is concerned these are the same -- contact.rb spec test
|
406
|
+
# may distinguish between them
|
407
|
+
alt_media = media.merge('sms' => '04987654321')
|
408
|
+
alt_media_intervals = media_intervals.merge('sms' => '200')
|
409
|
+
|
410
|
+
contact.should_receive(:set_address_for_media).with('sms', '04987654321')
|
411
|
+
contact.should_receive(:set_interval_for_media).with('sms', '200')
|
412
|
+
contact.should_receive(:media).and_return(alt_media)
|
413
|
+
contact.should_receive(:media_intervals).and_return(alt_media_intervals)
|
414
|
+
Flapjack::Data::Contact.should_receive(:find_by_id).
|
415
|
+
with(contact.id, {:redis => redis, :logger => @logger}).and_return(contact)
|
416
|
+
|
417
|
+
result = {'address' => alt_media['sms'], 'interval' => alt_media_intervals['sms']}
|
418
|
+
|
419
|
+
put "/contacts/#{contact.id}/media/sms", {:address => '04987654321', :interval => '200'}
|
420
|
+
last_response.should be_ok
|
421
|
+
last_response.body.should be_json_eql(result.to_json)
|
422
|
+
end
|
423
|
+
|
424
|
+
it "does not create a media of a contact that's not present" do
|
425
|
+
Flapjack::Data::Contact.should_receive(:find_by_id).
|
426
|
+
with(contact.id, {:redis => redis, :logger => @logger}).and_return(nil)
|
427
|
+
|
428
|
+
put "/contacts/#{contact.id}/media/sms", {:address => '04987654321', :interval => '200'}
|
429
|
+
last_response.should be_forbidden
|
430
|
+
end
|
431
|
+
|
432
|
+
it "does not create a media of a contact if no address is provided" do
|
433
|
+
Flapjack::Data::Contact.should_receive(:find_by_id).
|
434
|
+
with(contact.id, {:redis => redis, :logger => @logger}).and_return(contact)
|
435
|
+
|
436
|
+
put "/contacts/#{contact.id}/media/sms", {:interval => '200'}
|
437
|
+
last_response.should be_forbidden
|
438
|
+
end
|
439
|
+
|
440
|
+
it "creates a media of a contact even if no interval is provided" do
|
441
|
+
alt_media = media.merge('sms' => '04987654321')
|
442
|
+
alt_media_intervals = media_intervals.merge('sms' => nil)
|
443
|
+
|
444
|
+
contact.should_receive(:set_address_for_media).with('sms', '04987654321')
|
445
|
+
contact.should_receive(:set_interval_for_media).with('sms', nil)
|
446
|
+
contact.should_receive(:media).and_return(alt_media)
|
447
|
+
contact.should_receive(:media_intervals).and_return(alt_media_intervals)
|
448
|
+
Flapjack::Data::Contact.should_receive(:find_by_id).
|
449
|
+
with(contact.id, {:redis => redis, :logger => @logger}).and_return(contact)
|
450
|
+
|
451
|
+
put "/contacts/#{contact.id}/media/sms", {:address => '04987654321'}
|
452
|
+
last_response.should be_ok
|
453
|
+
end
|
454
|
+
|
455
|
+
it "deletes a media of a contact" do
|
456
|
+
contact.should_receive(:remove_media).with('sms')
|
457
|
+
Flapjack::Data::Contact.should_receive(:find_by_id).
|
458
|
+
with(contact.id, {:redis => redis, :logger => @logger}).and_return(contact)
|
459
|
+
|
460
|
+
delete "/contacts/#{contact.id}/media/sms"
|
461
|
+
last_response.status.should == 204
|
462
|
+
end
|
463
|
+
|
464
|
+
it "does not delete a media of a contact that's not present" do
|
465
|
+
Flapjack::Data::Contact.should_receive(:find_by_id).
|
466
|
+
with(contact.id, {:redis => redis, :logger => @logger}).and_return(nil)
|
467
|
+
|
468
|
+
delete "/contacts/#{contact.id}/media/sms"
|
469
|
+
last_response.should be_forbidden
|
470
|
+
end
|
471
|
+
|
472
|
+
# GET /contacts/CONTACT_ID/timezone
|
473
|
+
it "returns the timezone of a contact" do
|
474
|
+
contact.should_receive(:timezone).and_return(::ActiveSupport::TimeZone.new('Australia/Sydney'))
|
475
|
+
Flapjack::Data::Contact.should_receive(:find_by_id).
|
476
|
+
with(contact.id, {:redis => redis, :logger => @logger}).and_return(contact)
|
477
|
+
|
478
|
+
get "/contacts/#{contact.id}/timezone"
|
479
|
+
last_response.should be_ok
|
480
|
+
last_response.body.should be_json_eql('"Australia/Sydney"')
|
481
|
+
end
|
482
|
+
|
483
|
+
it "doesn't get the timezone of a contact that doesn't exist" do
|
484
|
+
Flapjack::Data::Contact.should_receive(:find_by_id).
|
485
|
+
with(contact.id, {:redis => redis, :logger => @logger}).and_return(nil)
|
486
|
+
|
487
|
+
get "/contacts/#{contact.id}/timezone"
|
488
|
+
last_response.should be_forbidden
|
489
|
+
end
|
490
|
+
|
491
|
+
# PUT /contacts/CONTACT_ID/timezone
|
492
|
+
it "sets the timezone of a contact" do
|
493
|
+
contact.should_receive(:timezone=).with('Australia/Perth')
|
494
|
+
contact.should_receive(:timezone).and_return(ActiveSupport::TimeZone.new('Australia/Perth'))
|
495
|
+
Flapjack::Data::Contact.should_receive(:find_by_id).
|
496
|
+
with(contact.id, {:redis => redis, :logger => @logger}).and_return(contact)
|
497
|
+
|
498
|
+
put "/contacts/#{contact.id}/timezone", {:timezone => 'Australia/Perth'}
|
499
|
+
last_response.should be_ok
|
500
|
+
end
|
501
|
+
|
502
|
+
it "doesn't set the timezone of a contact who can't be found" do
|
503
|
+
Flapjack::Data::Contact.should_receive(:find_by_id).
|
504
|
+
with(contact.id, {:redis => redis, :logger => @logger}).and_return(nil)
|
505
|
+
|
506
|
+
put "/contacts/#{contact.id}/timezone", {:timezone => 'Australia/Perth'}
|
507
|
+
last_response.should be_forbidden
|
508
|
+
end
|
509
|
+
|
510
|
+
# DELETE /contacts/CONTACT_ID/timezone
|
511
|
+
it "deletes the timezone of a contact" do
|
512
|
+
contact.should_receive(:timezone=).with(nil)
|
513
|
+
Flapjack::Data::Contact.should_receive(:find_by_id).
|
514
|
+
with(contact.id, {:redis => redis, :logger => @logger}).and_return(contact)
|
515
|
+
|
516
|
+
delete "/contacts/#{contact.id}/timezone"
|
517
|
+
last_response.status.should == 204
|
518
|
+
end
|
519
|
+
|
520
|
+
it "does not delete the timezone of a contact that's not present" do
|
521
|
+
Flapjack::Data::Contact.should_receive(:find_by_id).
|
522
|
+
with(contact.id, {:redis => redis, :logger => @logger}).and_return(nil)
|
523
|
+
|
524
|
+
delete "/contacts/#{contact.id}/timezone"
|
525
|
+
last_response.should be_forbidden
|
526
|
+
end
|
527
|
+
|
528
|
+
it "sets a single tag on a contact and returns current tags" do
|
529
|
+
contact.should_receive(:add_tags).with('web')
|
530
|
+
contact.should_receive(:tags).and_return(['web'])
|
531
|
+
Flapjack::Data::Contact.should_receive(:find_by_id).
|
532
|
+
with(contact.id, {:redis => redis, :logger => @logger}).and_return(contact)
|
533
|
+
|
534
|
+
post "contacts/#{contact.id}/tags", :tag => 'web'
|
535
|
+
last_response.should be_ok
|
536
|
+
last_response.body.should be_json_eql( ['web'].to_json )
|
537
|
+
end
|
538
|
+
|
539
|
+
it "does not set a single tag on a contact that's not found" do
|
540
|
+
Flapjack::Data::Contact.should_receive(:find_by_id).
|
541
|
+
with(contact.id, {:redis => redis, :logger => @logger}).and_return(nil)
|
542
|
+
|
543
|
+
post "contacts/#{contact.id}/tags", :tag => 'web'
|
544
|
+
last_response.should be_forbidden
|
545
|
+
end
|
546
|
+
|
547
|
+
it "sets multiple tags on a contact and returns current tags" do
|
548
|
+
contact.should_receive(:add_tags).with('web', 'app')
|
549
|
+
contact.should_receive(:tags).and_return(['web', 'app'])
|
550
|
+
Flapjack::Data::Contact.should_receive(:find_by_id).
|
551
|
+
with(contact.id, {:redis => redis, :logger => @logger}).and_return(contact)
|
552
|
+
|
553
|
+
post "contacts/#{contact.id}/tags", :tag => ['web', 'app']
|
554
|
+
last_response.should be_ok
|
555
|
+
last_response.body.should be_json_eql( ['web', 'app'].to_json )
|
556
|
+
end
|
557
|
+
|
558
|
+
it "does not set multiple tags on a contact that's not found" do
|
559
|
+
Flapjack::Data::Contact.should_receive(:find_by_id).
|
560
|
+
with(contact.id, {:redis => redis, :logger => @logger}).and_return(nil)
|
561
|
+
|
562
|
+
post "contacts/#{contact.id}/tags", :tag => ['web', 'app']
|
563
|
+
last_response.should be_forbidden
|
564
|
+
end
|
565
|
+
|
566
|
+
it "removes a single tag from a contact" do
|
567
|
+
contact.should_receive(:delete_tags).with('web')
|
568
|
+
Flapjack::Data::Contact.should_receive(:find_by_id).
|
569
|
+
with(contact.id, {:redis => redis, :logger => @logger}).and_return(contact)
|
570
|
+
|
571
|
+
delete "contacts/#{contact.id}/tags", :tag => 'web'
|
572
|
+
last_response.status.should == 204
|
573
|
+
end
|
574
|
+
|
575
|
+
it "does not remove a single tag from a contact that's not found" do
|
576
|
+
Flapjack::Data::Contact.should_receive(:find_by_id).
|
577
|
+
with(contact.id, {:redis => redis, :logger => @logger}).and_return(nil)
|
578
|
+
|
579
|
+
delete "contacts/#{contact.id}/tags", :tag => 'web'
|
580
|
+
last_response.should be_forbidden
|
581
|
+
end
|
582
|
+
|
583
|
+
it "removes multiple tags from a contact" do
|
584
|
+
contact.should_receive(:delete_tags).with('web', 'app')
|
585
|
+
Flapjack::Data::Contact.should_receive(:find_by_id).
|
586
|
+
with(contact.id, {:redis => redis, :logger => @logger}).and_return(contact)
|
587
|
+
|
588
|
+
delete "contacts/#{contact.id}/tags", :tag => ['web', 'app']
|
589
|
+
last_response.status.should == 204
|
590
|
+
end
|
591
|
+
|
592
|
+
it "does not remove multiple tags from a contact that's not found" do
|
593
|
+
Flapjack::Data::Contact.should_receive(:find_by_id).
|
594
|
+
with(contact.id, {:redis => redis, :logger => @logger}).and_return(nil)
|
595
|
+
|
596
|
+
delete "contacts/#{contact.id}/tags", :tag => ['web', 'app']
|
597
|
+
last_response.should be_forbidden
|
598
|
+
end
|
599
|
+
|
600
|
+
it "gets all tags on a contact" do
|
601
|
+
contact.should_receive(:tags).and_return(['web', 'app'])
|
602
|
+
Flapjack::Data::Contact.should_receive(:find_by_id).
|
603
|
+
with(contact.id, {:redis => redis, :logger => @logger}).and_return(contact)
|
604
|
+
|
605
|
+
get "contacts/#{contact.id}/tags"
|
606
|
+
last_response.should be_ok
|
607
|
+
last_response.body.should be_json_eql( ['web', 'app'].to_json )
|
608
|
+
end
|
609
|
+
|
610
|
+
it "does not get all tags on a contact that's not found" do
|
611
|
+
Flapjack::Data::Contact.should_receive(:find_by_id).
|
612
|
+
with(contact.id, {:redis => redis, :logger => @logger}).and_return(nil)
|
613
|
+
|
614
|
+
get "contacts/#{contact.id}/tags"
|
615
|
+
last_response.should be_forbidden
|
616
|
+
end
|
617
|
+
|
618
|
+
it "gets all entity tags for a contact" do
|
619
|
+
entity_1 = mock(Flapjack::Data::Entity)
|
620
|
+
entity_1.should_receive(:name).and_return('entity_1')
|
621
|
+
entity_2 = mock(Flapjack::Data::Entity)
|
622
|
+
entity_2.should_receive(:name).and_return('entity_2')
|
623
|
+
tag_data = [{:entity => entity_1, :tags => ['web']},
|
624
|
+
{:entity => entity_2, :tags => ['app']}]
|
625
|
+
contact.should_receive(:entities).with(:tags => true).
|
626
|
+
and_return(tag_data)
|
627
|
+
|
628
|
+
Flapjack::Data::Contact.should_receive(:find_by_id).
|
629
|
+
with(contact.id, {:redis => redis, :logger => @logger}).and_return(contact)
|
630
|
+
|
631
|
+
get "contacts/#{contact.id}/entity_tags"
|
632
|
+
last_response.should be_ok
|
633
|
+
tag_response = {'entity_1' => ['web'],
|
634
|
+
'entity_2' => ['app']}
|
635
|
+
last_response.body.should be_json_eql( tag_response.to_json )
|
636
|
+
end
|
637
|
+
|
638
|
+
it "does not get all entity tags for a contact that's not found" do
|
639
|
+
Flapjack::Data::Contact.should_receive(:find_by_id).
|
640
|
+
with(contact.id, {:redis => redis, :logger => @logger}).and_return(nil)
|
641
|
+
|
642
|
+
get "contacts/#{contact.id}/entity_tags"
|
643
|
+
last_response.should be_forbidden
|
644
|
+
end
|
645
|
+
|
646
|
+
it "adds tags to multiple entities for a contact" do
|
647
|
+
entity_1 = mock(Flapjack::Data::Entity)
|
648
|
+
entity_1.should_receive(:name).twice.and_return('entity_1')
|
649
|
+
entity_1.should_receive(:add_tags).with('web')
|
650
|
+
entity_2 = mock(Flapjack::Data::Entity)
|
651
|
+
entity_2.should_receive(:name).twice.and_return('entity_2')
|
652
|
+
entity_2.should_receive(:add_tags).with('app')
|
653
|
+
|
654
|
+
entities = [{:entity => entity_1}, {:entity => entity_2}]
|
655
|
+
contact.should_receive(:entities).and_return(entities)
|
656
|
+
tag_data = [{:entity => entity_1, :tags => ['web']},
|
657
|
+
{:entity => entity_2, :tags => ['app']}]
|
658
|
+
contact.should_receive(:entities).with(:tags => true).and_return(tag_data)
|
659
|
+
|
660
|
+
Flapjack::Data::Contact.should_receive(:find_by_id).
|
661
|
+
with(contact.id, {:redis => redis, :logger => @logger}).and_return(contact)
|
662
|
+
|
663
|
+
post "contacts/#{contact.id}/entity_tags",
|
664
|
+
:entity => {'entity_1' => ['web'], 'entity_2' => ['app']}
|
665
|
+
last_response.should be_ok
|
666
|
+
tag_response = {'entity_1' => ['web'],
|
667
|
+
'entity_2' => ['app']}
|
668
|
+
last_response.body.should be_json_eql( tag_response.to_json )
|
669
|
+
end
|
670
|
+
|
671
|
+
it "does not add tags to multiple entities for a contact that's not found" do
|
672
|
+
Flapjack::Data::Contact.should_receive(:find_by_id).
|
673
|
+
with(contact.id, {:redis => redis, :logger => @logger}).and_return(nil)
|
674
|
+
|
675
|
+
post "contacts/#{contact.id}/entity_tags",
|
676
|
+
:entity => {'entity_1' => ['web'], 'entity_2' => ['app']}
|
677
|
+
last_response.should be_forbidden
|
678
|
+
end
|
679
|
+
|
680
|
+
it "deletes tags from multiple entities for a contact" do
|
681
|
+
entity_1 = mock(Flapjack::Data::Entity)
|
682
|
+
entity_1.should_receive(:name).and_return('entity_1')
|
683
|
+
entity_1.should_receive(:delete_tags).with('web')
|
684
|
+
entity_2 = mock(Flapjack::Data::Entity)
|
685
|
+
entity_2.should_receive(:name).and_return('entity_2')
|
686
|
+
entity_2.should_receive(:delete_tags).with('app')
|
687
|
+
|
688
|
+
entities = [{:entity => entity_1}, {:entity => entity_2}]
|
689
|
+
contact.should_receive(:entities).and_return(entities)
|
690
|
+
|
691
|
+
Flapjack::Data::Contact.should_receive(:find_by_id).
|
692
|
+
with(contact.id, {:redis => redis, :logger => @logger}).and_return(contact)
|
693
|
+
|
694
|
+
delete "contacts/#{contact.id}/entity_tags",
|
695
|
+
:entity => {'entity_1' => ['web'], 'entity_2' => ['app']}
|
696
|
+
last_response.status.should == 204
|
697
|
+
end
|
698
|
+
|
699
|
+
it "does not delete tags from multiple entities for a contact that's not found" do
|
700
|
+
Flapjack::Data::Contact.should_receive(:find_by_id).
|
701
|
+
with(contact.id, {:redis => redis, :logger => @logger}).and_return(nil)
|
702
|
+
|
703
|
+
delete "contacts/#{contact.id}/entity_tags",
|
704
|
+
:entity => {'entity_1' => ['web'], 'entity_2' => ['app']}
|
705
|
+
last_response.should be_forbidden
|
706
|
+
end
|
707
|
+
|
708
|
+
|
709
|
+
end
|