vayacondios-client 0.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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: