From 57140b80f00aab43918a3ec3276062823971dec7 Mon Sep 17 00:00:00 2001 From: Azul Date: Tue, 10 Sep 2013 09:44:38 +0200 Subject: bringing over couch_changes from leap_ca including tests --- .travis.yml | 2 ++ lib/tapicero.rb | 19 ++++++++++++ lib/tapicero/config.rb | 69 +++++++++++++++++++++++++++++++++++++++++ lib/tapicero/couch_changes.rb | 19 ++++++++++++ lib/tapicero/couch_stream.rb | 25 +++++++++++++++ lib/tapicero_daemon.rb | 25 +++++++++++++++ test/config/config.yaml | 5 +++ test/test_helper.rb | 10 ++++++ test/unit/couch_changes_test.rb | 32 +++++++++++++++++++ test/unit/couch_stream_test.rb | 35 +++++++++++++++++++++ 10 files changed, 241 insertions(+) create mode 100644 .travis.yml create mode 100644 lib/tapicero.rb create mode 100644 lib/tapicero/config.rb create mode 100644 lib/tapicero/couch_changes.rb create mode 100644 lib/tapicero/couch_stream.rb create mode 100644 lib/tapicero_daemon.rb create mode 100644 test/config/config.yaml create mode 100644 test/test_helper.rb create mode 100644 test/unit/couch_changes_test.rb create mode 100644 test/unit/couch_stream_test.rb diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..984e24a --- /dev/null +++ b/.travis.yml @@ -0,0 +1,2 @@ +services: + - couchdb diff --git a/lib/tapicero.rb b/lib/tapicero.rb new file mode 100644 index 0000000..ee52db4 --- /dev/null +++ b/lib/tapicero.rb @@ -0,0 +1,19 @@ +unless defined? BASE_DIR + BASE_DIR = File.expand_path('../..', __FILE__) +end +unless defined? LEAP_CA_CONFIG + LEAP_CA_CONFIG = '/etc/leap/tapicero.yaml' +end + +# +# Load Config +# this must come first, because CouchRest needs the connection defined before the models are defined. +# +require 'tapicero/config' +Tapicero::Config.load(BASE_DIR, 'config/default.yaml', LEAP_CA_CONFIG, ARGV.grep(/\.ya?ml$/).first) + +# +# Load Tapicero +# +require 'tapicero/couch_stream' +require 'tapicero/couch_changes' diff --git a/lib/tapicero/config.rb b/lib/tapicero/config.rb new file mode 100644 index 0000000..cb22792 --- /dev/null +++ b/lib/tapicero/config.rb @@ -0,0 +1,69 @@ +require 'yaml' + +module Tapicero + module Config + extend self + + attr_accessor :users_db_name + attr_accessor :db_prefix + attr_accessor :couch_connection + + def self.load(base_dir, *configs) + configs.each do |file_path| + load_config find_file(base_dir, file_path) + end + end + + # TODO: enable username and password + def couch_host + couch_connection[:protocol] + '://' + + couch_connection[:host] + ':' + + couch_connection[:port] + '/' + end + + private + + def load_config(file_path) + return unless file_path + puts " * Loading configuration #{file_path}" + load_settings YAML.load(File.read(file_path)) + rescue NoMethodError => exc + STDERR.puts "ERROR in file #{file_path}" + exit(1) + end + + def load_settings(hash) + return unless hash + hash.each do |key, value| + apply_setting(key, value) + end + end + + def apply_setting(key, value) + if value.is_a? Hash + value = symbolize_keys(value) + end + self.send("#{key}=", value) + rescue NoMethodError => exc + STDERR.puts "'#{key}' is not a valid option" + raise exc + end + + def self.symbolize_keys(hsh) + newhsh = {} + hsh.keys.each do |key| + newhsh[key.to_sym] = hsh[key] + end + newhsh + end + + def self.find_file(base_dir, file_path) + return nil unless file_path + if defined? CWD + return File.expand_path(file_path, CWD) if File.exists?(File.expand_path(file_path, CWD)) + end + return File.expand_path(file_path, base_dir) if File.exists?(File.expand_path(file_path, base_dir)) + return nil + end + end +end diff --git a/lib/tapicero/couch_changes.rb b/lib/tapicero/couch_changes.rb new file mode 100644 index 0000000..2e668dc --- /dev/null +++ b/lib/tapicero/couch_changes.rb @@ -0,0 +1,19 @@ +module Tapicero + class CouchChanges + def initialize(stream) + @stream = stream + end + + def last_seq + @stream.get "_changes", :limit => 1, :descending => true do |hash| + return hash[:last_seq] + end + end + + def follow + @stream.get "_changes", :feed => :continuous, :since => last_seq do |hash| + yield(hash) + end + end + end +end diff --git a/lib/tapicero/couch_stream.rb b/lib/tapicero/couch_stream.rb new file mode 100644 index 0000000..96c752a --- /dev/null +++ b/lib/tapicero/couch_stream.rb @@ -0,0 +1,25 @@ +require 'yajl/http_stream' + +module Tapicero + class CouchStream + def initialize(database_url) + @database_url = database_url + end + + def get(path, options) + url = url_for(path, options) + # puts url + Yajl::HttpStream.get(url, :symbolize_keys => true) do |hash| + yield(hash) + end + end + + protected + + def url_for(path, options = {}) + url = [@database_url, path].join('/') + url += '?' if options.any? + url += options.map {|k,v| "#{k}=#{v}"}.join('&') + end + end +end diff --git a/lib/tapicero_daemon.rb b/lib/tapicero_daemon.rb new file mode 100644 index 0000000..a5347c7 --- /dev/null +++ b/lib/tapicero_daemon.rb @@ -0,0 +1,25 @@ +# +# This file should not be required directly. Use the wrapper in /bin +# instead or run this using daemons: +# +# Daemons.run('tapicero_daemon.rb') +# + +require 'tapicero' + +module Tapicero + puts " * Tracking #{Config.users_db_name}" + couch = CouchStream.new(Config.couch_host + Config.users_db_name) + changes = CouchChanges.new(couch) + + # fill the pool + # pool.fill + + # watch for deletions, fill the pool whenever it gets low + changes.follow do |hash| + if hash[:created] + puts " Created #{hash.inspect}" + # pool.fill + end + end +end diff --git a/test/config/config.yaml b/test/config/config.yaml new file mode 100644 index 0000000..ee10fe6 --- /dev/null +++ b/test/config/config.yaml @@ -0,0 +1,5 @@ +# +# testing configuration options +# + +db_prefix: "tapicero_test-" diff --git a/test/test_helper.rb b/test/test_helper.rb new file mode 100644 index 0000000..3857e2c --- /dev/null +++ b/test/test_helper.rb @@ -0,0 +1,10 @@ +require 'rubygems' +require 'minitest/autorun' + +BASE_DIR = File.expand_path('../..', __FILE__) +$:.unshift File.expand_path('lib', BASE_DIR) + +require 'mocha/setup' + +TAPICERO_CONFIG = "test/config/config.yaml" +require 'tapicero' diff --git a/test/unit/couch_changes_test.rb b/test/unit/couch_changes_test.rb new file mode 100644 index 0000000..043caf1 --- /dev/null +++ b/test/unit/couch_changes_test.rb @@ -0,0 +1,32 @@ +require File.expand_path('../../test_helper.rb', __FILE__) +require 'tapicero/couch_changes' + +class CouchChangesTest < MiniTest::Unit::TestCase + + LAST_SEQ = 12 + + def setup + @stream = mock() + @changes = Tapicero::CouchChanges.new(@stream) + end + + def test_last_seq + @stream.expects(:get). + with('_changes', {:limit => 1, :descending => true}). + yields(:last_seq => LAST_SEQ) + assert_equal LAST_SEQ, @changes.last_seq + end + + def test_follow + stub_entry = {:new => :result} + @stream.expects(:get). + with('_changes', {:limit => 1, :descending => true}). + yields(:last_seq => LAST_SEQ) + @stream.expects(:get). + with('_changes', {:feed => :continuous, :since => LAST_SEQ}). + yields(stub_entry) + @changes.follow do |hash| + assert_equal stub_entry, hash + end + end +end diff --git a/test/unit/couch_stream_test.rb b/test/unit/couch_stream_test.rb new file mode 100644 index 0000000..48b663a --- /dev/null +++ b/test/unit/couch_stream_test.rb @@ -0,0 +1,35 @@ +require File.expand_path('../../test_helper.rb', __FILE__) +require 'tapicero/couch_stream' + +# we'll mock this +module Yajl + class HttpStream + end +end + +class CouchStreamTest < MiniTest::Unit::TestCase + + def setup + @root = "http://server/database" + @stream = Tapicero::CouchStream.new(@root) + @url = @root + "/_changes?a=b&c=d" + @path = "_changes" + @options = {:a => :b, :c => :d} + end + + def test_get + Yajl::HttpStream.expects(:get). + with(@url, :symbolize_keys => true). + yields(stub_hash = stub) + @stream.get(@path, @options) do |hash| + assert_equal stub_hash, hash + end + end + + # internal + def test_url_creation + assert_equal "http://server/database/", @stream.send(:url_for, "") + assert_equal @url, @stream.send(:url_for, @path, @options) + end + +end -- cgit v1.2.3