diff --git a/lib/backstop/config.rb b/lib/backstop/config.rb index f0c9d2c..09233ef 100644 --- a/lib/backstop/config.rb +++ b/lib/backstop/config.rb @@ -8,5 +8,6 @@ def self.deploy; env!("DEPLOY"); end def self.port; env!("PORT").to_i; end def self.carbon_urls; env!("CARBON_URLS").split(","); end def self.prefixes; env!("PREFIXES").split(","); end + def self.test?; ENV.key?('TEST'); end end end diff --git a/lib/backstop/web.rb b/lib/backstop/web.rb index cc2fece..317234d 100644 --- a/lib/backstop/web.rb +++ b/lib/backstop/web.rb @@ -7,28 +7,15 @@ module Backstop class Application < Sinatra::Base - configure do enable :logging require 'newrelic_rpm' - @@sockets = [] + @@publisher = nil end helpers do - def sockets - if !@@sockets.empty? - return @@sockets - else - @@sockets = [] - Config.carbon_urls.each do |c| - if (c =~ /^carbon:\/\//) - c.gsub!(/carbon:\/\//, "") - host, port = c.split(":") - s = TCPSocket.new host, port - @@sockets.push s - end - end - end + def publisher + @@publisher ||= Backstop::Publisher.new(Config.carbon_urls) end end @@ -47,9 +34,8 @@ def sockets results.each do |r| r["source"] = "collectd" halt 400, "missing fields" unless (r[:cloud] && r[:slot] && r[:id] && r[:metric] && r[:value] && r[:measure_time]) - s = sockets.sample r[:cloud].gsub!(/\./, "-") - s.puts "mitt.#{r[:cloud]}.#{r[:slot]}.#{r[:id]}.#{r[:metric]} #{r[:value]} #{r[:measure_time]}" if s + publisher.publish("mitt.#{r[:cloud]}.#{r[:slot]}.#{r[:id]}.#{r[:metric]}", r[:value], r[:measure_time]) end end "ok" @@ -85,14 +71,12 @@ def sockets data.each do |item| item["source"] = params[:name] halt 400, "missing fields" unless (item['metric'] && item['value'] && item['measure_time']) - s = sockets.sample - s.puts "#{item['source']}.#{item['metric']} #{item['value']} #{item['measure_time']}" + publisher.publish("#{item['source']}.#{item['metric']}", item['value'], item['measure_time']) end else data["source"] = params[:name] halt 400, "missing fields" unless (data['metric'] && data['value'] && data['measure_time']) - s = sockets.sample - s.puts "#{data['source']}.#{data['metric']} #{data['value']} #{data['measure_time']}" + publisher.publish("#{data['source']}.#{data['metric']}", data['value'], data['measure_time']) end "ok" else diff --git a/spec/backstop/bad_collectd_data.json b/spec/backstop/bad_collectd_data.json new file mode 100644 index 0000000..f48f026 --- /dev/null +++ b/spec/backstop/bad_collectd_data.json @@ -0,0 +1,13 @@ +[ + { + "values": [1901474177], + "dstypes": ["counter"], + "dsnames": ["value"], + "interval": 10, + "host": "leeloo.octo.it", + "plugin": "cpu", + "plugin_instance": "0", + "type": "cpu", + "type_instance": "idle" + } +] diff --git a/spec/backstop/good_collectd_data.json b/spec/backstop/good_collectd_data.json new file mode 100644 index 0000000..fd21a75 --- /dev/null +++ b/spec/backstop/good_collectd_data.json @@ -0,0 +1,14 @@ +[ + { + "values": [1901474177], + "dstypes": ["counter"], + "dsnames": ["value"], + "time": 1280959128, + "interval": 10, + "host": "leeloo.octo.it", + "plugin": "cpu", + "plugin_instance": "0", + "type": "cpu", + "type_instance": "idle" + } +] diff --git a/spec/backstop/web_spec.rb b/spec/backstop/web_spec.rb index 5ccbb66..fc17b69 100644 --- a/spec/backstop/web_spec.rb +++ b/spec/backstop/web_spec.rb @@ -3,8 +3,6 @@ require 'backstop/web' require 'rack/test' -set :environment, :test - describe Backstop::Application do include Rack::Test::Methods @@ -12,8 +10,67 @@ def app Backstop::Application end - it 'responds to /health' do - get '/health' - last_response.should be_ok + before(:each) do + app.class_variable_set :@@publisher, nil + end + + context 'GET /health' do + it 'should handle GET /health' do + get '/health' + last_response.should be_ok + end + end + + context 'POST /publish/:name' do + it 'should require JSON' do + post '/publish/foo', 'foo' + last_response.should_not be_ok + last_response.status.should eq(400) + end + + it 'should handle a single metric' do + p = double('publisher') + Backstop::Publisher.should_receive(:new) { p } + p.should_receive(:publish).with('test.bar', 12345, 1) + post '/publish/test', { :metric => 'bar', :value => 12345, :measure_time => 1 }.to_json + last_response.should be_ok + end + + it 'should handle an array of metrics' do + p = double('publisher') + Backstop::Publisher.should_receive(:new) { p } + p.should_receive(:publish).with('test.bar', 12345, 1) + p.should_receive(:publish).with('test.bar', 12344, 2) + post '/publish/test', [{ :metric => 'bar', :value => 12345, :measure_time => 1 }, { :metric => 'bar', :value => 12344, :measure_time => 2} ].to_json + last_response.should be_ok + end + end + + context 'POST /collectd' do + let(:collectd_data) { File.open(File.dirname(__FILE__) + '/good_collectd_data.json').read } + let(:bad_collectd_data) { File.open(File.dirname(__FILE__) + '/bad_collectd_data.json').read } + + it 'should require JSON' do + post '/collectd', 'foo' + last_response.should_not be_ok + last_response.status.should eq(400) + end + + it 'should handle a collectd metric' do + p = double('publisher') + Backstop::Publisher.should_receive(:new) { p } + p.should_receive(:publish).with('mitt.leeloo.octo.it.cpu.0.idle', 1901474177, 1280959128) + post '/collectd', collectd_data + last_response.body.should eq('ok') + last_response.status.should eq(200) + end + + it 'should complain if missing fields' do + post '/collectd', bad_collectd_data + last_response.status.should eq(400) + last_response.body.should eq('missing fields') + end end end + + diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 80e0e27..7c2c59b 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -1,19 +1,11 @@ -# This file was generated by the `rspec --init` command. Conventionally, all -# specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`. -# Require this file using `require "spec_helper"` to ensure that it is only -# loaded once. -# -# See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration require 'backstop' +ENV['CARBON_URLS'] = 'carbon://1.1.1.1:5000' +ENV['PREFIXES'] = 'test' + RSpec.configure do |config| config.treat_symbols_as_metadata_keys_with_true_values = true config.run_all_when_everything_filtered = true config.filter_run :focus - - # Run specs in random order to surface order dependencies. If you find an - # order dependency and want to debug it, you can fix the order by providing - # the seed, which is printed after each run. - # --seed 1234 config.order = 'random' end