scout 2.0.7 → 4.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (128) hide show
  1. data/CHANGELOG +15 -0
  2. data/Rakefile +14 -59
  3. data/data/cacert.pem +3154 -0
  4. data/data/gpl-2.0.txt +339 -0
  5. data/data/lgpl-2.1.txt +504 -0
  6. data/lib/scout.rb +4 -4
  7. data/lib/scout/command.rb +9 -0
  8. data/lib/scout/command/test.rb +8 -6
  9. data/lib/scout/plugin.rb +17 -6
  10. data/lib/scout/server.rb +127 -123
  11. data/vendor/json_pure/CHANGES +119 -0
  12. data/vendor/json_pure/GPL +340 -0
  13. data/vendor/json_pure/README +78 -0
  14. data/vendor/json_pure/RUBY +58 -0
  15. data/vendor/json_pure/Rakefile +270 -0
  16. data/vendor/json_pure/TODO +1 -0
  17. data/vendor/json_pure/VERSION +1 -0
  18. data/vendor/json_pure/benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkComparison.log +52 -0
  19. data/vendor/json_pure/benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkExt#generator_fast-autocorrelation.dat +1000 -0
  20. data/vendor/json_pure/benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkExt#generator_fast.dat +1001 -0
  21. data/vendor/json_pure/benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkExt#generator_pretty-autocorrelation.dat +900 -0
  22. data/vendor/json_pure/benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkExt#generator_pretty.dat +901 -0
  23. data/vendor/json_pure/benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkExt#generator_safe-autocorrelation.dat +1000 -0
  24. data/vendor/json_pure/benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkExt#generator_safe.dat +1001 -0
  25. data/vendor/json_pure/benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkExt.log +261 -0
  26. data/vendor/json_pure/benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkPure#generator_fast-autocorrelation.dat +1000 -0
  27. data/vendor/json_pure/benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkPure#generator_fast.dat +1001 -0
  28. data/vendor/json_pure/benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkPure#generator_pretty-autocorrelation.dat +1000 -0
  29. data/vendor/json_pure/benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkPure#generator_pretty.dat +1001 -0
  30. data/vendor/json_pure/benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkPure#generator_safe-autocorrelation.dat +1000 -0
  31. data/vendor/json_pure/benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkPure#generator_safe.dat +1001 -0
  32. data/vendor/json_pure/benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkPure.log +262 -0
  33. data/vendor/json_pure/benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkRails#generator-autocorrelation.dat +1000 -0
  34. data/vendor/json_pure/benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkRails#generator.dat +1001 -0
  35. data/vendor/json_pure/benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkRails.log +82 -0
  36. data/vendor/json_pure/benchmarks/data-p4-3GHz-ruby18/ParserBenchmarkComparison.log +34 -0
  37. data/vendor/json_pure/benchmarks/data-p4-3GHz-ruby18/ParserBenchmarkExt#parser-autocorrelation.dat +900 -0
  38. data/vendor/json_pure/benchmarks/data-p4-3GHz-ruby18/ParserBenchmarkExt#parser.dat +901 -0
  39. data/vendor/json_pure/benchmarks/data-p4-3GHz-ruby18/ParserBenchmarkExt.log +81 -0
  40. data/vendor/json_pure/benchmarks/data-p4-3GHz-ruby18/ParserBenchmarkPure#parser-autocorrelation.dat +1000 -0
  41. data/vendor/json_pure/benchmarks/data-p4-3GHz-ruby18/ParserBenchmarkPure#parser.dat +1001 -0
  42. data/vendor/json_pure/benchmarks/data-p4-3GHz-ruby18/ParserBenchmarkPure.log +82 -0
  43. data/vendor/json_pure/benchmarks/data-p4-3GHz-ruby18/ParserBenchmarkRails#parser-autocorrelation.dat +1000 -0
  44. data/vendor/json_pure/benchmarks/data-p4-3GHz-ruby18/ParserBenchmarkRails#parser.dat +1001 -0
  45. data/vendor/json_pure/benchmarks/data-p4-3GHz-ruby18/ParserBenchmarkRails.log +82 -0
  46. data/vendor/json_pure/benchmarks/data-p4-3GHz-ruby18/ParserBenchmarkYAML#parser-autocorrelation.dat +1000 -0
  47. data/vendor/json_pure/benchmarks/data-p4-3GHz-ruby18/ParserBenchmarkYAML#parser.dat +1001 -0
  48. data/vendor/json_pure/benchmarks/data-p4-3GHz-ruby18/ParserBenchmarkYAML.log +82 -0
  49. data/vendor/json_pure/benchmarks/generator_benchmark.rb +165 -0
  50. data/vendor/json_pure/benchmarks/parser_benchmark.rb +197 -0
  51. data/vendor/json_pure/bin/edit_json.rb +9 -0
  52. data/vendor/json_pure/bin/prettify_json.rb +75 -0
  53. data/vendor/json_pure/data/example.json +1 -0
  54. data/vendor/json_pure/data/index.html +38 -0
  55. data/vendor/json_pure/data/prototype.js +4184 -0
  56. data/vendor/json_pure/doc-templates/main.txt +283 -0
  57. data/vendor/json_pure/ext/json/ext/generator/extconf.rb +11 -0
  58. data/vendor/json_pure/ext/json/ext/generator/generator.c +919 -0
  59. data/vendor/json_pure/ext/json/ext/generator/unicode.c +182 -0
  60. data/vendor/json_pure/ext/json/ext/generator/unicode.h +53 -0
  61. data/vendor/json_pure/ext/json/ext/parser/extconf.rb +11 -0
  62. data/vendor/json_pure/ext/json/ext/parser/parser.c +1829 -0
  63. data/vendor/json_pure/ext/json/ext/parser/parser.rl +686 -0
  64. data/vendor/json_pure/ext/json/ext/parser/unicode.c +154 -0
  65. data/vendor/json_pure/ext/json/ext/parser/unicode.h +58 -0
  66. data/vendor/json_pure/install.rb +26 -0
  67. data/vendor/json_pure/lib/json.rb +10 -0
  68. data/vendor/json_pure/lib/json/Array.xpm +21 -0
  69. data/vendor/json_pure/lib/json/FalseClass.xpm +21 -0
  70. data/vendor/json_pure/lib/json/Hash.xpm +21 -0
  71. data/vendor/json_pure/lib/json/Key.xpm +73 -0
  72. data/vendor/json_pure/lib/json/NilClass.xpm +21 -0
  73. data/vendor/json_pure/lib/json/Numeric.xpm +28 -0
  74. data/vendor/json_pure/lib/json/String.xpm +96 -0
  75. data/vendor/json_pure/lib/json/TrueClass.xpm +21 -0
  76. data/vendor/json_pure/lib/json/add/core.rb +135 -0
  77. data/vendor/json_pure/lib/json/add/rails.rb +58 -0
  78. data/vendor/json_pure/lib/json/common.rb +354 -0
  79. data/vendor/json_pure/lib/json/editor.rb +1371 -0
  80. data/vendor/json_pure/lib/json/ext.rb +15 -0
  81. data/vendor/json_pure/lib/json/json.xpm +1499 -0
  82. data/vendor/json_pure/lib/json/pure.rb +77 -0
  83. data/vendor/json_pure/lib/json/pure/generator.rb +430 -0
  84. data/vendor/json_pure/lib/json/pure/parser.rb +269 -0
  85. data/vendor/json_pure/lib/json/version.rb +8 -0
  86. data/vendor/json_pure/tests/fixtures/fail1.json +1 -0
  87. data/vendor/json_pure/tests/fixtures/fail10.json +1 -0
  88. data/vendor/json_pure/tests/fixtures/fail11.json +1 -0
  89. data/vendor/json_pure/tests/fixtures/fail12.json +1 -0
  90. data/vendor/json_pure/tests/fixtures/fail13.json +1 -0
  91. data/vendor/json_pure/tests/fixtures/fail14.json +1 -0
  92. data/vendor/json_pure/tests/fixtures/fail18.json +1 -0
  93. data/vendor/json_pure/tests/fixtures/fail19.json +1 -0
  94. data/vendor/json_pure/tests/fixtures/fail2.json +1 -0
  95. data/vendor/json_pure/tests/fixtures/fail20.json +1 -0
  96. data/vendor/json_pure/tests/fixtures/fail21.json +1 -0
  97. data/vendor/json_pure/tests/fixtures/fail22.json +1 -0
  98. data/vendor/json_pure/tests/fixtures/fail23.json +1 -0
  99. data/vendor/json_pure/tests/fixtures/fail24.json +1 -0
  100. data/vendor/json_pure/tests/fixtures/fail25.json +1 -0
  101. data/vendor/json_pure/tests/fixtures/fail27.json +2 -0
  102. data/vendor/json_pure/tests/fixtures/fail28.json +2 -0
  103. data/vendor/json_pure/tests/fixtures/fail3.json +1 -0
  104. data/vendor/json_pure/tests/fixtures/fail4.json +1 -0
  105. data/vendor/json_pure/tests/fixtures/fail5.json +1 -0
  106. data/vendor/json_pure/tests/fixtures/fail6.json +1 -0
  107. data/vendor/json_pure/tests/fixtures/fail7.json +1 -0
  108. data/vendor/json_pure/tests/fixtures/fail8.json +1 -0
  109. data/vendor/json_pure/tests/fixtures/fail9.json +1 -0
  110. data/vendor/json_pure/tests/fixtures/pass1.json +56 -0
  111. data/vendor/json_pure/tests/fixtures/pass15.json +1 -0
  112. data/vendor/json_pure/tests/fixtures/pass16.json +1 -0
  113. data/vendor/json_pure/tests/fixtures/pass17.json +1 -0
  114. data/vendor/json_pure/tests/fixtures/pass2.json +1 -0
  115. data/vendor/json_pure/tests/fixtures/pass26.json +1 -0
  116. data/vendor/json_pure/tests/fixtures/pass3.json +6 -0
  117. data/vendor/json_pure/tests/test_json.rb +312 -0
  118. data/vendor/json_pure/tests/test_json_addition.rb +164 -0
  119. data/vendor/json_pure/tests/test_json_fixtures.rb +34 -0
  120. data/vendor/json_pure/tests/test_json_generate.rb +106 -0
  121. data/vendor/json_pure/tests/test_json_rails.rb +146 -0
  122. data/vendor/json_pure/tests/test_json_unicode.rb +62 -0
  123. data/vendor/json_pure/tools/fuzz.rb +139 -0
  124. data/vendor/json_pure/tools/server.rb +61 -0
  125. metadata +120 -6
  126. data/lib/scout/command/clone.rb +0 -21
  127. data/setup.rb +0 -1360
  128. data/test/scout_test.rb +0 -91
