diff --git a/Gemfile.lock b/Gemfile.lock index 2ce264d..7ebee7f 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,8 +1,9 @@ PATH remote: . specs: - riemann-dash (0.2.5) + riemann-dash (0.2.8) erubis (>= 2.7.0) + fog multi_json (= 1.3.6) riemann-client (>= 0.0.7) sass (>= 3.1.14) @@ -12,34 +13,55 @@ PATH GEM remote: https://rubygems.org/ specs: - beefcake (0.3.7) + beefcake (0.5.0) + builder (3.2.2) coderay (1.0.9) daemons (1.1.9) erubis (2.7.0) eventmachine (1.0.3) + excon (0.31.0) + fog (1.19.0) + builder + excon (~> 0.31.0) + formatador (~> 0.2.0) + mime-types + multi_json (~> 1.0) + net-scp (~> 1.1) + net-ssh (>= 2.1.3) + nokogiri (~> 1.5) + ruby-hmac + formatador (0.2.4) method_source (0.8.1) + mime-types (2.0) + mini_portile (0.5.2) mtrc (0.0.4) multi_json (1.3.6) + net-scp (1.1.2) + net-ssh (>= 2.6.5) + net-ssh (2.7.0) + nokogiri (1.6.1) + mini_portile (~> 0.5.0) pry (0.9.12) coderay (~> 1.0.5) method_source (~> 0.8) slop (~> 3.4) rack (1.5.2) - rack-protection (1.5.0) + rack-protection (1.5.2) rack riemann-client (0.2.2) beefcake (>= 0.3.5) mtrc (>= 0.0.4) trollop (>= 1.16.2) - sass (3.2.7) - sinatra (1.3.6) + ruby-hmac (0.4.0) + sass (3.3.2) + sinatra (1.4.4) rack (~> 1.4) - rack-protection (~> 1.3) - tilt (~> 1.3, >= 1.3.3) + rack-protection (~> 1.4) + tilt (~> 1.3, >= 1.3.4) slop (3.4.3) - thin (1.5.1) + thin (1.6.2) daemons (>= 1.0.9) - eventmachine (>= 0.12.6) + eventmachine (>= 1.0.0) rack (>= 1.0.0) tilt (1.4.1) trollop (2.0) diff --git a/lib/riemann/dash.rb b/lib/riemann/dash.rb index 640a497..080ea56 100644 --- a/lib/riemann/dash.rb +++ b/lib/riemann/dash.rb @@ -1,6 +1,8 @@ require 'rubygems' require 'sinatra/base' require 'riemann/dash/version' -require 'riemann/dash/config' require 'riemann/dash/browser_config' +require 'riemann/dash/browser_config/file' +require 'riemann/dash/browser_config/s3' +require 'riemann/dash/config' require 'riemann/dash/app' diff --git a/lib/riemann/dash/app.rb b/lib/riemann/dash/app.rb index f7f0b68..2e14eb5 100644 --- a/lib/riemann/dash/app.rb +++ b/lib/riemann/dash/app.rb @@ -26,6 +26,7 @@ module Riemann config.load_controllers config.setup_views config.setup_public_dir + config.setup_ws_backend end end end diff --git a/lib/riemann/dash/browser_config.rb b/lib/riemann/dash/browser_config.rb index f7039be..fa08c07 100644 --- a/lib/riemann/dash/browser_config.rb +++ b/lib/riemann/dash/browser_config.rb @@ -3,6 +3,14 @@ module Riemann::Dash::BrowserConfig require 'fileutils' require 'pp' + def self.backend + @backend + end + + def self.backend=(backend) + @backend = backend + end + # TODO: this is gonna take significant restructuring of the dashboard itself, # but we should move to http://arxiv.org/abs/1201.1784 or equivalent CRDTs. @@ -54,35 +62,11 @@ module Riemann::Dash::BrowserConfig 'workspaces' => merge_workspaces(a['workspaces'], b['workspaces']) end - - def self.read(config) - if File.exists? config.ws_config_file - File.open(config.ws_config_file, 'r') do |f| - f.flock File::LOCK_SH - f.read - end - else - MultiJson.encode({}) - end + def self.read + backend.read end - def self.update(config, update) - update = MultiJson.decode update - - # Read old config - old = MultiJson.decode read(config) - - new = merge_configs update, old - - # Save new config - FileUtils.mkdir_p File.dirname(config.ws_config_file) - begin - File.open(config.ws_config_file, File::RDWR|File::CREAT, 0644) do |f| - f.flock File::LOCK_EX - f.write(MultiJson.encode(new, :pretty => true)) - f.flush - f.truncate f.pos - end - end + def self.update(update) + backend.update(update) end end diff --git a/lib/riemann/dash/browser_config/file.rb b/lib/riemann/dash/browser_config/file.rb new file mode 100644 index 0000000..3b12871 --- /dev/null +++ b/lib/riemann/dash/browser_config/file.rb @@ -0,0 +1,39 @@ +class Riemann::Dash::BrowserConfig::File + require 'multi_json' + require 'fileutils' + + def initialize(path) + @path = path + end + + def read + if ::File.exists? @path + ::File.open(@path, 'r') do |f| + f.flock ::File::LOCK_SH + f.read + end + else + MultiJson.encode({}) + end + end + + def update(update) + update = MultiJson.decode update + + # Read old config + old = MultiJson.decode read + + new = Riemann::Dash::BrowserConfig.merge_configs update, old + + # Save new config + FileUtils.mkdir_p ::File.dirname(@path) + begin + ::File.open(@path, ::File::RDWR|::File::CREAT, 0644) do |f| + f.flock ::File::LOCK_EX + f.write(MultiJson.encode(new, :pretty => true)) + f.flush + f.truncate f.pos + end + end + end +end diff --git a/lib/riemann/dash/browser_config/s3.rb b/lib/riemann/dash/browser_config/s3.rb new file mode 100644 index 0000000..306e59e --- /dev/null +++ b/lib/riemann/dash/browser_config/s3.rb @@ -0,0 +1,31 @@ +class Riemann::Dash::BrowserConfig::S3 + require 'multi_json' + require 'fog' + + def initialize(bucket, path, config = {}) + @bucket = bucket + @path = path + @config = config + + @storage = Fog::Storage.new(:region => config[:region], + :provider => 'AWS') + end + + def read + begin + @storage.get_object(@bucket, @path).body + rescue Excon::Errors::NotFound + MultiJson.encode({}) + end + end + + def update(update) + update = MultiJson.decode update + + # Read old config + old = MultiJson.decode read + + new = Riemann::Dash::BrowserConfig.merge_configs update, old + @storage.put_object @bucket, @path, MultiJson.encode(new, :pretty => true) + end +end diff --git a/lib/riemann/dash/config.rb b/lib/riemann/dash/config.rb index eeae8a2..879a41b 100644 --- a/lib/riemann/dash/config.rb +++ b/lib/riemann/dash/config.rb @@ -1,4 +1,6 @@ class Riemann::Dash::Config + require 'uri' + attr_accessor :config_path attr_accessor :store @@ -62,6 +64,19 @@ class Riemann::Dash::Config Riemann::Dash::App.use Riemann::Dash::Static, :root => store[:public] end + def setup_ws_backend + uri = URI.parse(ws_config_file) + backend = case uri.scheme + when "s3" + Riemann::Dash::BrowserConfig::S3.new(uri.host, uri.path.sub(/^\//, ''), store[:s3_config]) + when nil, "file" + Riemann::Dash::BrowserConfig::File.new(uri.path) + else + raise Exception.new "Unknown backend for #{ws_config_file}" + end + Riemann::Dash::BrowserConfig.backend = backend + end + # Load controllers. def load_controllers_from(dir) sorted_controller_list(dir).each do |r| diff --git a/lib/riemann/dash/controller/index.rb b/lib/riemann/dash/controller/index.rb index 0e626d9..6a9ae25 100644 --- a/lib/riemann/dash/controller/index.rb +++ b/lib/riemann/dash/controller/index.rb @@ -5,16 +5,16 @@ class Riemann::Dash::App get '/config', :provides => 'json' do content_type "application/json" - Riemann::Dash::BrowserConfig.read config + Riemann::Dash::BrowserConfig.read end post '/config' do # Read update request.body.rewind - Riemann::Dash::BrowserConfig.update config, request.body.read + Riemann::Dash::BrowserConfig.update request.body.read # Return current config content_type "application/json" - Riemann::Dash::BrowserConfig.read config + Riemann::Dash::BrowserConfig.read end end diff --git a/riemann-dash.gemspec b/riemann-dash.gemspec index 992c239..686312d 100644 --- a/riemann-dash.gemspec +++ b/riemann-dash.gemspec @@ -21,6 +21,7 @@ Gem::Specification.new do |gem| gem.add_dependency 'sass', '>= 3.1.14' gem.add_dependency 'thin', '>= 1.3.1' gem.add_dependency 'multi_json', '1.3.6' + gem.add_dependency 'fog' gem.files = `git ls-files`.split($/) gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) } gem.test_files = gem.files.grep(%r{^(test|spec|features)/})