summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAzul <azul@riseup.net>2013-09-10 09:44:38 +0200
committerAzul <azul@riseup.net>2013-09-10 09:44:38 +0200
commit57140b80f00aab43918a3ec3276062823971dec7 (patch)
tree759de1356d0cee24e44a4229629ddaf2fc662ad0
parentc221405796270f46d8d4881183fd55fd4d977da9 (diff)
bringing over couch_changes from leap_ca including tests
-rw-r--r--.travis.yml2
-rw-r--r--lib/tapicero.rb19
-rw-r--r--lib/tapicero/config.rb69
-rw-r--r--lib/tapicero/couch_changes.rb19
-rw-r--r--lib/tapicero/couch_stream.rb25
-rw-r--r--lib/tapicero_daemon.rb25
-rw-r--r--test/config/config.yaml5
-rw-r--r--test/test_helper.rb10
-rw-r--r--test/unit/couch_changes_test.rb32
-rw-r--r--test/unit/couch_stream_test.rb35
10 files changed, 241 insertions, 0 deletions
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