data/lib/scout.rb CHANGED
@@ -1,9 +1,9 @@
1
1
  #!/usr/bin/env ruby -wKU
2
2
 
3
+ module Scout
4
+ VERSION = "4.0.0".freeze
5
+ end
6
+
3
7
  require "scout/command"
4
8
  require "scout/plugin"
5
9
  require "scout/server"
6
-
7
- module Scout
8
- VERSION = "2.0.7".freeze
9
- end
data/lib/scout/command.rb CHANGED
@@ -199,6 +199,15 @@ module Scout
199
199
  running = true
200
200
  begin
201
201
  Process.kill(0, pid)
202
+ if stat = File.stat(pid_file)
203
+ if mtime = stat.mtime
204
+ if Time.now - mtime > 25 * 60 # assume process is hung after 25m
205
+ log.info "Trying to KILL an old process..." if log
206
+ Process.kill("KILL", pid)
207
+ running = false
208
+ end
209
+ end
210
+ end
202
211
  rescue Errno::ESRCH
203
212
  running = false
204
213
  rescue
@@ -25,12 +25,14 @@ module Scout
25
25
  end
26
26
 
27
27
  Scout::Server.new(nil, nil, history, log) do |scout|
28
- pp scout.process_plugin( :interval => 0,
29
- :plugin_id => 1,
30
- :name => "Local Plugin",
31
- :code => plugin_code,
32
- :options => plugin_options,
33
- :path => plugin )
28
+ scout.prepare_checkin
29
+ scout.process_plugin( 'interval' => 0,
30
+ 'plugin_id' => 1,
31
+ 'name' => "Local Plugin",
32
+ 'code' => plugin_code,
33
+ 'options' => plugin_options,
34
+ 'path' => plugin )
35
+ scout.show_checkin(:pp)
34
36
  end
