vayacondios-client 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,23 @@
1
+ require 'configliere'
2
+ require 'multi_json'
3
+ require 'net/http'
4
+
5
+ require 'gorillib/builder'
6
+ require 'gorillib/configurable'
7
+ require 'gorillib/enumerable/sum'
8
+ require 'gorillib/exception/raisers'
9
+ require 'gorillib/hash/deep_compact'
10
+ require 'gorillib/hash/deep_merge'
11
+ require 'gorillib/hash/keys'
12
+ require 'gorillib/logger/log'
13
+ require 'gorillib/metaprogramming/class_attribute'
14
+ require 'gorillib/object/blank'
15
+ require 'gorillib/string/constantize'
16
+ require 'gorillib/string/inflections'
17
+
18
+ require 'vayacondios/client/http_client'
19
+ require 'vayacondios/client/notifier'
20
+ require 'vayacondios/client/configliere'
21
+
22
+
23
+
@@ -0,0 +1,38 @@
1
+ class Vayacondios
2
+ module Configliere
3
+
4
+ def load_from_vayacondios(organization, id, options = {})
5
+ options.symbolize_keys!.deep_merge!(organization: organization)
6
+
7
+ client = ::Vayacondios::HttpClient.receive(options.deep_compact!)
8
+ id = [id, options[:env]].compact.join('.')
9
+
10
+ begin
11
+ new_data = client.fetch(:config, id)
12
+ rescue ::Vayacondios::HttpClient::Error
13
+ warn "Unable to load vayacondios config '#{id}' for #{organization} at: #{client.host}:#{client.port}"
14
+ new_data = {}
15
+ end
16
+ deep_merge! new_data
17
+ self
18
+ end
19
+
20
+ def save_to_vayacondios(organization, id, options = {})
21
+ options.symbolize_keys!.deep_merge!(organization: organization)
22
+
23
+ client = ::Vayacondios::HttpClient.receive(options.deep_compact!)
24
+ id = [id, options[:env]].compact.join('.')
25
+
26
+ begin
27
+ client.insert(self.to_hash, :config, id)
28
+ rescue ::Vayacondios::HttpClient::Error
29
+ warn "Unable to save vayacondios config '#{id}' for #{organization} at: #{client.host}:#{client.port}"
30
+ end
31
+ self
32
+ end
33
+ end
34
+ end
35
+
36
+ ::Configliere::Param.class_eval do
37
+ include ::Vayacondios::Configliere
38
+ end
@@ -0,0 +1,49 @@
1
+ class Vayacondios
2
+ class HttpClient
3
+ include Gorillib::Builder
4
+
5
+ field :host, String, :default => 'localhost'
6
+ field :port, Integer, :default => 8000
7
+ field :organization, String, :default => 'infochimps'
8
+
9
+ class Error < StandardError; end
10
+
11
+ def uri
12
+ return @uri if @uri
13
+
14
+ uri_str = "http://#{host}:#{port}/v1"
15
+ uri_str += "/#{organization}" if organization
16
+ @uri ||= URI(uri_str)
17
+ end
18
+
19
+ def fetch(type, id)
20
+ request(:get, type, id)
21
+ end
22
+
23
+ def insert(document = {}, type = nil, id = nil)
24
+ id ||= document.delete(:_id) || document.delete('_id')
25
+ type ||= document.delete(:_type) || document.delete('_type')
26
+
27
+ request(:post, type, id, MultiJson.dump(document))
28
+ end
29
+
30
+ private
31
+
32
+ def request(method, type, id = nil, document = nil)
33
+ path = File.join(uri.path, type.to_s, *id.to_s.split(/\W/))
34
+ http = Net::HTTP.new(uri.host, uri.port)
35
+
36
+ params = [method.to_sym, path]
37
+ params += [document, {'Content-Type' => 'application/json'}] unless document.nil?
38
+
39
+ response = http.send *params
40
+
41
+ if Net::HTTPSuccess === response
42
+ MultiJson.load(response.body) rescue response.body
43
+ else
44
+ raise Error.new("Error (#{response.code}) while #{method.to_s == 'get' ? 'fetching' : 'inserting'} document: " + response.body)
45
+ end
46
+ end
47
+ end
48
+ end
49
+
@@ -0,0 +1,84 @@
1
+ class Vayacondios
2
+
3
+ class_attribute :notifier
4
+
5
+ class Notifier < Vayacondios
6
+ attr_accessor :client
7
+
8
+ def prepare(obj)
9
+ case
10
+ when obj.respond_to?(:to_inspectable) then obj.to_inspectable
11
+ when obj.respond_to?(:to_wire) then obj.to_wire
12
+ when obj.respond_to?(:to_hash) then obj.to_hash
13
+ else
14
+ raise ArgumentError.new("Cannot notify '#{obj.inspect}' -- require a hash-like object.")
15
+ end
16
+ end
17
+
18
+ def notify(topic, cargo = {})
19
+ NoMethodError.unimplemented_method(self)
20
+ end
21
+ end
22
+
23
+ class LogNotifier < Notifier
24
+
25
+ def initialize(options = {})
26
+ @client = options[:log] || Log
27
+ end
28
+
29
+ def notify(topic, cargo = {})
30
+ prepped = prepare(cargo)
31
+ level = prepped.delete(:level) || :info
32
+ message = "Notification: #{topic.inspect}."
33
+ message += " Reason: #{prepped.delete(:reason)}." if prepped[:reason]
34
+ message += " Cargo: #{prepped.inspect}"
35
+ client.send(level, message)
36
+ end
37
+ end
38
+
39
+ class HttpNotifier < Notifier
40
+
41
+ def initialize(options = {})
42
+ @client = Vayacondios::HttpClient.receive(options)
43
+ end
44
+
45
+ def notify(topic, cargo = {})
46
+ prepped = prepare(cargo)
47
+ client.insert(prepped, :event, topic)
48
+ nil
49
+ end
50
+ end
51
+
52
+ class NotifierFactory
53
+ def self.receive(attrs = {})
54
+ type = attrs.delete(:type)
55
+ case type
56
+ when 'http' then HttpNotifier.new(attrs)
57
+ when 'log' then LogNotifier.new(attrs)
58
+ else
59
+ raise ArgumentError, "<#{type}> is not a valid build option"
60
+ end
61
+ end
62
+ end
63
+
64
+ def self.default_notifier() NotifierFactory.receive(type: 'http') ; end
65
+
66
+ module Notifications
67
+ extend Gorillib::Concern
68
+ include Gorillib::Configurable
69
+
70
+ def notify(topic, cargo = {})
71
+ notifier.notify(topic, cargo)
72
+ end
73
+
74
+ included do
75
+ class_eval do
76
+ config(:notifier, Vayacondios::NotifierFactory, default: Vayacondios.default_notifier)
77
+ end
78
+ end
79
+
80
+ end
81
+
82
+ extend Notifications
83
+ self.notifier = default_notifier
84
+ end
@@ -0,0 +1,123 @@
1
+ require 'spec_helper'
2
+ require 'gorillib/builder'
3
+ require 'configliere'
4
+
5
+ require_relative '../../configurable/lib/gorillib_configurable_model'
6
+ require 'vayacondios/notifier'
7
+
8
+ class FakeModel
9
+ include Vayacondios::Notifications
10
+ end
11
+
12
+ describe FakeModel do
13
+ context 'including', Vayacondios::Notifications do
14
+
15
+ it 'defines an instance method notify()' do
16
+ subject.should respond_to(:notify)
17
+ end
18
+
19
+ it 'adds a configurable attribute :notifier with default' do
20
+ subject.notifier.should be_instance_of(Vayacondios.default_notifier.class)
21
+ end
22
+
23
+ end
24
+ end
25
+
26
+ describe Vayacondios::Notifier do
27
+
28
+ shared_examples_for described_class do
29
+ it{ should respond_to(:notify) }
30
+ end
31
+
32
+ context '.prepare' do
33
+ context 'given a Hash-like object' do
34
+ let(:hashlike) { double :hashlike, :to_hash => {} }
35
+ it 'returns a Hash' do
36
+ subject.prepare(hashlike).should be_instance_of(Hash)
37
+ end
38
+ end
39
+
40
+ context 'given a bad argument' do
41
+ let(:bad_arg) { 'shazam' }
42
+ it 'raises an ArgumentError' do
43
+ expect{ subject.prepare(bad_arg) }.to raise_error(ArgumentError, /Cannot notify.*#{bad_arg}.*require a hash-like object/)
44
+ end
45
+ end
46
+ end
47
+
48
+ end
49
+
50
+ describe Vayacondios::HttpNotifier do
51
+ it_behaves_like Vayacondios::Notifier
52
+
53
+ its(:client){ should be_instance_of(Vayacondios::HttpClient) }
54
+
55
+ context '#notify' do
56
+ let(:test_client) { double :client }
57
+ let(:topic) { 'weeeeeeeeeee' }
58
+ let(:cargo) { Hash.new }
59
+
60
+ before do
61
+ subject.stub(:client).and_return(test_client)
62
+ subject.stub(:prepare).and_return(cargo)
63
+ end
64
+
65
+ it 'notifies its client correctly' do
66
+ test_client.should_receive(:insert).with(cargo, :event, topic)
67
+ subject.notify(topic, cargo)
68
+ end
69
+ end
70
+ end
71
+
72
+ describe Vayacondios::LogNotifier do
73
+ it_behaves_like Vayacondios::Notifier
74
+
75
+ its(:client){ should be_instance_of(Logger) }
76
+
77
+ context '#notify' do
78
+ let(:test_client) { double :client }
79
+ let(:topic) { 'weeeeeeeeeee' }
80
+ let(:cargo) { Hash.new }
81
+
82
+ before do
83
+ subject.stub(:client).and_return(test_client)
84
+ subject.stub(:prepare).and_return(cargo)
85
+ end
86
+
87
+ it 'notifies its client correctly' do
88
+ test_client.should_receive(:info).with(/Notification.*#{topic}/)
89
+ subject.notify(topic, cargo)
90
+ end
91
+ end
92
+
93
+ end
94
+
95
+ describe Vayacondios::NotifierFactory do
96
+ context '.receive' do
97
+ context 'given :http' do
98
+ it 'builds a HttpNotifier' do
99
+ described_class.receive(type: 'http').should be_instance_of(Vayacondios::HttpNotifier)
100
+ end
101
+ end
102
+
103
+ context 'given :log' do
104
+ it 'builds a LogNotifier' do
105
+ described_class.receive(type: 'log').should be_instance_of(Vayacondios::LogNotifier)
106
+ end
107
+ end
108
+
109
+ context 'given a bad argument' do
110
+ it 'raises an ArgumentError' do
111
+ expect{ described_class.receive(type: 'bad') }.to raise_error(ArgumentError, /not a valid build option/)
112
+ end
113
+ end
114
+ end
115
+ end
116
+
117
+ describe Vayacondios do
118
+
119
+ it 'has a class method notify()' do
120
+ described_class.should respond_to(:notify)
121
+ end
122
+
123
+ end
metadata ADDED
@@ -0,0 +1,94 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: vayacondios-client
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.3
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Philip (flip) Kromer
9
+ - Travis Dempsey
10
+ - Huston Hoburg
11
+ autorequire:
12
+ bindir: bin
13
+ cert_chain: []
14
+ date: 2012-08-16 00:00:00.000000000Z
15
+ dependencies:
16
+ - !ruby/object:Gem::Dependency
17
+ name: configliere
18
+ requirement: &2170425660 !ruby/object:Gem::Requirement
19
+ none: false
20
+ requirements:
21
+ - - ! '>='
22
+ - !ruby/object:Gem::Version
23
+ version: 0.4.16
24
+ type: :runtime
25
+ prerelease: false
26
+ version_requirements: *2170425660
27
+ - !ruby/object:Gem::Dependency
28
+ name: multi_json
29
+ requirement: &2170425160 !ruby/object:Gem::Requirement
30
+ none: false
31
+ requirements:
32
+ - - ~>
33
+ - !ruby/object:Gem::Version
34
+ version: '1.1'
35
+ type: :runtime
36
+ prerelease: false
37
+ version_requirements: *2170425160
38
+ - !ruby/object:Gem::Dependency
39
+ name: gorillib
40
+ requirement: &2170424700 !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - =
44
+ - !ruby/object:Gem::Version
45
+ version: 0.4.0pre
46
+ type: :runtime
47
+ prerelease: false
48
+ version_requirements: *2170424700
49
+ description: ! " \nSimple
50
+ enough to use in a shell script, performant enough to use everywhere. Why the hell
51
+ wouldn't you record that metric, ese?\n\n* Client code\n\n"
52
+ email:
53
+ executables: []
54
+ extensions: []
55
+ extra_rdoc_files: []
56
+ files:
57
+ - lib/vayacondios-client.rb
58
+ - lib/vayacondios/client/configliere.rb
59
+ - lib/vayacondios/client/http_client.rb
60
+ - lib/vayacondios/client/notifier.rb
61
+ - spec/client/notifier_spec.rb
62
+ homepage: https://github.com/infochimps-labs/vayacondios
63
+ licenses: []
64
+ post_install_message:
65
+ rdoc_options: []
66
+ require_paths:
67
+ - lib
68
+ required_ruby_version: !ruby/object:Gem::Requirement
69
+ none: false
70
+ requirements:
71
+ - - ! '>='
72
+ - !ruby/object:Gem::Version
73
+ version: '0'
74
+ segments:
75
+ - 0
76
+ hash: 546804456992730553
77
+ required_rubygems_version: !ruby/object:Gem::Requirement
78
+ none: false
79
+ requirements:
80
+ - - ! '>='
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ segments:
84
+ - 0
85
+ hash: 546804456992730553
86
+ requirements: []
87
+ rubyforge_project:
88
+ rubygems_version: 1.8.15
89
+ signing_key:
90
+ specification_version: 3
91
+ summary: Data goes in. The right thing happens
92
+ test_files:
93
+ - spec/client/notifier_spec.rb
94
+ has_rdoc: