flapjack 0.9.6 → 1.0.0rc1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (90) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +2 -0
  3. data/.rspec +6 -0
  4. data/.travis.yml +20 -16
  5. data/CHANGELOG.md +11 -25
  6. data/Dockerfile +8 -0
  7. data/Gemfile +2 -5
  8. data/bin/flapjack +24 -213
  9. data/etc/flapjack_config.yaml.example +6 -30
  10. data/features/cli.feature +16 -14
  11. data/features/cli_flapjack-feed-events.feature +12 -13
  12. data/features/cli_flapjack-nagios-receiver.feature +14 -15
  13. data/features/cli_flapjack-populator.feature +16 -15
  14. data/features/cli_flapper.feature +12 -12
  15. data/features/cli_receive-events.feature +6 -5
  16. data/features/cli_simulate-failed-check.feature +7 -6
  17. data/features/steps/cli_steps.rb +2 -2
  18. data/features/support/env.rb +1 -0
  19. data/flapjack.gemspec +1 -0
  20. data/lib/flapjack/cli/flapper.rb +200 -0
  21. data/lib/flapjack/cli/import.rb +102 -0
  22. data/lib/flapjack/cli/receiver.rb +656 -0
  23. data/lib/flapjack/cli/server.rb +256 -0
  24. data/lib/flapjack/cli/simulate.rb +180 -0
  25. data/lib/flapjack/configuration.rb +2 -0
  26. data/lib/flapjack/data/entity_check.rb +5 -22
  27. data/lib/flapjack/data/event.rb +7 -12
  28. data/lib/flapjack/gateways/email.rb +4 -1
  29. data/lib/flapjack/gateways/jabber.rb +12 -36
  30. data/lib/flapjack/gateways/jsonapi/check_presenter.rb +6 -6
  31. data/lib/flapjack/gateways/jsonapi/report_methods.rb +5 -3
  32. data/lib/flapjack/gateways/pagerduty.rb +1 -1
  33. data/lib/flapjack/gateways/web/public/js/backbone.jsonapi.js +1 -1
  34. data/lib/flapjack/gateways/web/public/js/modules/contact.js +2 -2
  35. data/lib/flapjack/gateways/web/public/js/modules/entity.js +2 -2
  36. data/lib/flapjack/gateways/web/public/js/modules/medium.js +4 -4
  37. data/lib/flapjack/gateways/web/public/js/self_stats.js +1 -1
  38. data/lib/flapjack/gateways/web/views/check.html.erb +7 -7
  39. data/lib/flapjack/gateways/web/views/checks.html.erb +2 -3
  40. data/lib/flapjack/gateways/web/views/contact.html.erb +4 -4
  41. data/lib/flapjack/gateways/web/views/contacts.html.erb +2 -2
  42. data/lib/flapjack/gateways/web/views/edit_contacts.html.erb +1 -1
  43. data/lib/flapjack/gateways/web/views/entities.html.erb +1 -1
  44. data/lib/flapjack/gateways/web/views/entity.html.erb +1 -1
  45. data/lib/flapjack/gateways/web/views/index.html.erb +2 -2
  46. data/lib/flapjack/gateways/web/views/layout.erb +10 -10
  47. data/lib/flapjack/gateways/web/views/self_stats.html.erb +1 -1
  48. data/lib/flapjack/gateways/web.rb +36 -7
  49. data/lib/flapjack/pikelet.rb +0 -2
  50. data/lib/flapjack/processor.rb +3 -1
  51. data/lib/flapjack/redis_pool.rb +2 -6
  52. data/lib/flapjack/version.rb +1 -1
  53. data/spec/lib/flapjack/coordinator_spec.rb +3 -3
  54. data/spec/lib/flapjack/data/entity_check_spec.rb +2 -6
  55. data/spec/lib/flapjack/data/event_spec.rb +0 -31
  56. data/spec/lib/flapjack/gateways/email_spec.rb +109 -0
  57. data/spec/lib/flapjack/gateways/jabber_spec.rb +18 -16
  58. data/spec/lib/flapjack/gateways/jsonapi/check_presenter_spec.rb +12 -24
  59. data/spec/lib/flapjack/gateways/pagerduty_spec.rb +1 -1
  60. data/spec/lib/flapjack/gateways/web/views/check.html.erb_spec.rb +2 -0
  61. data/spec/lib/flapjack/gateways/web/views/contact.html.erb_spec.rb +2 -0
  62. data/spec/lib/flapjack/gateways/web/views/index.html.erb_spec.rb +2 -0
  63. data/spec/lib/flapjack/gateways/web_spec.rb +194 -145
  64. data/spec/lib/flapjack/redis_pool_spec.rb +0 -1
  65. data/spec/support/profile_all_formatter.rb +44 -0
  66. data/spec/support/uncolored_doc_formatter.rb +9 -0
  67. data/tasks/benchmarks.rake +0 -4
  68. metadata +28 -38
  69. data/.ruby-version +0 -1
  70. data/Gemfile-ruby1.9 +0 -28
  71. data/Gemfile-ruby1.9.lock +0 -227
  72. data/bin/flapjack-feed-events +0 -124
  73. data/bin/flapjack-nagios-receiver +0 -246
  74. data/bin/flapjack-nsca-receiver +0 -246
  75. data/bin/flapjack-populator +0 -132
  76. data/bin/flapper +0 -152
  77. data/bin/receive-events +0 -179
  78. data/bin/simulate-failed-check +0 -151
  79. data/lib/flapjack/data/migration.rb +0 -36
  80. data/lib/flapjack/gateways/api/contact_methods.rb +0 -369
  81. data/lib/flapjack/gateways/api/entity_check_presenter.rb +0 -218
  82. data/lib/flapjack/gateways/api/entity_methods.rb +0 -361
  83. data/lib/flapjack/gateways/api/entity_presenter.rb +0 -75
  84. data/lib/flapjack/gateways/api/rack/json_params_parser.rb +0 -26
  85. data/lib/flapjack/gateways/api.rb +0 -124
  86. data/spec/lib/flapjack/gateways/api/contact_methods_spec.rb +0 -772
  87. data/spec/lib/flapjack/gateways/api/entity_check_presenter_spec.rb +0 -211
  88. data/spec/lib/flapjack/gateways/api/entity_methods_spec.rb +0 -863
  89. data/spec/lib/flapjack/gateways/api/entity_presenter_spec.rb +0 -108
  90. data/spec/lib/flapjack/gateways/api_spec.rb +0 -30
@@ -1,151 +0,0 @@
1
- #!/usr/bin/env ruby
2
-
3
- unless $:.include?(File.dirname(__FILE__) + '/../lib/')
4
- $: << File.dirname(__FILE__) + '/../lib'
5
- end
6
-
7
- require 'optparse'
8
- require 'ostruct'
9
- require 'redis'
10
- require 'eventmachine'
11
-
12
- require 'json'
13
-
14
- require 'flapjack/configuration'
15
- require 'flapjack/data/event'
16
-
17
- def pike(message)
18
- puts "piking out: #{message}"
19
- exit 1
20
- end
21
-
22
- def send_event(event, opts)
23
- redis = opts[:redis]
24
- Flapjack::Data::Event.add(event, :redis => redis)
25
- end
26
-
27
- def fail(opts)
28
- redis = Redis.new(opts[:redis_options])
29
- stop_after = (opts[:minutes] * 60).to_i
30
- recover = opts[:recover]
31
- state = opts[:state] || 'critical'
32
- event = {
33
- 'entity' => opts[:entity] || 'foo-app-01',
34
- 'check' => opts[:check] || 'HTTP',
35
- 'type' => 'service'
36
- }
37
- failure = event.merge('state' => state, 'summary' => 'Simulated check output (test by operator)')
38
- recovery = event.merge('state' => 'ok', 'summary' => 'Simulated check output (test by operator)')
39
- key = "#{event['entity']}:#{event['check']}"
40
-
41
- puts "#{Time.now}: sending failure event (#{state}) for #{key}"
42
- send_event(failure, :redis => redis)
43
-
44
- EM.run {
45
-
46
- EM.add_timer(stop_after) do
47
- puts "#{Time.now}: stopping"
48
- if recover
49
- puts "#{Time.now}: sending recovery event for #{key}"
50
- send_event(recovery.merge('time' => Time.now.to_i), :redis => redis)
51
- end
52
- EM.stop
53
- end
54
-
55
- EM.add_periodic_timer(opts[:interval]) do
56
- puts "#{Time.now}: sending failure event (#{state}) for #{key}"
57
- send_event(failure.merge('time' => Time.now.to_i), :redis => redis)
58
- end
59
-
60
- }
61
-
62
- end
63
-
64
-
65
- options = OpenStruct.new
66
- options.config = Flapjack::Configuration::DEFAULT_CONFIG_PATH
67
- options.daemonize = nil
68
-
69
- exe = File.basename(__FILE__)
70
-
71
- optparse = OptionParser.new do |opts|
72
- opts.banner = "Usage: #{exe} COMMAND [OPTIONS]"
73
-
74
- opts.separator ""
75
- opts.separator "Commands"
76
- opts.separator " fail-and-recover"
77
- opts.separator " fail"
78
- opts.separator ""
79
- opts.separator "Options"
80
-
81
- opts.on("-c", "--config [PATH]", String, "PATH to the config file to use") do |c|
82
- options.config = c
83
- end
84
-
85
- opts.on("-n", "--environment [ENV]", String, "Environment to boot") do |e|
86
- options.environment = e
87
- end
88
-
89
- opts.on("-t", "--time MINUTES", String, "MINUTES to generate failure events for (0.75)") do |t|
90
- options.minutes = t.to_f
91
- end
92
-
93
- opts.on("-i", "--interval SECONDS", String, "SECONDS between events, can be decimal eg 0.1 (10)") do |i|
94
- options.interval = i.to_f
95
- end
96
-
97
- opts.on("-e", "--entity ENTITY", String, "ENTITY to generate failure events for ('foo-app-01')") do |e|
98
- options.entity = e
99
- end
100
-
101
- opts.on("-k", "--check CHECK", String, "CHECK to generate failure events for ('HTTP')") do |k|
102
- options.check = k
103
- end
104
-
105
- opts.on("-s", "--state STATE", String, "optional STATE to generate failure events with ('CRITICAL')") do |s|
106
- options.state = s
107
- end
108
-
109
- end
110
- optparse.parse!(ARGV)
111
-
112
- unless options.interval.to_f > 0
113
- options.interval = 10.0
114
- end
115
-
116
- unless options.minutes
117
- options.minutes = 0.75
118
- end
119
-
120
- FLAPJACK_ENV = options.environment || ENV['FLAPJACK_ENV'] || 'production'
121
-
122
- config = Flapjack::Configuration.new
123
- config.load(options.config)
124
- config_env = config.all
125
- redis_options = config.for_redis
126
-
127
- if config_env.nil? || config_env.empty?
128
- puts "No config data for environment '#{FLAPJACK_ENV}' found in '#{options.config}'"
129
- puts "\n#{optparse}"
130
- exit 1
131
- end
132
-
133
- options = {:redis_options => redis_options, :minutes => options.minutes,
134
- :entity => options.entity, :check => options.check, :state => options.state,
135
- :interval => options.interval}
136
- case ARGV[0]
137
- when "fail-and-recover"
138
- fail(options.merge(:recover => true))
139
- puts " done."
140
- when "fail"
141
- fail(options.merge(:recover => false))
142
- puts " done."
143
- else
144
- if ARGV.nil? || ARGV.empty?
145
- puts "No command provided."
146
- else
147
- puts "Unknown command provided: '#{ARGV[0]}'"
148
- end
149
- puts "\n#{optparse}"
150
- exit 1
151
- end
@@ -1,36 +0,0 @@
1
- #!/usr/bin/env ruby
2
-
3
- module Flapjack
4
- module Data
5
- class Migration
6
-
7
- def self.refresh_archive_index(options = {})
8
- raise "Redis connection not set" unless redis = options[:redis]
9
- archive_keys = redis.keys('events_archive:*')
10
- if archive_keys.empty?
11
- redis.del('known_events_archive_keys')
12
- return
13
- end
14
-
15
- grouped_keys = archive_keys.group_by do |ak|
16
- (redis.llen(ak) > 0) ? 'add' : 'remove'
17
- end
18
-
19
- {'remove' => :srem, 'add' => :sadd}.each_pair do |k, cmd|
20
- next unless grouped_keys.has_key?(k) && !grouped_keys[k].empty?
21
- redis.send(cmd, 'known_events_archive_keys', grouped_keys[k])
22
- end
23
- end
24
-
25
- def self.purge_expired_archive_index(options = {})
26
- raise "Redis connection not set" unless redis = options[:redis]
27
- return unless redis.exists('known_events_archive_keys')
28
-
29
- redis.smembers('known_events_archive_keys').each do |ak|
30
- redis.srem('known_events_archive_keys', ak) unless redis.exists(ak)
31
- end
32
- end
33
-
34
- end
35
- end
36
- end
@@ -1,369 +0,0 @@
1
- #!/usr/bin/env ruby
2
-
3
- require 'sinatra/base'
4
-
5
- require 'flapjack/data/contact'
6
- require 'flapjack/data/notification_rule'
7
-
8
- module Flapjack
9
-
10
- module Gateways
11
-
12
- class API < Sinatra::Base
13
-
14
- class ContactNotFound < RuntimeError
15
- attr_reader :contact_id
16
- def initialize(contact_id)
17
- @contact_id = contact_id
18
- end
19
- end
20
-
21
- class NotificationRuleNotFound < RuntimeError
22
- attr_reader :rule_id
23
- def initialize(rule_id)
24
- @rule_id = rule_id
25
- end
26
- end
27
-
28
- module ContactMethods
29
-
30
- module Helpers
31
-
32
- def find_contact(contact_id)
33
- contact = Flapjack::Data::Contact.find_by_id(contact_id, :logger => logger, :redis => redis)
34
- raise Flapjack::Gateways::API::ContactNotFound.new(contact_id) if contact.nil?
35
- contact
36
- end
37
-
38
- def find_rule(rule_id)
39
- rule = Flapjack::Data::NotificationRule.find_by_id(rule_id, :logger => logger, :redis => redis)
40
- raise Flapjack::Gateways::API::NotificationRuleNotFound.new(rule_id) if rule.nil?
41
- rule
42
- end
43
-
44
- def find_tags(tags)
45
- halt err(403, "no tags") if tags.nil? || tags.empty?
46
- tags
47
- end
48
-
49
- end
50
-
51
- def self.registered(app)
52
-
53
- app.helpers Flapjack::Gateways::API::ContactMethods::Helpers
54
-
55
- app.post '/contacts' do
56
- pass unless 'application/json'.eql?(request.content_type)
57
- content_type :json
58
-
59
- errors = []
60
-
61
- contacts_data = params[:contacts]
62
- if contacts_data.nil? || !contacts_data.is_a?(Enumerable)
63
- errors << "No valid contacts were submitted"
64
- else
65
- # stringifying as integer string params are automatically integered,
66
- # but our redis ids are strings
67
- contacts_data_ids = contacts_data.reject {|c| c['id'].nil? }.
68
- map {|co| co['id'].to_s }
69
-
70
- if contacts_data_ids.empty?
71
- errors << "No contacts with IDs were submitted"
72
- else
73
- contacts = Flapjack::Data::Contact.all(:redis => redis)
74
- contacts_h = hashify(*contacts) {|c| [c.id, c] }
75
- contacts_ids = contacts_h.keys
76
-
77
- # delete contacts not found in the bulk list
78
- (contacts_ids - contacts_data_ids).each do |contact_to_delete_id|
79
- contact_to_delete = contacts.detect {|c| c.id == contact_to_delete_id }
80
- contact_to_delete.delete!
81
- end
82
-
83
- # add or update contacts found in the bulk list
84
- contacts_data.reject {|cd| cd['id'].nil? }.each do |contact_data|
85
- if contacts_ids.include?(contact_data['id'].to_s)
86
- contacts_h[contact_data['id'].to_s].update(contact_data)
87
- else
88
- Flapjack::Data::Contact.add(contact_data, :redis => redis)
89
- end
90
- end
91
- end
92
- end
93
- errors.empty? ? 204 : err(403, *errors)
94
- end
95
-
96
- # Returns all the contacts
97
- # https://github.com/flapjack/flapjack/wiki/API#wiki-get_contacts
98
- app.get '/contacts' do
99
- content_type :json
100
- "[" +
101
- Flapjack::Data::Contact.all(:redis => redis).map do |contact|
102
- contact.to_json
103
- end.join(',') +
104
- "]"
105
- end
106
-
107
- # Returns the core information about the specified contact
108
- # https://github.com/flapjack/flapjack/wiki/API#wiki-get_contacts_id
109
- app.get '/contacts/:contact_id' do
110
- content_type :json
111
-
112
- contact = find_contact(params[:contact_id])
113
- contact.to_json
114
- end
115
-
116
- # Lists this contact's notification rules
117
- # https://github.com/flapjack/flapjack/wiki/API#wiki-get_contacts_id_notification_rules
118
- app.get '/contacts/:contact_id/notification_rules' do
119
- content_type :json
120
-
121
- "[" + find_contact(params[:contact_id]).notification_rules.map {|r| r.to_json }.join(',') + "]"
122
- end
123
-
124
- # Get the specified notification rule for this user
125
- # https://github.com/flapjack/flapjack/wiki/API#wiki-get_contacts_id_notification_rules_id
126
- app.get '/notification_rules/:id' do
127
- content_type :json
128
-
129
- rule = find_rule(params[:id])
130
- rule.to_json
131
- end
132
-
133
- # Creates a notification rule for a contact
134
- # https://github.com/flapjack/flapjack/wiki/API#wiki-post_contacts_id_notification_rules
135
- app.post '/notification_rules' do
136
- content_type :json
137
-
138
- if params[:id]
139
- halt err(403, "post cannot be used for update, do a put instead")
140
- end
141
-
142
- logger.debug("post /notification_rules data: ")
143
- logger.debug(params.inspect)
144
-
145
- contact = find_contact(params[:contact_id])
146
-
147
- rule_data = hashify(:entities, :regex_entities, :tags, :regex_tags,
148
- :unknown_media, :warning_media, :critical_media, :time_restrictions,
149
- :unknown_blackhole, :warning_blackhole, :critical_blackhole) {|k| [k, params[k]]}
150
-
151
- rule_or_errors = contact.add_notification_rule(rule_data, :logger => logger)
152
-
153
- unless rule_or_errors.respond_to?(:critical_media)
154
- halt err(403, *rule_or_errors)
155
- end
156
- rule_or_errors.to_json
157
- end
158
-
159
- # Updates a notification rule
160
- # https://github.com/flapjack/flapjack/wiki/API#wiki-put_notification_rules_id
161
- app.put('/notification_rules/:id') do
162
- content_type :json
163
-
164
- logger.debug("put /notification_rules/#{params[:id]} data: ")
165
- logger.debug(params.inspect)
166
-
167
- rule = find_rule(params[:id])
168
-
169
- # previous bug may have led to rule's contact_id being wiped :(
170
- contact = find_contact(rule.contact_id || params[:contact_id])
171
-
172
- rule_data = hashify(:entities, :regex_entities, :tags, :regex_tags,
173
- :unknown_media, :warning_media, :critical_media, :time_restrictions,
174
- :unknown_blackhole, :warning_blackhole, :critical_blackhole) {|k| [k, params[k]]}
175
-
176
- errors = rule.update(rule_data, :logger => logger)
177
-
178
- unless errors.nil? || errors.empty?
179
- halt err(403, *errors)
180
- end
181
- rule.to_json
182
- end
183
-
184
- # Deletes a notification rule
185
- # https://github.com/flapjack/flapjack/wiki/API#wiki-put_notification_rules_id
186
- app.delete('/notification_rules/:id') do
187
- logger.debug("delete /notification_rules/#{params[:id]}")
188
- rule = find_rule(params[:id])
189
- logger.debug("rule to delete: #{rule.inspect}, contact_id: #{rule.contact_id}")
190
- contact = find_contact(rule.contact_id)
191
- contact.delete_notification_rule(rule)
192
- status 204
193
- end
194
-
195
- # Returns the media of a contact
196
- # https://github.com/flapjack/flapjack/wiki/API#wiki-get_contacts_id_media
197
- app.get '/contacts/:contact_id/media' do
198
- content_type :json
199
-
200
- contact = find_contact(params[:contact_id])
201
-
202
- media = contact.media
203
- media_intervals = contact.media_intervals
204
- media_rollup_thresholds = contact.media_rollup_thresholds
205
- media_addr_int = hashify(*media.keys) {|k|
206
- [k, {'address' => media[k],
207
- 'interval' => media_intervals[k],
208
- 'rollup_threshold' => media_rollup_thresholds[k] }]
209
- }
210
- media_addr_int.to_json
211
- end
212
-
213
- # Returns the specified media of a contact
214
- # https://github.com/flapjack/flapjack/wiki/API#wiki-get_contacts_id_media_media
215
- app.get('/contacts/:contact_id/media/:id') do
216
- content_type :json
217
-
218
- contact = find_contact(params[:contact_id])
219
- media = contact.media[params[:id]]
220
- if media.nil?
221
- halt err(403, "no #{params[:id]} for contact '#{params[:contact_id]}'")
222
- end
223
- interval = contact.media_intervals[params[:id]]
224
- if interval.nil?
225
- halt err(403, "no #{params[:id]} interval for contact '#{params[:contact_id]}'")
226
- end
227
- rollup_threshold = contact.media_rollup_thresholds[params[:id]]
228
- {'address' => media,
229
- 'interval' => interval,
230
- 'rollup_threshold' => rollup_threshold }.to_json
231
- end
232
-
233
- # Creates or updates a media of a contact
234
- # https://github.com/flapjack/flapjack/wiki/API#wiki-put_contacts_id_media_media
235
- app.put('/contacts/:contact_id/media/:id') do
236
- content_type :json
237
-
238
- contact = find_contact(params[:contact_id])
239
- errors = []
240
-
241
- if 'pagerduty'.eql?(params[:id])
242
- errors = [:service_key, :subdomain, :username, :password].inject([]) do |memo, pdp|
243
- memo << "no #{pdp.to_s} for 'pagerduty' media" if params[pdp].nil?
244
- memo
245
- end
246
-
247
- halt err(403, *errors) unless errors.empty?
248
-
249
- contact.set_pagerduty_credentials('service_key' => params[:service_key],
250
- 'subdomain' => params[:subdomain],
251
- 'username' => params[:username],
252
- 'password' => params[:password])
253
-
254
- contact.pagerduty_credentials.to_json
255
- else
256
- if params[:address].nil?
257
- errors << "no address for '#{params[:id]}' media"
258
- end
259
-
260
- halt err(403, *errors) unless errors.empty?
261
-
262
- contact.set_address_for_media(params[:id], params[:address])
263
- contact.set_interval_for_media(params[:id], params[:interval])
264
- contact.set_rollup_threshold_for_media(params[:id], params[:rollup_threshold])
265
-
266
- {'address' => contact.media[params[:id]],
267
- 'interval' => contact.media_intervals[params[:id]],
268
- 'rollup_threshold' => contact.media_rollup_thresholds[params[:id]]}.to_json
269
- end
270
- end
271
-
272
- # delete a media of a contact
273
- app.delete('/contacts/:contact_id/media/:id') do
274
- contact = find_contact(params[:contact_id])
275
- contact.remove_media(params[:id])
276
- status 204
277
- end
278
-
279
- # Returns the timezone of a contact
280
- # https://github.com/flapjack/flapjack/wiki/API#wiki-get_contacts_id_timezone
281
- app.get('/contacts/:contact_id/timezone') do
282
- content_type :json
283
-
284
- contact = find_contact(params[:contact_id])
285
- contact.timezone.name.to_json
286
- end
287
-
288
- # Sets the timezone of a contact
289
- # https://github.com/flapjack/flapjack/wiki/API#wiki-put_contacts_id_timezone
290
- app.put('/contacts/:contact_id/timezone') do
291
- content_type :json
292
-
293
- contact = find_contact(params[:contact_id])
294
- contact.timezone = params[:timezone]
295
- contact.timezone.name.to_json
296
- end
297
-
298
- # Removes the timezone of a contact
299
- # https://github.com/flapjack/flapjack/wiki/API#wiki-put_contacts_id_timezone
300
- app.delete('/contacts/:contact_id/timezone') do
301
- contact = find_contact(params[:contact_id])
302
- contact.timezone = nil
303
- status 204
304
- end
305
-
306
- app.post '/contacts/:contact_id/tags' do
307
- content_type :json
308
-
309
- tags = find_tags(params[:tag])
310
- contact = find_contact(params[:contact_id])
311
- contact.add_tags(*tags)
312
- contact.tags.to_json
313
- end
314
-
315
- app.post '/contacts/:contact_id/entity_tags' do
316
- content_type :json
317
- contact = find_contact(params[:contact_id])
318
- contact.entities.map {|e| e[:entity]}.each do |entity|
319
- next unless tags = params[:entity][entity.name]
320
- entity.add_tags(*tags)
321
- end
322
- contact_ent_tag = hashify(*contact.entities(:tags => true)) {|et|
323
- [et[:entity].name, et[:tags]]
324
- }
325
- contact_ent_tag.to_json
326
- end
327
-
328
- app.delete '/contacts/:contact_id/tags' do
329
- tags = find_tags(params[:tag])
330
- contact = find_contact(params[:contact_id])
331
- contact.delete_tags(*tags)
332
- status 204
333
- end
334
-
335
- app.delete '/contacts/:contact_id/entity_tags' do
336
- contact = find_contact(params[:contact_id])
337
- contact.entities.map {|e| e[:entity]}.each do |entity|
338
- next unless tags = params[:entity][entity.name]
339
- entity.delete_tags(*tags)
340
- end
341
- status 204
342
- end
343
-
344
- app.get '/contacts/:contact_id/tags' do
345
- content_type :json
346
-
347
- contact = find_contact(params[:contact_id])
348
- contact.tags.to_json
349
- end
350
-
351
- app.get '/contacts/:contact_id/entity_tags' do
352
- content_type :json
353
-
354
- contact = find_contact(params[:contact_id])
355
- contact_ent_tag = hashify(*contact.entities(:tags => true)) {|et|
356
- [et[:entity].name, et[:tags]]
357
- }
358
- contact_ent_tag.to_json
359
- end
360
-
361
- end
362
-
363
- end
364
-
365
- end
366
-
367
- end
368
-
369
- end