vayacondios-server 0.2.11 → 0.3.0

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.
Files changed (142) hide show
  1. data/.gitignore +3 -1
  2. data/.travis.yml +2 -0
  3. data/Gemfile +15 -9
  4. data/LICENSE.md +2 -6
  5. data/Procfile +1 -1
  6. data/README.md +656 -111
  7. data/Rakefile +89 -6
  8. data/bin/vcd +10 -0
  9. data/bin/vcd-server +8 -0
  10. data/config/database.yml +6 -0
  11. data/config/spec.example.yml +18 -0
  12. data/config/vayacondios.example.yml +15 -0
  13. data/config/vcd-server.rb +37 -0
  14. data/examples/configuration.rb +56 -0
  15. data/examples/event_stream.rb +19 -0
  16. data/examples/simple.rb +61 -0
  17. data/features/event.feature +319 -0
  18. data/features/events.feature +208 -0
  19. data/features/stash.feature +840 -0
  20. data/features/stashes.feature +492 -0
  21. data/features/step_definitions/stash_steps.rb +113 -0
  22. data/features/stream.feature +30 -0
  23. data/features/support/em.rb +14 -0
  24. data/features/support/env.rb +13 -0
  25. data/lib/vayacondios/configuration.rb +63 -0
  26. data/lib/vayacondios/server/api.rb +126 -0
  27. data/lib/vayacondios/server/api_options.rb +56 -0
  28. data/lib/vayacondios/server/configuration.rb +23 -0
  29. data/lib/vayacondios/server/driver.rb +71 -0
  30. data/lib/vayacondios/server/drivers/mongo.rb +126 -0
  31. data/lib/vayacondios/server/handlers/document_handler.rb +81 -0
  32. data/lib/vayacondios/server/handlers/event_handler.rb +31 -26
  33. data/lib/vayacondios/server/handlers/events_handler.rb +31 -0
  34. data/lib/vayacondios/server/handlers/stash_handler.rb +69 -0
  35. data/lib/vayacondios/server/handlers/stashes_handler.rb +49 -0
  36. data/lib/vayacondios/server/handlers/stream_handler.rb +39 -0
  37. data/lib/vayacondios/server/models/document.rb +87 -0
  38. data/lib/vayacondios/server/models/event.rb +198 -0
  39. data/lib/vayacondios/server/models/stash.rb +100 -0
  40. data/lib/vayacondios/server.rb +35 -0
  41. data/lib/vayacondios-server.rb +19 -13
  42. data/lib/vayacondios.rb +22 -0
  43. data/pom.xml +124 -4
  44. data/spec/configuration_spec.rb +41 -0
  45. data/spec/server/api_options_spec.rb +32 -0
  46. data/spec/server/api_spec.rb +279 -0
  47. data/spec/server/configuration_spec.rb +27 -0
  48. data/spec/server/drivers/mongo_spec.rb +107 -0
  49. data/spec/server/handlers/event_handler_spec.rb +62 -0
  50. data/spec/server/handlers/events_handler_spec.rb +51 -0
  51. data/spec/server/handlers/stash_handler_spec.rb +68 -0
  52. data/spec/server/handlers/stashes_handler_spec.rb +50 -0
  53. data/spec/server/handlers/stream_handler_spec.rb +5 -0
  54. data/spec/server/models/document_spec.rb +9 -0
  55. data/spec/server/models/event_spec.rb +185 -0
  56. data/spec/server/models/stash_spec.rb +95 -0
  57. data/spec/spec_helper.rb +23 -3
  58. data/spec/support/database_helper.rb +42 -0
  59. data/spec/support/log_helper.rb +19 -0
  60. data/spec/support/shared_context_for_events.rb +22 -0
  61. data/spec/support/shared_context_for_stashes.rb +24 -0
  62. data/spec/support/shared_examples_for_handlers.rb +32 -0
  63. data/src/main/java/com/infochimps/vayacondios/BaseClient.java +342 -0
  64. data/src/main/java/com/infochimps/vayacondios/HTTPClient.java +426 -0
  65. data/src/main/java/com/infochimps/vayacondios/VayacondiosClient.java +487 -65
  66. data/src/main/java/com/infochimps/vayacondios/test/IntegrationTest.java +3 -0
  67. data/src/test/java/com/infochimps/vayacondios/BaseClientTest.java +50 -0
  68. data/src/test/java/com/infochimps/vayacondios/HTTPClientIT.java +267 -0
  69. data/vayacondios-server.gemspec +9 -9
  70. metadata +127 -122
  71. checksums.yaml +0 -15
  72. data/.rspec +0 -2
  73. data/.yardopts +0 -10
  74. data/Guardfile +0 -41
  75. data/app/http_shim.rb +0 -71
  76. data/bin/vcd.sh +0 -27
  77. data/config/http_shim.rb +0 -43
  78. data/config/vayacondios.example.yaml +0 -7
  79. data/config/vayacondios.yaml +0 -7
  80. data/examples/java/ItemSetTest.java +0 -76
  81. data/lib/tasks/publish.rake +0 -23
  82. data/lib/tasks/spec.rake +0 -11
  83. data/lib/tasks/yard.rake +0 -2
  84. data/lib/vayacondios/client/config.rb +0 -7
  85. data/lib/vayacondios/client/configliere.rb +0 -38
  86. data/lib/vayacondios/client/cube_client.rb +0 -39
  87. data/lib/vayacondios/client/http_client.rb +0 -49
  88. data/lib/vayacondios/client/itemset.rb +0 -130
  89. data/lib/vayacondios/client/legacy_switch.rb +0 -43
  90. data/lib/vayacondios/client/notifier.rb +0 -123
  91. data/lib/vayacondios/client/zabbix_client.rb +0 -148
  92. data/lib/vayacondios/legacy_switch.rb +0 -43
  93. data/lib/vayacondios/server/errors/bad_request.rb +0 -6
  94. data/lib/vayacondios/server/errors/not_found.rb +0 -6
  95. data/lib/vayacondios/server/handlers/config_handler.rb +0 -32
  96. data/lib/vayacondios/server/handlers/itemset_handler.rb +0 -60
  97. data/lib/vayacondios/server/legacy_switch.rb +0 -43
  98. data/lib/vayacondios/server/model/config_document.rb +0 -89
  99. data/lib/vayacondios/server/model/document.rb +0 -25
  100. data/lib/vayacondios/server/model/event_document.rb +0 -94
  101. data/lib/vayacondios/server/model/itemset_document.rb +0 -126
  102. data/lib/vayacondios/server/rack/extract_methods.rb +0 -35
  103. data/lib/vayacondios/server/rack/jsonize.rb +0 -43
  104. data/lib/vayacondios/server/rack/params.rb +0 -50
  105. data/lib/vayacondios/server/rack/path.rb +0 -23
  106. data/lib/vayacondios/server/rack/path_validation.rb +0 -22
  107. data/lib/vayacondios/version.rb +0 -3
  108. data/lib/vayacondios-client.rb +0 -22
  109. data/scripts/hadoop_monitor/configurable.rb +0 -66
  110. data/scripts/hadoop_monitor/hadoop_attempt_scraper.rb +0 -45
  111. data/scripts/hadoop_monitor/hadoop_client.rb +0 -273
  112. data/scripts/hadoop_monitor/hadoop_monitor.rb +0 -101
  113. data/scripts/hadoop_monitor/hadoopable.rb +0 -65
  114. data/scripts/hadoop_monitor/machine_monitor.rb +0 -115
  115. data/scripts/s3_cataloger/buckets +0 -33
  116. data/scripts/s3_cataloger/foreach_bucket +0 -88
  117. data/scripts/s3_cataloger/parse_ls.py +0 -391
  118. data/spec/client/itemset_legacy_spec.rb +0 -55
  119. data/spec/client/itemset_spec.rb +0 -60
  120. data/spec/client/notifier_spec.rb +0 -120
  121. data/spec/server/config_spec.rb +0 -113
  122. data/spec/server/event_spec.rb +0 -103
  123. data/spec/server/itemset_legacy_spec.rb +0 -320
  124. data/spec/server/itemset_spec.rb +0 -317
  125. data/spec/server/rack/extract_methods_spec.rb +0 -60
  126. data/spec/server/rack/path_spec.rb +0 -36
  127. data/spec/server/rack/path_validation_spec.rb +0 -22
  128. data/spec/server/server_spec.rb +0 -20
  129. data/spec/support/mongo_cleaner.rb +0 -32
  130. data/src/main/java/ItemSetTest.java +0 -76
  131. data/src/main/java/com/infochimps/util/CurrentClass.java +0 -26
  132. data/src/main/java/com/infochimps/util/DebugUtil.java +0 -38
  133. data/src/main/java/com/infochimps/util/HttpHelper.java +0 -181
  134. data/src/main/java/com/infochimps/vayacondios/ItemSets.java +0 -373
  135. data/src/main/java/com/infochimps/vayacondios/LinkToVCD.java +0 -18
  136. data/src/main/java/com/infochimps/vayacondios/MemoryVCDShim.java +0 -84
  137. data/src/main/java/com/infochimps/vayacondios/Organization.java +0 -62
  138. data/src/main/java/com/infochimps/vayacondios/PathBuilder.java +0 -13
  139. data/src/main/java/com/infochimps/vayacondios/StandardVCDLink.java +0 -218
  140. data/src/main/java/com/infochimps/vayacondios/VCDIntegrationTest.java +0 -108
  141. data/src/test/java/com/infochimps/vayacondios/TestVayacondiosInMemory.java +0 -78
  142. data/vayacondios-client.gemspec +0 -25
@@ -1,76 +0,0 @@
1
- import com.infochimps.vayacondios.Organization;
2
- import com.infochimps.vayacondios.VayacondiosClient;
3
- import com.infochimps.vayacondios.ItemSets;
4
- import static com.infochimps.vayacondios.ItemSets.Item;
5
- import static com.infochimps.vayacondios.ItemSets.ItemSet;
6
-
7
- import java.io.*;
8
- import java.util.*;
9
-
10
- public class ItemSetTest {
11
- private static final int VCD_PORT = 8000;
12
-
13
- public static void main(String argv[]) throws IOException {
14
- // Instantiate a new Vayacondios client.
15
- VayacondiosClient client = new VayacondiosClient("localhost", VCD_PORT);
16
-
17
- // Organizations can allow for testing and multiple environments
18
- // (staging, development).
19
- Organization org = client.organization("test");
20
-
21
- // At the moment, only the itemsets protocol is supported via a
22
- // Java API.
23
- ItemSets isets = org.itemsets();
24
-
25
- List<Item> foobar = Arrays.asList(new Item("foo"), new Item("bar"));
26
-
27
- // All of the following are equivalent ways to clobber the itemset
28
- // at topic my_topic and id my_id, replacing it with the items
29
- // "foo" and "bar." The first and second exist to avoid
30
- // instantiating new objects repeatedly when a code path must
31
- // access many different topics and ids.
32
- isets .create("my_topic", "my_id", foobar);
33
- isets.topic("my_topic") .create( "my_id", foobar);
34
- isets.topic("my_topic").itemSet("my_id").create( foobar);
35
-
36
- List<Item> fetched;
37
-
38
- // Similarly, these are all equivalent ways to fetch items.
39
- fetched = isets .fetch("my_topic", "my_id");
40
- fetched = isets.topic("my_topic") .fetch( "my_id");
41
- fetched = isets.topic("my_topic").itemSet("my_id").fetch( );
42
-
43
- ItemSet iset = isets.topic("my_topic").itemSet("my_id");
44
-
45
- // foo and bar will be printed, along with their types: STRING
46
- System.out.println("fetched items: " + fetched);
47
-
48
- List<Item> bazqux = Arrays.asList(new Item("baz"), new Item("qux"));
49
-
50
- // Updating an itemset with a list of items ensures the presence
51
- // in the itemset of all of the items in the specified list.
52
- isets .update("my_topic", "my_id", bazqux);
53
- isets.topic("my_topic") .update( "my_id", bazqux);
54
- isets.topic("my_topic").itemSet("my_id").update( bazqux);
55
-
56
- // foo, bar, baz, and qux will all be printed.
57
- System.out.println("after update: " + iset.fetch());
58
-
59
- List<Item> barbaz = Arrays.asList(new Item("bar"), new Item("baz"));
60
-
61
- // Updating an itemset with a list of items ensures the presence
62
- // in the itemset of all of the items in the specified list.
63
- isets .remove("my_topic", "my_id", barbaz);
64
- isets.topic("my_topic") .remove( "my_id", barbaz);
65
- isets.topic("my_topic").itemSet("my_id").remove( barbaz);
66
-
67
- // foo and qux will now be printed
68
- System.out.println("after removing: " + iset.fetch());
69
-
70
- // Create an empty itemset to effectively delete it.
71
- iset.create(Collections.EMPTY_LIST);
72
-
73
- // foo and qux will now be printed
74
- System.out.println("after deletion: " + iset.fetch());
75
- }
76
- }
@@ -1,23 +0,0 @@
1
- $:.push File.expand_path('..', __FILE__)
2
- require 'vayacondios/version'
3
-
4
- Dir['*.gemspec'].each do |gemspec|
5
- gem_name = gemspec.gsub(/\.gemspec/, '')
6
-
7
- desc "Build #{gem_name} gem into the pkg directory"
8
- task "build_#{gem_name}" do
9
- FileUtils.rm_rf('pkg')
10
- system "gem build #{gemspec}"
11
- FileUtils.mkdir_p('pkg')
12
- FileUtils.mv(Dir['*.gem'], 'pkg')
13
- end
14
-
15
- desc "Tags version, pushes to remote, and pushes #{gem_name} gem"
16
- task "release_#{gem_name}" => "build_#{gem_name}" do
17
- sh 'git', 'tag', '-m', "releasing #{gem_name}", "#{gem_name}-v#{Vayacondios::VERSION}"
18
- branch = `git branch | awk -F '/* ' '{print $2}'`.strip
19
- sh "git push origin #{branch}"
20
- sh "git push origin #{gem_name}-v#{Vayacondios::VERSION}"
21
- sh "ls pkg/#{gem_name}*.gem | xargs -n 1 gem push"
22
- end
23
- end
data/lib/tasks/spec.rake DELETED
@@ -1,11 +0,0 @@
1
- # -*- ruby -*-
2
-
3
- require 'rspec/core/rake_task'
4
-
5
- RSpec::Core::RakeTask.new
6
-
7
- namespace :spec do
8
- # RSpec::Core::RakeTask.new :coverage do
9
- # ENV['COVERAGE'] = "true"
10
- # end
11
- end
data/lib/tasks/yard.rake DELETED
@@ -1,2 +0,0 @@
1
- require 'yard'
2
- YARD::Rake::YardocTask.new
@@ -1,7 +0,0 @@
1
- def ENV.root_path(*args)
2
- File.expand_path(File.join(File.dirname(__FILE__), '../../../', *args))
3
- end
4
-
5
- require 'configliere'
6
-
7
- Settings.read(ENV.root_path('config/vayacondios.yaml'))
@@ -1,38 +0,0 @@
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
@@ -1,39 +0,0 @@
1
- class Vayacondios
2
- class CubeClient
3
- include Gorillib::Model
4
-
5
- field :host, String, :default => 'localhost'
6
- field :port, Integer, :default => 6000
7
-
8
- class Error < StandardError; end
9
-
10
- def uri
11
- return @uri if @uri
12
-
13
- uri_str = "http://#{host}:#{port}/1.0"
14
- @uri ||= URI(uri_str)
15
- end
16
-
17
- def event(topic, document = {})
18
- request(:post, File.join(uri.path, 'event'), MultiJson.dump(document))
19
- end
20
-
21
- private
22
-
23
- def request(method, path, document=nil)
24
- http = Net::HTTP.new(uri.host, uri.port)
25
-
26
- params = [method.to_sym, path]
27
- params += [document, {'Content-Type' => 'application/json'}] unless document.nil?
28
-
29
- response = http.send *params
30
-
31
- if Net::HTTPSuccess === response
32
- MultiJson.load(response.body) rescue response.body
33
- else
34
- raise Error.new("Error (#{response.code}) while #{method.to_s == 'get' ? 'fetching' : 'inserting'} document: " + response.body)
35
- end
36
- end
37
- end
38
- end
39
-
@@ -1,49 +0,0 @@
1
- class Vayacondios
2
- class HttpClient
3
- include Gorillib::Model
4
-
5
- field :host, String, :default => 'localhost'
6
- field :port, String, :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
-
@@ -1,130 +0,0 @@
1
- require 'gorillib/logger/log'
2
- require 'net/http'
3
- require 'multi_json'
4
- require_relative 'config'
5
- require_relative 'legacy_switch'
6
-
7
- class Vayacondios
8
- class Client
9
- class ItemSet
10
- def initialize host, port, organization=nil, topic=nil, id=nil
11
- @host = host
12
- @port = port
13
- @organization = organization
14
- @topic = topic
15
- @id = id
16
- end
17
-
18
- def fetch organization=nil, topic=nil, id=nil
19
- resp = execute_request(_req(:fetch, nil, organization, topic, id)) and
20
- Vayacondios.legacy_switch.extract_response(resp)
21
- end
22
-
23
- def update ary, organization=nil, topic=nil, id=nil
24
- execute_request(_req(:update, ary, organization, topic, id))
25
- end
26
-
27
- def create ary, organization=nil, topic=nil, id=nil
28
- execute_request(_req(:create, ary, organization, topic, id))
29
- end
30
-
31
- def remove ary, organization=nil, topic=nil, id=nil
32
- execute_request(_req(:remove, ary, organization, topic, id))
33
- end
34
-
35
- private
36
-
37
- def execute_request req
38
- begin
39
- resp = Net::HTTP.start(@host, @port) do |http|
40
- http.request(req)
41
- end.body
42
- result = MultiJson.decode(resp) unless resp.nil? or resp.empty?
43
- (result.respond_to?(:has_key?) and result.has_key? "error") ? nil : result
44
- rescue StandardError => ex
45
- Log.warn("problem contacting vayacondios: #{ex.message}")
46
- Log.debug(ex.backtrace.join("\n"))
47
- nil
48
- end
49
- end
50
-
51
- def path organization, topic, id
52
- if ((the_organization = (organization || @organization)).nil? ||
53
- (the_topic = (topic || @topic )).nil? ||
54
- (the_id = (id || @id )).nil?)
55
- raise ArgumentError.new("must provide organization, topic, and id!")
56
- end
57
-
58
- ['/v1', the_organization, 'itemset', the_topic, the_id].join("/")
59
- end
60
-
61
- # This is the only private method that is tested.
62
- def _req type, ary=nil, organization=nil, topic=nil, id=nil
63
-
64
- the_path = path(organization, topic, id)
65
- headers = {"content-type" => "application/json"}
66
- headers.merge!("x-method" => "PATCH") if type == :update
67
-
68
- case type
69
- when :fetch then Net::HTTP::Get
70
- when :create then Net::HTTP::Put
71
- when :update then Net::HTTP::Put
72
- when :remove then Net::HTTP::Delete
73
- else raise ArgumentError.new("invalid type: #{type}")
74
- end.new(the_path, headers).tap do |req|
75
- unless type == :fetch
76
- req.body =
77
- MultiJson.encode(Vayacondios.legacy_switch.wrap_contents(ary))
78
- end
79
- end
80
- end
81
- end
82
-
83
- # Subclasses should implement the remove_items(arr) and
84
- # add_items(arr) methods, both of which will be called with arrays
85
- # when the items in an itemset change. The run method polls the
86
- # provided itemset at a specified interval and calls these methods
87
- # appropriately.
88
- class ItemSetListener
89
- POLL_WAIT_SEC=2
90
-
91
- def initialize itemset, poll_wait_sec = POLL_WAIT_SEC
92
- @itemset = itemset
93
- @items = []
94
- @poll_wait_sec = poll_wait_sec
95
- end
96
-
97
- def run
98
- setup
99
- loop do
100
- new_items = @itemset.fetch || []
101
-
102
- Log.debug "currently configured: #{@items.inspect}"
103
- Log.debug "new items: #{new_items.inspect}"
104
-
105
- add_items(new_items - @items)
106
- remove_items(@items - new_items)
107
-
108
- @items = new_items
109
-
110
- sleep @poll_wait_sec
111
- end
112
- teardown
113
- end
114
-
115
- protected
116
-
117
- def add_items
118
- raise NoMethodError.new("class #{self.class.name} must override add_items")
119
- end
120
-
121
- def remove_items
122
- raise NoMethodError.new("class #{self.class.name} must override remove_items")
123
- end
124
-
125
- def setup() end
126
- def teardown() end
127
-
128
- end
129
- end
130
- end
@@ -1,43 +0,0 @@
1
- require 'gorillib/logger/log'
2
-
3
- class Vayacondios
4
- # Are we operating on JSON Hashes (Vayacondios) or on JSON arrays
5
- # (Vayacondios Legacy)? These classes determine which to use.
6
-
7
- class StandardContentsHandler
8
- def wrap_contents(contents) {contents: contents} end
9
- def extract_contents(document) document['contents'] end
10
- def extract_response(document) document['contents'] end
11
- def proper_request(document) true end
12
- end
13
-
14
- class LegacyContentsHandler
15
- def wrap_contents(contents) contents end
16
- def extract_contents(document) document end
17
- def extract_response(document) document end
18
- def proper_request(document) true end
19
- end
20
-
21
- @@legacy_switch = nil
22
-
23
- def self.legacy_switch
24
- if @@legacy_switch.nil?
25
- legacy_mode_on = Settings[:vayacondios][:legacy]
26
- @@legacy_switch = get_legacy_switch(legacy_mode_on)
27
- Log.info("using #{legacy_mode_on ? 'legacy' : 'standard'} mode")
28
- end
29
- @@legacy_switch
30
- end
31
-
32
- def self.force_legacy_mode on
33
- Log.info("forcing #{on ? 'legacy' : 'standard'} mode")
34
- @@legacy_switch = get_legacy_switch on
35
- end
36
-
37
- private
38
-
39
- def self.get_legacy_switch on
40
- (on ? LegacyContentsHandler : StandardContentsHandler).new
41
- end
42
- end
43
-
@@ -1,123 +0,0 @@
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 NullNotifier < Notifier
24
- def initialize(*args) ; end
25
-
26
- def notify topic, cargo={}
27
- end
28
- end
29
-
30
- class LogNotifier < Notifier
31
-
32
- def initialize(options = {})
33
- @client = options[:log] || Log
34
- end
35
-
36
- def notify(topic, cargo = {})
37
- prepped = prepare(cargo)
38
- level = prepped.delete(:level) || :info
39
- message = "Notification: #{topic.inspect}."
40
- message += " Reason: #{prepped.delete(:reason)}." if prepped[:reason]
41
- message += " Cargo: #{prepped.inspect}"
42
- client.send(level, message)
43
- end
44
- end
45
-
46
- class HttpNotifier < Notifier
47
-
48
- def initialize(options = {})
49
- @client = Vayacondios::HttpClient.receive(options)
50
- end
51
-
52
- def notify(topic, cargo = {})
53
- prepped = prepare(cargo)
54
- client.insert(prepped, :event, topic)
55
- nil
56
- end
57
- end
58
-
59
- class CubeNotifier < Notifier
60
- def initialize(options={})
61
- @client = Vayacondios::CubeClient.receive(options)
62
- end
63
- def notify topic, cargo={}
64
- prepped = prepare(cargo)
65
- client.event(topic, prepped)
66
- nil
67
- end
68
- end
69
-
70
- class ZabbixNotifier < Notifier
71
- def initialize options={}
72
- @client = Vayacondios::ZabbixClient.receive(options)
73
- end
74
- def notify(topic, cargo={})
75
- prepped = prepare(cargo)
76
- client.insert(topic, prepped)
77
- end
78
- end
79
-
80
- class NotifierFactory
81
- def self.receive(attrs = {})
82
- type = attrs[:type]
83
- case type
84
- when 'http' then HttpNotifier.new(attrs)
85
- when 'cube' then CubeNotifier.new(attrs)
86
- when 'zabbix' then ZabbixNotifier.new(attrs)
87
- when 'log' then LogNotifier.new(attrs)
88
- when 'none','null' then NullNotifier.new(attrs)
89
- else
90
- raise ArgumentError, "<#{type}> is not a valid build option"
91
- end
92
- end
93
- end
94
-
95
- def self.default_notifier(log = nil) NotifierFactory.receive(type: 'log', log: log) ; end
96
-
97
- module Notifications
98
-
99
- def notify(topic, cargo = {})
100
- notifier.notify(topic, cargo)
101
- end
102
-
103
- def self.included klass
104
- if klass.ancestors.include? Gorillib::Model
105
- klass.class_eval do
106
- field :notifier, Vayacondios::NotifierFactory, default: Vayacondios.default_notifier, :doc => "Notifier used to notify out of band data"
107
-
108
- def receive_notifier params
109
- params.merge!(log: try(:log)) if params[:type] == 'log'
110
- @notifier = Vayacondios::NotifierFactory.receive(params)
111
- end
112
- end
113
- else
114
- klass.class_attribute :notifier
115
- klass.notifier = Vayacondios.default_notifier try(:log)
116
- end
117
- end
118
-
119
- end
120
-
121
- extend Notifications
122
- self.notifier = default_notifier
123
- end
@@ -1,148 +0,0 @@
1
- require 'socket'
2
-
3
- class Vayacondios
4
-
5
- # Used for sending events to a Zabbix server.
6
- #
7
- # An 'event' from Vayacondios' perspective is an arbitrary Hash.
8
- #
9
- # An 'event' from Zabbix's perspective is a tuple of values:
10
- #
11
- # * time
12
- # * host
13
- # * key
14
- # * value
15
- #
16
- # This client will accept a Vayacondios event and internally
17
- # translate it into a set of Zabbix events.
18
- #
19
- # @example A CPU monitoring notification
20
- #
21
- # notify "foo-server.example.com", cpu: {
22
- # util: {
23
- # user: 0.20,
24
- # idle: 0.70,
25
- # sys: 0.10
26
- # },
27
- # load: 1.3
28
- # }
29
- #
30
- # would get turned into the following events when written to Zabbix:
31
- #
32
- # @example The CPU monitoring notification translated to Zabbix events
33
- #
34
- # [
35
- # { host: "foo-server.example.com", key: "cpu.util.user", value: 0.20 }
36
- # { host: "foo-server.example.com", key: "cpu.util.idle", value: 0.70 },
37
- # { host: "foo-server.example.com", key: "cpu.util.sys", value: 0.10 },
38
- # { host: "foo-server.example.com", key: "cpu.load", value: 1.3 }
39
- # ]
40
- #
41
- # Zabbix will interpret the time as the time it receives each event.
42
- #
43
- # The following links provide details on the protocol used by Zabbix
44
- # to receive events:
45
- #
46
- # * https://www.zabbix.com/forum/showthread.php?t=20047&highlight=sender
47
- # * https://gist.github.com/1170577
48
- # * http://spin.atomicobject.com/2012/10/30/collecting-metrics-from-ruby-processes-using-zabbix-trappers/?utm_source=rubyflow&utm_medium=ao&utm_campaign=collecting-metrics-zabix
49
- class ZabbixClient
50
- include Gorillib::Builder
51
-
52
- attr_accessor :socket
53
-
54
- field :host, String, :default => 'localhost', :doc => "Host for the Zabbix server"
55
- field :port, Integer, :default => 10051, :doc => "Port for the Zabbix server"
56
-
57
- # Insert events to a Zabbix server.
58
- #
59
- # The `topic` will be used as the name of the Zabbix host to
60
- # associate event data to.
61
- #
62
- # As per the documentation for the [Zabbix sender
63
- # protocol](https://www.zabbix.com/wiki/doc/tech/proto/zabbixsenderprotocol),
64
- # a new TCP connection will be created for each event.
65
- #
66
- # @param [String] topic
67
- # @param [Hash] cargo
68
- # Array<Hash>] text
69
- def insert topic, cargo={}
70
- self.socket = TCPSocket.new(host, port)
71
- send_request(topic, cargo)
72
- handle_response
73
- self.socket.close
74
- end
75
-
76
- private
77
-
78
- # :nodoc
79
- def send_request topic, cargo
80
- socket.write(payload(topic, cargo))
81
- end
82
-
83
- # :nodoc
84
- def handle_response
85
- header = socket.recv(5)
86
- if header == "ZBXD\1"
87
- data_header = socket.recv(8)
88
- length = data_header[0,4].unpack("i")[0]
89
- response = MultiJson.load(socket.recv(length))
90
- puts response["info"]
91
- else
92
- puts "Invalid response: #{header}"
93
- end
94
- end
95
-
96
- # :nodoc
97
- def payload topic, cargo={}
98
- body = body_for(topic, cargo)
99
- header_for(body) + body
100
- end
101
-
102
- # :nodoc
103
- def body_for topic, cargo={}
104
- MultiJson.dump({request: "sender data", data: zabbix_events_from(topic, cargo) })
105
- end
106
-
107
- # :nodoc
108
- def header_for body
109
- length = body.bytesize
110
- "ZBXD\1".encode("ascii") + [length].pack("i") + "\x00\x00\x00\x00"
111
- end
112
-
113
- # :nodoc
114
- def zabbix_events_from topic, cargo, scope=''
115
- events = []
116
- case cargo
117
- when Hash
118
- cargo.each_pair do |key, value|
119
- events += zabbix_events_from(topic, value, new_scope(scope, key))
120
- end
121
- when Array
122
- cargo.each_with_index do |item, index|
123
- events += zabbix_events_from(topic, item, new_scope(scope, index))
124
- end
125
- else
126
- events << event_body(topic, scope, cargo)
127
- end
128
- events
129
- end
130
-
131
- # :nodoc
132
- def new_scope(current_scope, new_scope)
133
- [current_scope, new_scope].map(&:to_s).reject(&:empty?).join('.')
134
- end
135
-
136
- # :nodoc
137
- def event_body topic, scope, cargo
138
- value = case cargo
139
- when Hash then cargo[:value]
140
- when Array then cargo.first
141
- else cargo
142
- end
143
- { host: topic, key: scope, value: value }
144
- end
145
-
146
- end
147
- end
148
-