pushyd 0.0.2

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.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 8f1475888d98b181ea4d70fbd0568a1ea73b900a
4
+ data.tar.gz: a4f3e851e8d8698084e480a2ea94c2fd1040d5dc
5
+ SHA512:
6
+ metadata.gz: 507f389e40d4d80de6f4db4ed61c526d644cc0c0bdce04b21565c3507289421f0bda9d650f6dd4cfb3b3f9e6ebe0d491a6410781bd18de1b34fd8d9160a30375
7
+ data.tar.gz: c999e4e4bb98169092434000ceaa5aaf6facb2be792123ae56170458b732de78d2351c30883fabdd4f7ef5eb4fd45b776b823986546cc0811ea961b9d5c1f0c3
data/.gitignore ADDED
@@ -0,0 +1,8 @@
1
+ pkg
2
+ .bundle
3
+ .DS_Store
4
+ *.log
5
+ tmp/
6
+ log/
7
+ DOC/
8
+ .ruby-version
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source "http://rubygems.org"
2
+
3
+ gemspec
data/Gemfile.lock ADDED
@@ -0,0 +1,86 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ pushyd (0.0.2)
5
+ bunny
6
+ chamber
7
+ daemons
8
+ json
9
+ rest_client
10
+ terminal-table
11
+
12
+ GEM
13
+ remote: http://rubygems.org/
14
+ specs:
15
+ addressable (2.4.0)
16
+ amq-protocol (2.0.1)
17
+ ast (2.2.0)
18
+ astrolabe (1.3.1)
19
+ parser (~> 2.2)
20
+ bunny (2.2.2)
21
+ amq-protocol (>= 2.0.1)
22
+ chamber (2.9.0)
23
+ hashie (~> 3.3)
24
+ thor (~> 0.19.1)
25
+ daemons (1.2.3)
26
+ diff-lcs (1.2.5)
27
+ domain_name (0.5.20160310)
28
+ unf (>= 0.0.5, < 1.0.0)
29
+ hashie (3.4.4)
30
+ http (0.9.9)
31
+ addressable (~> 2.3)
32
+ http-cookie (~> 1.0)
33
+ http-form_data (~> 1.0.1)
34
+ http_parser.rb (~> 0.6.0)
35
+ http-cookie (1.0.2)
36
+ domain_name (~> 0.5)
37
+ http-form_data (1.0.1)
38
+ http_parser.rb (0.6.0)
39
+ json (1.8.3)
40
+ netrc (0.7.9)
41
+ parser (2.3.1.2)
42
+ ast (~> 2.2)
43
+ powerpack (0.1.1)
44
+ rainbow (2.1.0)
45
+ rake (11.1.2)
46
+ rest_client (1.8.3)
47
+ netrc (~> 0.7.7)
48
+ rspec (3.4.0)
49
+ rspec-core (~> 3.4.0)
50
+ rspec-expectations (~> 3.4.0)
51
+ rspec-mocks (~> 3.4.0)
52
+ rspec-core (3.4.4)
53
+ rspec-support (~> 3.4.0)
54
+ rspec-expectations (3.4.0)
55
+ diff-lcs (>= 1.2.0, < 2.0)
56
+ rspec-support (~> 3.4.0)
57
+ rspec-mocks (3.4.1)
58
+ diff-lcs (>= 1.2.0, < 2.0)
59
+ rspec-support (~> 3.4.0)
60
+ rspec-support (3.4.1)
61
+ rubocop (0.32.1)
62
+ astrolabe (~> 1.3)
63
+ parser (>= 2.2.2.5, < 3.0)
64
+ powerpack (~> 0.1)
65
+ rainbow (>= 1.99.1, < 3.0)
66
+ ruby-progressbar (~> 1.4)
67
+ ruby-progressbar (1.8.1)
68
+ terminal-table (1.5.2)
69
+ thor (0.19.1)
70
+ unf (0.1.4)
71
+ unf_ext
72
+ unf_ext (0.0.7.2)
73
+
74
+ PLATFORMS
75
+ ruby
76
+
77
+ DEPENDENCIES
78
+ bundler (~> 1.6)
79
+ http (~> 0.8)
80
+ pushyd!
81
+ rake
82
+ rspec
83
+ rubocop (~> 0.32.0)
84
+
85
+ BUNDLED WITH
86
+ 1.11.2
data/README.md ADDED
@@ -0,0 +1 @@
1
+ # pushyd
data/Rakefile ADDED
@@ -0,0 +1,16 @@
1
+ # encoding: utf-8
2
+ require "bundler/gem_tasks"
3
+ require "rubygems"
4
+
5
+ require "rspec/core/rake_task"
6
+ RSpec::Core::RakeTask.new(:spec)
7
+
8
+ # Run specs by default
9
+ desc "Run all tests"
10
+
11
+ require "rubocop/rake_task"
12
+ RuboCop::RakeTask.new(:rubocop) do |task|
13
+ task.fail_on_error = false
14
+ end
15
+
16
+ task default: [:spec, :rubocop]
data/bin/pushyd.rb ADDED
@@ -0,0 +1,69 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ # Try to load external libs, helpers and constants
4
+ begin
5
+ require "rubygems"
6
+ require "optparse"
7
+ require 'daemons'
8
+ require 'logger'
9
+ require_relative "../lib/pushyd/config"
10
+ rescue LoadError
11
+ raise "EXITING: some basic libs were not found"
12
+ end
13
+
14
+ # Guess app root
15
+ APP_ROOT = File.expand_path(File.dirname(__FILE__) + "/../")
16
+
17
+ # Parse options and check compliance
18
+ cmd_config = nil
19
+ cmd_env = "production"
20
+ cmd_dump = false
21
+ begin
22
+ OptionParser.new do |opts|
23
+ opts.banner = "Usage: #{File.basename $PROGRAM_NAME} [options] start|stop"
24
+ opts.on("-c", "--config CONFIGFILE") { |config| cmd_config = File.expand_path(config)}
25
+ opts.on("-e", "--environment ENV") { |env| cmd_env = env }
26
+ opts.on("-d", "--dump") { cmd_dump = true }
27
+ opts.on("", "--dev") { cmd_env = "development" }
28
+ end.order!(ARGV)
29
+ rescue OptionParser::InvalidOption => e
30
+ abort "EXITING: option parser: #{e.message}"
31
+ end
32
+
33
+
34
+ # Build Chamber-based configuration from Gemspec with initial context
35
+ Config.prepare root: APP_ROOT, gemspec: "pushyd", env: cmd_env, config: cmd_config
36
+
37
+ # Display final configuration
38
+ puts "--- #{Config.name} #{Config.version}"
39
+ puts "Environment \t #{Config.env}"
40
+ puts "Config files \t #{Config.files}"
41
+ puts
42
+ puts "Log file \t #{Config[:log]}"
43
+ puts Config.dump if cmd_dump
44
+
45
+
46
+ # Run daemon
47
+ run_options = {
48
+ ontop: false,
49
+ # :dir_mode => :normal,
50
+ # :dir => File.join(root, 'amine.log'),
51
+ # :log_output => true,
52
+ :backtrace => true,
53
+ :multiple => false
54
+ }
55
+ Daemons.run_proc('pushy-daemon', run_options) do
56
+ # Load code
57
+ puts "--- loading code and logger"
58
+ require_relative "../lib/pushyd"
59
+
60
+ # Prepare logger
61
+ if Config[:log]
62
+ logger = Logger.new(Config[:log])
63
+ logger.info('Daemon starting')
64
+ end
65
+
66
+ # Start daemon
67
+ puts "--- starting"
68
+ PushyDaemon::Daemon.run(logger)
69
+ end
data/defaults.yml ADDED
@@ -0,0 +1,25 @@
1
+ # common defaults
2
+ flag: 0
3
+ bus:
4
+ host: localhost
5
+ port: 5672
6
+ user: guest
7
+ pass: guest
8
+ log: "pushyd.log"
9
+ shout:
10
+ topic: pushyd
11
+ # keys:
12
+ # - tic
13
+ # - tac
14
+ # - toe
15
+ # - created
16
+ # - updated
17
+ # - deleted
18
+ # - crunched
19
+ # rules:
20
+ # proxy_tests:
21
+ # title: All proxy tests messages
22
+ # topic: proxy
23
+ # routes: "proxy.#"
24
+ # subscribe: false
25
+ # #relay: http://requestb.in/1clzv7v1
@@ -0,0 +1,43 @@
1
+ require "chamber"
2
+
3
+ class Config
4
+ extend Chamber
5
+
6
+ class << self
7
+ attr_reader :name
8
+ attr_reader :spec
9
+ attr_reader :files
10
+ attr_reader :version
11
+ attr_reader :env
12
+ end
13
+
14
+ def self.prepare args = {}
15
+ # Context parameters
16
+ raise "config: missing root" unless (@root = args[:root])
17
+ raise "config: missing env" unless (@env = args[:env])
18
+
19
+ # Gemspec parameter
20
+ gemspec_path = "#{args[:root]}/#{args[:gemspec]}.gemspec"
21
+ raise "config: missing gemspec" unless args[:gemspec]
22
+ raise "config: missing gemspec file at #{gemspec_path}" unless File.exist?(gemspec_path)
23
+
24
+ # Load Gemspec
25
+ @spec = Gem::Specification::load gemspec_path
26
+ @name = @spec.name
27
+ @version = @spec.version
28
+ raise "config: missing name" unless @name
29
+
30
+ # Init Chamber (defaults, etc, cmdline)
31
+ @files = ["#{args[:root]}/defaults.yml"]
32
+ @files << File.expand_path("/etc/#{@name}.yml")
33
+ @files << args[:config].to_s if args[:config]
34
+
35
+ # Load configuration files
36
+ load files: @files, namespaces: { environment: @env }
37
+ end
38
+
39
+ def self.dump
40
+ self.to_hash.to_yaml
41
+ end
42
+
43
+ end
@@ -0,0 +1,21 @@
1
+ module PushyDaemon
2
+ class Daemon
3
+
4
+ def self.run(logger)
5
+ # Create a new proxy
6
+ p = Proxy.new(logger)
7
+
8
+ # Prepare subscriptions
9
+ p.prepare
10
+
11
+ # Make it listen
12
+
13
+ # Dump config table
14
+ puts p.table.to_s
15
+
16
+ # Start infinite loop
17
+ p.main
18
+ end
19
+
20
+ end
21
+ end
@@ -0,0 +1,268 @@
1
+ require 'rest_client'
2
+ require 'bunny'
3
+ require 'yaml'
4
+ require 'json'
5
+ require 'terminal-table'
6
+
7
+ # Constants
8
+ PROXY_MESSAGE_MAX = 1
9
+ PROXY_USE_ACK = false
10
+ PROXY_SCOPE = "dev"
11
+ # PROXY_IDENT = "proxy"
12
+ # QUEUE_HOST = `hostname`.to_s.chomp
13
+ # SEPARATOR = "="*160
14
+ # ACK_PERCENT = 50
15
+
16
+
17
+ module PushyDaemon
18
+ class Proxy
19
+
20
+ attr_accessor :table
21
+
22
+ def initialize(logger)
23
+ @exchanges = {}
24
+ @logger = logger
25
+
26
+ # Init ASCII table
27
+ @table = Terminal::Table.new
28
+ @table.title = "Propagation rules"
29
+ @table.headings = ["queue binding", "topic", "route", "relay", "title"]
30
+ @table.align_column(5, :right)
31
+ end
32
+
33
+ def prepare
34
+ # Start connexion to RabbitMQ and create channel
35
+ conn = connect Config.bus
36
+ @channel = conn.create_channel
37
+ info "prepare: connected on a channel"
38
+
39
+ # Check rules
40
+ unless (Config.rules.is_a? Enumerable) && !Config.rules.empty?
41
+ abort "prepare: empty [rules] section"
42
+ end
43
+ info "prepare: found [#{Config.rules.size}] rules"
44
+
45
+ # Subsribe for each and every rule/route
46
+ Config.rules.each do |name, rule|
47
+ rule[:name] = name
48
+ channel_subscribe rule
49
+ #abort "prepare: OK"
50
+ end
51
+
52
+ # Send config table to logs
53
+ info "prepare: dumping configuration\n#{@table.to_s}"
54
+ end
55
+
56
+ def main
57
+ loop do
58
+ info "ping"
59
+ sleep(1)
60
+ end
61
+ end
62
+
63
+ private
64
+
65
+ def abort message
66
+ @logger.error "ABORT: #{message}"
67
+ raise "ABORT: #{message}"
68
+ end
69
+
70
+ def info message
71
+ @logger.info message
72
+ end
73
+
74
+ def dump_rules rules
75
+
76
+ end
77
+
78
+ # Start connexion to RabbitMQ
79
+ def connect busconf
80
+ abort "connect: bus host/port not found" unless busconf.is_a? Hash
81
+
82
+ puts "connecting to #{busconf[:host]} port #{busconf[:port]}"
83
+ conn = Bunny.new host: (busconf[:host].to_s || "localhost").to_s,
84
+ port: busconf[:port].to_i,
85
+ user: busconf[:user].to_s,
86
+ pass: busconf[:pass].to_s,
87
+ heartbeat: :server
88
+ conn.start
89
+ rescue Bunny::TCPConnectionFailedForAllHosts, Bunny::AuthenticationFailureError, AMQ::Protocol::EmptyResponseError => e
90
+ abort "connect: error connecting to RabbitMQ (#{e.class})"
91
+ rescue Exception => e
92
+ abort "connect: unknow connection error (#{e.inspect})"
93
+ else
94
+ return conn
95
+ end
96
+
97
+ # Declare or return the exchange for this topic
98
+ def channel_exchange topic
99
+ @exchanges ||= {}
100
+ @exchanges[topic] ||= @channel.topic(topic, durable: true, persistent: true)
101
+ end
102
+
103
+ # Subscribe to interesting topic/routes and bind a listenner
104
+ def channel_subscribe rule
105
+ # Check information
106
+ rule_name = rule[:name].to_s
107
+ rule_topic = rule[:topic].to_s
108
+ rule_routes = rule[:routes].to_s.split(' ')
109
+ rule_queue = "#{Config.name}-#{PROXY_SCOPE}-#{rule[:name]}"
110
+ abort "subscribe: rule [#{rule_name}] lacking topic" unless rule_topic
111
+ abort "subscribe: rule [#{rule_name}] lacking routes" if rule_routes.empty?
112
+
113
+ # Create queue for this rule (remove it beforehand)
114
+ #conn.create_channel.queue_delete(rule_queue_name)
115
+ queue = @channel.queue(rule_queue, auto_delete: false, durable: true)
116
+
117
+ # Bind each route from this topic-exchange
118
+ topic_exchange = channel_exchange(rule_topic)
119
+ rule_routes.each do |route|
120
+ # Bind exchange to queue
121
+ queue.bind topic_exchange, routing_key: route
122
+ info "subscribe: bind: \t[#{rule_topic}] \t[#{route}] \t> [#{rule_queue}]"
123
+
124
+ # Add row to config table
125
+ @table.add_row [rule_name, rule_topic, route, rule[:relay].to_s, rule[:title].to_s ]
126
+ end
127
+
128
+ # Subscribe to our new queue
129
+ queue.subscribe(block: false, manual_ack: PROXY_USE_ACK, message_max: PROXY_MESSAGE_MAX) do |delivery_info, metadata, payload|
130
+
131
+ # Handle the message
132
+ handle_message rule[:name], rule, delivery_info, metadata, payload
133
+
134
+ end
135
+
136
+ rescue Bunny::PreconditionFailed => e
137
+ abort "subscribe: PreconditionFailed: [#{rule_topic}] code(#{e.channel_close.reply_code}) message(#{e.channel_close.reply_text})"
138
+ rescue Exception => e
139
+ abort "subscribe: unhandled (#{e.inspect})"
140
+
141
+ end
142
+
143
+ # Handle the reception of a message on a queue
144
+ def handle_message rule, delivery_info, metadata, payload
145
+ # Prepare data
146
+ rule_name = rule[:name]
147
+ msg_topic = delivery_info.exchange
148
+ msg_rkey = delivery_info.routing_key.force_encoding('UTF-8')
149
+ msg_headers = metadata.headers || {}
150
+
151
+ # Extract fields
152
+ data = parse payload, metadata.content_type #, rule
153
+
154
+ # Announce match
155
+ header rule_name, "<", msg_topic, msg_rkey
156
+
157
+ # Build notification payload
158
+ body = {
159
+ # received: msg_topic,
160
+ exchange: msg_topic,
161
+ route: msg_rkey,
162
+ #headers: msg_headers,
163
+ sent_at: msg_headers['sent_at'],
164
+ sent_by: msg_headers['sent_by'],
165
+ data: data,
166
+ }
167
+ pretty_body = JSON.pretty_generate(body)
168
+
169
+ # Dump body data
170
+ puts "RULE: #{rule.inspect}"
171
+ puts "APP-ID: #{metadata.app_id}"
172
+ puts "CONTENT-TYPE: #{metadata.content_type}"
173
+ puts pretty_body
174
+
175
+ # Propagate data if needed
176
+ #propagate rule[:relay], pretty_body
177
+ end
178
+
179
+ def propagate url, body
180
+ # Nothing more to do if no relay
181
+ return if url.nil? || url.empty?
182
+
183
+ # Push message to URL
184
+ puts "> POST #{url}"
185
+ response = RestClient.post url.to_s, body, :content_type => :json
186
+ puts "< #{response.body}"
187
+
188
+ rescue Exception => e
189
+ abort "propagate: #{e.message}"
190
+
191
+ end
192
+
193
+
194
+ def parse payload, content_type #, fields = []
195
+ # Force encoding (pftop...)
196
+ utf8payload = payload.force_encoding('UTF-8')
197
+
198
+ # Parse payload if content-type provided
199
+ case content_type
200
+ when "application/json"
201
+ # if fields = rule[:payload_extract]
202
+ # data = payload_extract(payload, fields)
203
+ # data_source = "extract #{fields.inspect} #{data.keys.count}k"
204
+ return JSON.parse utf8payload
205
+
206
+ when "text/plain"
207
+ return utf8payload.to_s
208
+
209
+ else
210
+ return utf8payload
211
+ end
212
+
213
+ # Handle body parse errors
214
+ rescue Encoding::UndefinedConversionError => e
215
+ abort "parse: JSON PARSE ERROR: #{e.inspect}"
216
+ return {}
217
+ end
218
+
219
+ end
220
+
221
+ end
222
+
223
+
224
+ # def prepare_shout
225
+
226
+
227
+ # # Prepare shout config
228
+ # shout_config = config[:shout]
229
+ # shout_exchange = nil
230
+ # shout_keys = []
231
+
232
+ # if shout_config.is_a? Hash
233
+ # shout_exchange = topic(channel, shout_config[:topic])
234
+ # shout_keys = shout_config[:keys] if shout_config[:keys].is_a? Array
235
+ # end
236
+
237
+ # end
238
+
239
+ # def endlessly
240
+ # # Endless loop with shout config
241
+ # begin
242
+ # loop do
243
+ # if shout_exchange
244
+ # random_string = SecureRandom.hex
245
+ # random_key = shout_keys.sample || "random"
246
+ # shout shout_exchange, [:ping, random_key, random_string], {}
247
+ # end
248
+ # sleep 1
249
+ # end
250
+ # rescue AMQ::Protocol::EmptyResponseError => e
251
+ # abort "ERROR: AMQ::Protocol::EmptyResponseError (#{e.inspect})"
252
+ # rescue Bunny::TCPConnectionFailedForAllHosts => e
253
+ # abort "ERROR: cannot connect to RabbitMQ hosts (#{e.inspect})"
254
+ # rescue Bunny::ChannelAlreadyClosed => e
255
+ # abort "ERROR: channel unexpectedly closed (#{e.inspect})"
256
+ # # sleep 1
257
+ # # retry
258
+ # rescue Bunny::PreconditionFailed => e
259
+ # abort "ERROR: precondition failed (#{e.inspect})"
260
+ # rescue Interrupt => e
261
+ # channel.close
262
+ # conn.close
263
+ # abort "QUITTING"
264
+ # end
265
+ # end
266
+
267
+ # Dump configuration
268
+ # Hashie.symbolize_keys! config
data/lib/pushyd.rb ADDED
@@ -0,0 +1,13 @@
1
+
2
+ # Global libs
3
+ require "rubygems"
4
+ require "json"
5
+ require "thread"
6
+ require "singleton"
7
+ # require "newrelic_rpm"
8
+
9
+ # Project's libs
10
+ require_relative "pushyd/config"
11
+ require_relative "pushyd/proxy"
12
+ require_relative "pushyd/daemon"
13
+
data/pushyd.gemspec ADDED
@@ -0,0 +1,38 @@
1
+ # coding: utf-8
2
+ Gem::Specification.new do |spec|
3
+ # Project version
4
+ spec.version = "0.0.2"
5
+
6
+ # Project description
7
+ spec.name = "pushyd"
8
+ spec.authors = ["Bruno MEDICI"]
9
+ spec.email = "pushyd@bmconseil.com"
10
+ spec.description = "(description to be written)"
11
+ spec.summary = "(summary to be written)"
12
+ spec.homepage = "http://github.com/bmedici/pushyd"
13
+ spec.licenses = ["MIT"]
14
+ spec.date = Time.now.strftime("%Y-%m-%d")
15
+
16
+ # List files and executables
17
+ spec.files = `git ls-files -z`.split("\x0").reject{ |f| f == "dashboard.png"}
18
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
19
+ spec.require_paths = ["lib"]
20
+ spec.required_ruby_version = ">= 2.2"
21
+
22
+ # Development dependencies
23
+ spec.add_development_dependency "bundler", "~> 1.6"
24
+ spec.add_development_dependency "rake"
25
+ spec.add_development_dependency "rspec"
26
+ spec.add_development_dependency "http", "~> 0.8"
27
+ spec.add_development_dependency "rubocop", "~> 0.32.0"
28
+ # spec.add_development_dependency "pry"
29
+
30
+ # Runtime dependencies
31
+ spec.add_runtime_dependency "daemons"
32
+ spec.add_runtime_dependency "chamber"
33
+ spec.add_runtime_dependency "json"
34
+ spec.add_runtime_dependency "bunny"
35
+ spec.add_runtime_dependency "rest_client"
36
+ spec.add_runtime_dependency "terminal-table"
37
+ # spec.add_runtime_dependency "newrelic_rpm"
38
+ end
metadata ADDED
@@ -0,0 +1,210 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: pushyd
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.2
5
+ platform: ruby
6
+ authors:
7
+ - Bruno MEDICI
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2016-06-02 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.6'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.6'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rspec
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: http
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '0.8'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '0.8'
69
+ - !ruby/object:Gem::Dependency
70
+ name: rubocop
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: 0.32.0
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: 0.32.0
83
+ - !ruby/object:Gem::Dependency
84
+ name: daemons
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :runtime
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ - !ruby/object:Gem::Dependency
98
+ name: chamber
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ">="
102
+ - !ruby/object:Gem::Version
103
+ version: '0'
104
+ type: :runtime
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ">="
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
111
+ - !ruby/object:Gem::Dependency
112
+ name: json
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - ">="
116
+ - !ruby/object:Gem::Version
117
+ version: '0'
118
+ type: :runtime
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - ">="
123
+ - !ruby/object:Gem::Version
124
+ version: '0'
125
+ - !ruby/object:Gem::Dependency
126
+ name: bunny
127
+ requirement: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - ">="
130
+ - !ruby/object:Gem::Version
131
+ version: '0'
132
+ type: :runtime
133
+ prerelease: false
134
+ version_requirements: !ruby/object:Gem::Requirement
135
+ requirements:
136
+ - - ">="
137
+ - !ruby/object:Gem::Version
138
+ version: '0'
139
+ - !ruby/object:Gem::Dependency
140
+ name: rest_client
141
+ requirement: !ruby/object:Gem::Requirement
142
+ requirements:
143
+ - - ">="
144
+ - !ruby/object:Gem::Version
145
+ version: '0'
146
+ type: :runtime
147
+ prerelease: false
148
+ version_requirements: !ruby/object:Gem::Requirement
149
+ requirements:
150
+ - - ">="
151
+ - !ruby/object:Gem::Version
152
+ version: '0'
153
+ - !ruby/object:Gem::Dependency
154
+ name: terminal-table
155
+ requirement: !ruby/object:Gem::Requirement
156
+ requirements:
157
+ - - ">="
158
+ - !ruby/object:Gem::Version
159
+ version: '0'
160
+ type: :runtime
161
+ prerelease: false
162
+ version_requirements: !ruby/object:Gem::Requirement
163
+ requirements:
164
+ - - ">="
165
+ - !ruby/object:Gem::Version
166
+ version: '0'
167
+ description: "(description to be written)"
168
+ email: pushyd@bmconseil.com
169
+ executables:
170
+ - pushyd.rb
171
+ extensions: []
172
+ extra_rdoc_files: []
173
+ files:
174
+ - ".gitignore"
175
+ - Gemfile
176
+ - Gemfile.lock
177
+ - README.md
178
+ - Rakefile
179
+ - bin/pushyd.rb
180
+ - defaults.yml
181
+ - lib/pushyd.rb
182
+ - lib/pushyd/config.rb
183
+ - lib/pushyd/daemon.rb
184
+ - lib/pushyd/proxy.rb
185
+ - pushyd.gemspec
186
+ homepage: http://github.com/bmedici/pushyd
187
+ licenses:
188
+ - MIT
189
+ metadata: {}
190
+ post_install_message:
191
+ rdoc_options: []
192
+ require_paths:
193
+ - lib
194
+ required_ruby_version: !ruby/object:Gem::Requirement
195
+ requirements:
196
+ - - ">="
197
+ - !ruby/object:Gem::Version
198
+ version: '2.2'
199
+ required_rubygems_version: !ruby/object:Gem::Requirement
200
+ requirements:
201
+ - - ">="
202
+ - !ruby/object:Gem::Version
203
+ version: '0'
204
+ requirements: []
205
+ rubyforge_project:
206
+ rubygems_version: 2.5.1
207
+ signing_key:
208
+ specification_version: 4
209
+ summary: "(summary to be written)"
210
+ test_files: []