35
37
  end
36
38
  end
data/lib/scout/plugin.rb CHANGED
@@ -69,22 +69,33 @@ module Scout
69
69
  # add_error(:subject => "subject", :body => "body")
70
70
  #
71
71
  def data_for_server
72
- @data_for_server ||= { :reports => [ ],
73
- :alerts => [ ],
74
- :errors => [ ],
72
+ @data_for_server ||= { :reports => [ ],
73
+ :alerts => [ ],
74
+ :errors => [ ],
75
+ :summaries => [ ],
75
76
  :memory => { } }
76
77
  end
77
78
 
78
- %w[report alert error].each do |kind|
79
+ %w[report alert error summary].each do |kind|
79
80
  class_eval <<-END
80
- def #{kind}s
81
- data_for_server[:#{kind}s]
81
+ if "#{kind}" == "summary"
82
+ def summaries
83
+ data_for_server[:summaries]
84
+ end
85
+ else
86
+ def #{kind}s
87
+ data_for_server[:#{kind}s]
88
+ end
82
89
  end
83
90
 
84
91
  if "#{kind}" == "report"
85
92
  def report(new_entry)
86
93
  reports << new_entry
87
94
  end
95
+ elsif "#{kind}" == "summary"
96
+ def summary(new_entry)
97
+ summaries << new_entry
98
+ end
88
99
  else
89
100
  def #{kind}(*fields)
90
101
  #{kind}s << ( fields.first.is_a?(Hash) ?
data/lib/scout/server.rb CHANGED
@@ -4,6 +4,12 @@ require "net/https"
4
4
  require "uri"
5
5
  require "yaml"
6
6
  require "timeout"
7
+ require "stringio"
8
+ require "zlib"
9
+ require "socket"
10
+
11
+ $LOAD_PATH << File.join(File.dirname(__FILE__), *%w[.. .. vendor json_pure lib])
12
+ require "json"
7
13
 
8
14
  module Scout
9
15
  class Server
@@ -12,18 +18,17 @@ module Scout
12
18
  # A new class for API Timeout errors.
13
19
  class APITimeoutError < RuntimeError; end
14
20
 
15
- # The default URLS are used to communicate with the Scout Server.
16
- URLS = { :plan => "/clients/CLIENT_KEY/plugins.scout?version=CLIENT_VERSION",
17
- :report => "/clients/CLIENT_KEY/plugins/PLUGIN_ID/reports.scout?version=CLIENT_VERSION",
18
- :error => "/clients/CLIENT_KEY/plugins/PLUGIN_ID/errors.scout?version=CLIENT_VERSION",
19
- :alert => "/clients/CLIENT_KEY/plugins/PLUGIN_ID/alerts.scout?version=CLIENT_VERSION",
20
- :clone => "/clients/CLIENT_KEY/clone_from?version=CLIENT_VERSION" }
21
-
21
+ # Headers passed up with all API requests.
22
+ HTTP_HEADERS = { "CLIENT_VERSION" => Scout::VERSION,
23
+ "CLIENT_HOSTNAME" => Socket.gethostname,
24
+ "ACCEPT_ENCODING" => "gzip" }
25
+
22
26
  #
23
- # A plugin cannot take more than PLUGIN_TIMEOUT seconds to execute,
24
- # otherwise, a timeout error is generated.
27
+ # A plugin cannot take more than DEFAULT_PLUGIN_TIMEOUT seconds to execute,
28
+ # otherwise, a timeout error is generated. This can be overriden by
29
+ # individual plugins.
25
30
  #
26
- PLUGIN_TIMEOUT = 60
31
+ DEFAULT_PLUGIN_TIMEOUT = 60
27
32
  #
28
33
  # A fuzzy range of seconds in which it is okay to rerun a plugin.
29
34
  # We consider the interval close enough at this point.
@@ -45,6 +50,18 @@ module Scout
45
50
  end
46
51
  end
47
52
 
53
+ # Prepares a check-in data structure to hold Plugin generated data.
54
+ def prepare_checkin
55
+ @checkin = { :reports => Array.new,
56
+ :alerts => Array.new,
57
+ :errors => Array.new,
58
+ :summaries => Array.new }
59
+ end
60
+
61
+ def show_checkin(printer = :p)
62
+ send(printer, @checkin)
63
+ end
64
+
48
65
  #
49
66
  # Loads the history file from disk. If the file does not exist,
50
67
  # it creates one.
@@ -72,7 +89,9 @@ module Scout
72
89
  # Runs all plugins from a given plan. Calls process_plugin on each plugin.
73
90
  def run_plugins_by_plan
74
91
  plan do |plugin|
92
+ prepare_checkin
75
93
  process_plugin(plugin)
94
+ checkin
76
95
  end
77
96
  end
78
97
 
@@ -86,17 +105,23 @@ module Scout
86
105
  # set memory and last_run information in the history file.
87
106
  #
88
107
  def process_plugin(plugin)
89
- info "Processing the #{plugin[:name]} plugin:"
90
- last_run = @history["last_runs"][plugin[:name]]
91
- memory = @history["memory"][plugin[:name]]
92
- run_time = Time.now
93
- delta = last_run.nil? ? nil : run_time - (last_run + plugin[:interval])
108
+ info "Processing the #{plugin['name']} plugin:"
109
+ id_and_name = "#{plugin['id']}-#{plugin['name']}".sub(/\A-/, "")
110
+ last_run = @history["last_runs"][id_and_name] ||
111
+ @history["last_runs"][plugin['name']]
112
+ memory = @history["memory"][id_and_name] ||
113
+ @history["memory"][plugin['name']]
114
+ run_time = Time.now
115
+ delta = last_run.nil? ? nil : run_time -
116
+ (last_run + plugin['interval'] * 60)
94
117
  if last_run.nil? or delta.between?(-RUN_DELTA, 0) or delta >= 0
95
118
  debug "Plugin is past interval and needs to be run. " +
96
119
  "(last run: #{last_run || 'nil'})"
97
120
  debug "Compiling plugin..."
98
121
  begin
99
- eval(plugin[:code], TOPLEVEL_BINDING, plugin[:path] || plugin[:name])
122
+ eval( plugin['code'],
123
+ TOPLEVEL_BINDING,
124
+ plugin['path'] || plugin['name'] )
100
125
  info "Plugin compiled."
101
126
  rescue Exception
102
127
  raise if $!.is_a? SystemExit
@@ -105,12 +130,14 @@ module Scout
105
130
  end
106
131
  debug "Loading plugin..."
107
132
  if job = Plugin.last_defined.load( last_run, (memory || Hash.new),
108
- plugin[:options] || Hash.new )
133
+ plugin['options'] || Hash.new )
109
134
  info "Plugin loaded."
110
135
  debug "Running plugin..."
111
136
  begin
112
- data = {}
113
- Timeout.timeout(PLUGIN_TIMEOUT, PluginTimeoutError) do
137
+ data = {}
138
+ timeout = plugin['timeout'].to_i
139
+ timeout = DEFAULT_PLUGIN_TIMEOUT unless timeout > 0
140
+ Timeout.timeout(timeout, PluginTimeoutError) do
114
141
  data = job.run
115
142
  end
116
143
  rescue Timeout::Error
@@ -118,30 +145,27 @@ module Scout
118
145
  return
119
146
  rescue Exception
120
147
  raise if $!.is_a? SystemExit
121
- error "Plugin failed to run: #{$!.class}: #{$!}\n#{$!.backtrace.join("\n")}"
148
+ error "Plugin failed to run: #{$!.class}: #{$!.message}\n" +
149
+ "#{$!.backtrace.join("\n")}"
122
150
  end
123
151
  info "Plugin completed its run."
124
152
 
125
- # handle single report or array of reports
126
- send_report(data[:report], plugin[:plugin_id]) if data[:report]
127
- if data[:reports] and not data[:reports].empty?
128
- data[:reports].each { |r| send_report(r, plugin[:plugin_id]) }
129
- end
130
- # handle single alert or array of alerts
131
- send_alert(data[:alert], plugin[:plugin_id]) if data[:alert]
132
- if data[:alerts] and not data[:alerts].empty?
133
- data[:alerts].each { |a| send_alert(a, plugin[:plugin_id]) }
134
- end
135
- # handle single error or array of errors
136
- send_error(data[:error], plugin[:plugin_id]) if data[:error]
137
- if data[:errors] and not data[:errors].empty?
138
- data[:errors].each { |e| send_error(e, plugin[:plugin_id]) }
153
+ %w[report alert error summary].each do |type|
154
+ plural = "#{type}s".sub(/ys\z/, "ies").to_sym
155
+ (Array(data[type.to_sym]) + Array(data[plural])).each do |fields|
156
+ @checkin[plural] << build_report(plugin['id'], fields)
157
+ end
139
158
  end
140
159
 
141
- @history["last_runs"][plugin[:name]] = run_time
142
- @history["memory"][plugin[:name]] = data[:memory]
160
+ @history["last_runs"].delete(plugin['name'])
161
+ @history["memory"].delete(plugin['name'])
162
+ @history["last_runs"][id_and_name] = run_time
163
+ @history["memory"][id_and_name] = data[:memory]
143
164
  else
144
- scout_error({:subject => "Plugin would not load."}, plugin[:plugin_id])
165
+ @checkin[:errors] << build_report(
166
+ plugin_id['id'],
167
+ :subject => "Plugin would not load."
168
+ )
145
169
  end
146
170
  else
147
171
  debug "Plugin does not need to be run at this time. " +
@@ -160,7 +184,7 @@ module Scout
160
184
  error "Unable to remove plugin."
161
185
  end
162
186
  end
163
- info "Plugin #{plugin[:name]} processing complete."
187
+ info "Plugin #{plugin['name']} processing complete."
164
188
  end
165
189
 
166
190
  #
@@ -170,118 +194,80 @@ module Scout
170
194
  def plan
171
195
  url = urlify(:plan)
172
196
  info "Loading plan from #{url}..."
173
- get(url, "Could not retrieve plan from server.") do |res|
174
- begin
175
- plugin_execution_plan = Marshal.load(res.body)
176
- # pp plugin_execution_plan
177
- info "Plan loaded. (#{plugin_execution_plan.size} plugins: " +
178
- "#{plugin_execution_plan.map { |p| p[:name] }.join(', ')})"
179
- rescue TypeError
180
- fatal "Plan from server was malformed."
181
- exit
197
+ headers = Hash.new
198
+ if @history["last_modified_for_plugins"] and @history["old_plugins"]
199
+ headers["If-Modified-Since"] = @history["last_modified_for_plugins"]
200
+ end
201
+ get(url, "Could not retrieve plan from server.", headers) do |res|
202
+ if res.is_a? Net::HTTPNotModified
203
+ info "Plan not modified. Reusing saved plan."
204
+ plugin_execution_plan = Array(@history["old_plugins"])
205
+ else
206
+ begin
207
+ body = res.body
208
+ if res["Content-Encoding"] == "gzip" and body and not body.empty?
209
+ body = Zlib::GzipReader.new(StringIO.new(body)).read
210
+ end
211
+ plugin_execution_plan = Array(JSON.parse(body)["plugins"])
212
+ if res["Last-Modified"]
213
+ @history["last_modified_for_plugins"] = res["last-modified"]
214
+ @history["old_plugins"] = plugin_execution_plan
215
+ end
216
+ info "Plan loaded. (#{plugin_execution_plan.size} plugins: " +
217
+ "#{plugin_execution_plan.map { |p| p['name'] }.join(', ')})"
218
+ rescue Exception
219
+ fatal "Plan from server was malformed."
220
+ exit
221
+ end
182
222
  end
183
223
  plugin_execution_plan.each do |plugin|
184
224
  begin
185
225
  yield plugin if block_given?
186
226
  rescue RuntimeError
187
- scout_error( { :subject => "Exception: #{$!.message}.",
188
- :body => $!.backtrace },
189
- plugin[:plugin_id] )
227
+ @checkin[:errors] << build_report(
228
+ plugin_id['id'],
229
+ :subject => "Exception: #{$!.message}.",
230
+ :body => $!.backtrace
231
+ )
190
232
  end
191
233
  end
192
234
  end
193
235
  end
194
236
  alias_method :test, :plan
195
-
196
- # Sends report data to the Scout Server.
197
- def send_report(data, plugin_id)
198
- url = urlify(:report, :plugin_id => plugin_id)
199
- report_hash = {:data => data, :plugin_id => plugin_id}
200
-
201
- # add in any special fields
202
- if time = ( data.delete(:scout_time) || data.delete("scout_time") )
203
- report_hash[:time] = time
204
- end
205
-
206
- debug "Sending report to #{url} (#{data.inspect})..."
207
- post url,
208
- "Unable to send report to server.",
209
- :report => report_hash
210
- info "Report sent."
211
- end
212
-
213
- # Sends an alert to the Scout Server.
214
- def send_alert(data, plugin_id)
215
- url = urlify(:alert, :plugin_id => plugin_id)
216
- debug "Sending alert to #{url} (subject: #{data[:subject]})..."
217
- post url,
218
- "Unable to send alert to server.",
219
- :alert => data.merge(:plugin_id => plugin_id)
220
- info "Alert sent."
221
- end
222
-
223
- # Sends an error to the Scout Server.
224
- def send_error(data, plugin_id)
225
- url = urlify(:error, :plugin_id => plugin_id)
226
- debug "Sending error to #{url} (subject: #{data[:subject]})..."
227
- post url,
228
- "Unable to log error on server.",
229
- :error => data.merge(:plugin_id => plugin_id)
230
- info "Error sent."
231
- end
232
-
233
- def clone_client(new_name, success_output)
234
- url = urlify(:clone)
235
- debug "Sending clone request to #{url}..."
236
- post( url,
237
- "Unable to send clone request to server.",
238
- "client[name]" => new_name ) do |response|
239
- case server_reply = response.body
240
- when /\AError:/i
241
- fatal "Clone error."
242
- abort server_reply
243
- else
244
- info "Client cloned."
245
- puts success_output.gsub(/\bCLIENT_KEY\b/, server_reply.strip)
246
- end
247
- end
248
- end
249
237
 
250
238
  private
239
+
240
+ def build_report(plugin_id, fields)
241
+ { :plugin_id => plugin_id,
242
+ :created_at => Time.now.utc.strftime("%Y-%m-%d %H:%M:%S"),
243
+ :fields => fields }
244
+ end
251
245
 
252
246
  def urlify(url_name, options = Hash.new)
253
247
  return unless @server
254
248
  options.merge!(:client_version => Scout::VERSION)
255
249
  URI.join( @server,
256
- URLS[url_name].
250
+ "/clients/CLIENT_KEY/#{url_name}.scout".
257
251
  gsub(/\bCLIENT_KEY\b/, @client_key).
258
252
  gsub(/\b[A-Z_]+\b/) { |k| options[k.downcase.to_sym] || k } )
259
253
  end
260
-
261
- def paramify(params, prefix = nil)
262
- params.inject(Hash.new) do |all, (key, value)|
263
- parent = prefix ? "#{prefix}[#{key}]" : String(key)
264
- if value.is_a? Hash
265
- all.merge(paramify(value, parent))
266
- else
267
- all.merge(parent => String(value))
268
- end
269
- end
270
- end
271
254
 
272
- def post(url, error, params = {}, &response_handler)
255
+ def post(url, error, body, headers = Hash.new, &response_handler)
273
256
  return unless url
274
257
  request(url, response_handler, error) do |connection|
275
- post = Net::HTTP::Post.new(url.path + (url.query ? ('?' + url.query) : ''))
276
- post.set_form_data(paramify(params))
258
+ post = Net::HTTP::Post.new( url.path +
259
+ (url.query ? ('?' + url.query) : ''),
260
+ HTTP_HEADERS.merge(headers) )
261
+ post.body = body
277
262
  connection.request(post)
278
263
  end
279
264
  end
280
265
 
281
- def get(url, error, params = {}, &response_handler)
266
+ def get(url, error, headers = Hash.new, &response_handler)
282
267
  return unless url
283
268
  request(url, response_handler, error) do |connection|
284
- connection.get(url.path + (url.query ? ('?' + url.query) : ''))
269
+ connection.get( url.path + (url.query ? ('?' + url.query) : ''),
270
+ HTTP_HEADERS.merge(headers) )
285
271
  end
286
272
  end
287
273
 
@@ -291,12 +277,15 @@ module Scout
291
277
  http = Net::HTTP.new(url.host, url.port)
292
278
  if url.is_a? URI::HTTPS
293
279
  http.use_ssl = true
294
- http.verify_mode = OpenSSL::SSL::VERIFY_NONE
280
+ http.ca_file = File.join( File.dirname(__FILE__),
281
+ *%w[.. .. data cacert.pem] )
282
+ http.verify_mode = OpenSSL::SSL::VERIFY_PEER |
283
+ OpenSSL::SSL::VERIFY_FAIL_IF_NO_PEER_CERT
295
284
  end
296
285
  response = no_warnings { http.start(&connector) }
297
286
  end
298
287
  case response
299
- when Net::HTTPSuccess
288
+ when Net::HTTPSuccess, Net::HTTPNotModified
300
289
  response_handler[response] unless response_handler.nil?
301
290
  else
302
291
  fatal error
@@ -311,6 +300,21 @@ module Scout
311
300
  exit
312
301
  end
313
302
 
303
+ def checkin
304
+ io = StringIO.new
305
+ gzip = Zlib::GzipWriter.new(io)
306
+ gzip << @checkin.to_json
307
+ gzip.close
308
+ post( urlify(:checkin),
309
+ "Unable to check in with the server.",
310
+ io.string,
311
+ "Content-Type" => "application/json",
312
+ "CONTENT_ENCODING" => "gzip" )
313
+ rescue Exception
314
+ error "Unable to check in with the server."
315
+ end
316
+
317
+
314
318
  def no_warnings
315
319
  old_verbose = $VERBOSE
316
320
  $VERBOSE = false