nerve 0.3.0 → 0.5.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.travis.yml +5 -0
- data/CONTRIBUTING.md +14 -0
- data/Gemfile.lock +19 -7
- data/README.md +14 -6
- data/Rakefile +6 -0
- data/bin/nerve +18 -8
- data/example/nerve.conf.json +6 -3
- data/example/nerve_services/service1.json +2 -1
- data/lib/nerve/reporter/base.rb +26 -0
- data/lib/nerve/reporter/zookeeper.rb +70 -0
- data/lib/nerve/reporter.rb +8 -57
- data/lib/nerve/service_watcher.rb +2 -9
- data/lib/nerve/version.rb +1 -1
- data/lib/nerve.rb +5 -2
- data/nerve.gemspec +4 -1
- data/spec/.gitkeep +0 -0
- data/spec/lib/nerve/reporter_spec.rb +27 -0
- data/spec/lib/nerve/reporter_zookeeper_spec.rb +17 -0
- data/spec/spec_helper.rb +20 -0
- metadata +49 -5
data/.travis.yml
ADDED
data/CONTRIBUTING.md
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
# Contributing Guidelines #
|
2
|
+
|
3
|
+
Thanks for contributing to SmartStack!
|
4
|
+
If you're opening a new PR, please ask for a merge into our `pull_requests` branch -- *not* `master`.
|
5
|
+
This will allow us avoid a back-and-forth by quickly accepting your PR and then making minor changes or doing testing before merging into `master`.
|
6
|
+
|
7
|
+
## Writing Checks ##
|
8
|
+
|
9
|
+
We welcome additional service checks into the core of nerve.
|
10
|
+
However, your checks must follow a few guidelines or they will not be accepted:
|
11
|
+
|
12
|
+
* be sure to respect timeouts; checks that do not time-out will not be accepted
|
13
|
+
* do NOT shell out; this becomes very expensive when done frequently
|
14
|
+
* use well-tested, stable, core libraries whenever possible
|
data/Gemfile.lock
CHANGED
@@ -1,23 +1,33 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
nerve (0.
|
5
|
-
bunny (= 1.
|
4
|
+
nerve (0.5.0)
|
5
|
+
bunny (= 1.1.0)
|
6
6
|
zk (~> 1.9.2)
|
7
7
|
|
8
8
|
GEM
|
9
9
|
remote: https://rubygems.org/
|
10
10
|
specs:
|
11
|
-
amq-protocol (1.
|
12
|
-
bunny (1.
|
13
|
-
amq-protocol (>= 1.
|
11
|
+
amq-protocol (1.9.2)
|
12
|
+
bunny (1.1.0)
|
13
|
+
amq-protocol (>= 1.9.2)
|
14
|
+
diff-lcs (1.2.5)
|
14
15
|
little-plugger (1.1.3)
|
15
16
|
logging (1.7.2)
|
16
17
|
little-plugger (>= 1.1.3)
|
17
|
-
|
18
|
+
rake (10.1.1)
|
19
|
+
rspec (2.14.1)
|
20
|
+
rspec-core (~> 2.14.0)
|
21
|
+
rspec-expectations (~> 2.14.0)
|
22
|
+
rspec-mocks (~> 2.14.0)
|
23
|
+
rspec-core (2.14.7)
|
24
|
+
rspec-expectations (2.14.4)
|
25
|
+
diff-lcs (>= 1.1.3, < 2.0)
|
26
|
+
rspec-mocks (2.14.4)
|
27
|
+
zk (1.9.3)
|
18
28
|
logging (~> 1.7.2)
|
19
29
|
zookeeper (~> 1.4.0)
|
20
|
-
zookeeper (1.4.
|
30
|
+
zookeeper (1.4.8)
|
21
31
|
|
22
32
|
PLATFORMS
|
23
33
|
java
|
@@ -25,3 +35,5 @@ PLATFORMS
|
|
25
35
|
|
26
36
|
DEPENDENCIES
|
27
37
|
nerve!
|
38
|
+
rake
|
39
|
+
rspec
|
data/README.md
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
[![Build Status](https://travis-ci.org/airbnb/nerve.png?branch=master)](https://travis-ci.org/airbnb/nerve)
|
2
|
+
|
1
3
|
# Nerve
|
2
4
|
|
3
5
|
Nerve is a utility for tracking the status of machines and services.
|
@@ -8,7 +10,7 @@ The combination of Nerve and [Synapse](https://github.com/airbnb/synapse) make s
|
|
8
10
|
## Motivation ##
|
9
11
|
|
10
12
|
We already use [Synapse](https://github.com/airbnb/synapse) to discover remote services.
|
11
|
-
However, those services needed boilerplate code to register themselves in [Zookeeper](zookeeper.apache.org/).
|
13
|
+
However, those services needed boilerplate code to register themselves in [Zookeeper](http://zookeeper.apache.org/).
|
12
14
|
Nerve simplifies underlying services, enables code reuse, and allows us to create a more composable system.
|
13
15
|
It does so by factoring out the boilerplate into it's own application, which independenly handles monitoring and reporting.
|
14
16
|
|
@@ -36,7 +38,7 @@ It is usually called `nerve.conf.json`.
|
|
36
38
|
An example config file is available in `example/nerve.conf.json`.
|
37
39
|
The config file is composed of two main sections:
|
38
40
|
|
39
|
-
* `instance_id`: the name
|
41
|
+
* `instance_id`: the name nerve will submit when registering services; makes debugging easier
|
40
42
|
* `services`: the hash (from service name to config) of the services nerve will be monitoring
|
41
43
|
* `service_conf_dir`: path to a directory in which each json file will be interpreted as a service with the basename of the file minus the .json extension
|
42
44
|
|
@@ -46,13 +48,19 @@ Each service that nerve will be monitoring is specified in the `services` hash.
|
|
46
48
|
The key is the name of the service, and the value is a configuration hash telling nerve how to monitor the service.
|
47
49
|
The configuration contains the following options:
|
48
50
|
|
49
|
-
* `
|
50
|
-
* `
|
51
|
-
* `
|
52
|
-
* `zk_path`: the path (or [znode](https://zookeeper.apache.org/doc/r3.1.2/zookeeperProgrammers.html#sc_zkDataModel_znodes)) where the registration will be created; nerve will create the [ephemeral node](https://zookeeper.apache.org/doc/r3.1.2/zookeeperProgrammers.html#Ephemeral+Nodes) that is the registration as a child of this path
|
51
|
+
* `host`: the default host on which to make service checks; you should make this your *public* ip to ensure your service is publically accessible
|
52
|
+
* `port`: the default port for service checks; nerve will report the `host`:`port` combo via your chosen reporter
|
53
|
+
* `reporter_type`: the mechanism used to report up/down information; depending on the reporter you choose, additional parameters may be required. Defaults to `zookeeper`
|
53
54
|
* `check_interval`: the frequency with which service checks will be initiated; defaults to `500ms`
|
54
55
|
* `checks`: a list of checks that nerve will perform; if all of the pass, the service will be registered; otherwise, it will be un-registered
|
55
56
|
|
57
|
+
#### Zookeeper Reporter ####
|
58
|
+
|
59
|
+
If you set your `reporter_type` to `"zookeeper"` you should also set these parameters:
|
60
|
+
|
61
|
+
* `zk_hosts`: a list of the zookeeper hosts comprising the [ensemble](https://zookeeper.apache.org/doc/r3.1.2/zookeeperAdmin.html#sc_zkMulitServerSetup) that nerve will submit registration to
|
62
|
+
* `zk_path`: the path (or [znode](https://zookeeper.apache.org/doc/r3.1.2/zookeeperProgrammers.html#sc_zkDataModel_znodes)) where the registration will be created; nerve will create the [ephemeral node](https://zookeeper.apache.org/doc/r3.1.2/zookeeperProgrammers.html#Ephemeral+Nodes) that is the registration as a child of this path
|
63
|
+
|
56
64
|
### Checks ###
|
57
65
|
|
58
66
|
The core of nerve is a set of service checks.
|
data/Rakefile
CHANGED
data/bin/nerve
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
|
3
|
-
require '
|
3
|
+
require 'yaml'
|
4
4
|
require 'optparse'
|
5
5
|
|
6
6
|
require 'nerve'
|
@@ -20,7 +20,13 @@ EOB
|
|
20
20
|
options[:config] = key
|
21
21
|
end
|
22
22
|
|
23
|
-
|
23
|
+
options[:instance_id] = ENV['NERVE_INSTANCE_ID']
|
24
|
+
opts.on('-i instance_id','--instance_id instance_id', String,
|
25
|
+
'reported as `name` to ZK; overrides instance id from config file') do |key,value|
|
26
|
+
options[:instance_id] = key
|
27
|
+
end
|
28
|
+
|
29
|
+
opts.on('-h', '--help', 'Display this screen') do
|
24
30
|
puts opts
|
25
31
|
exit
|
26
32
|
end
|
@@ -34,15 +40,15 @@ optparse.parse!
|
|
34
40
|
def parseconfig(filename)
|
35
41
|
# parse synapse config file
|
36
42
|
begin
|
37
|
-
c =
|
43
|
+
c = YAML::parse(File.read(filename))
|
38
44
|
rescue Errno::ENOENT => e
|
39
45
|
raise ArgumentError, "config file does not exist:\n#{e.inspect}"
|
40
46
|
rescue Errno::EACCES => e
|
41
47
|
raise ArgumentError, "could not open config file:\n#{e.inspect}"
|
42
|
-
rescue
|
43
|
-
raise "config file #{filename} is not
|
48
|
+
rescue YAML::ParseError => e
|
49
|
+
raise "config file #{filename} is not yaml:\n#{e.inspect}"
|
44
50
|
end
|
45
|
-
return c
|
51
|
+
return c.to_ruby
|
46
52
|
end
|
47
53
|
|
48
54
|
config = parseconfig(options[:config])
|
@@ -53,8 +59,12 @@ if config.has_key?('service_conf_dir')
|
|
53
59
|
if ! Dir.exists?(cdir) then
|
54
60
|
raise "service conf dir does not exist:#{cdir}"
|
55
61
|
end
|
56
|
-
cfiles = Dir.glob(File.join(cdir, '*.json'))
|
57
|
-
cfiles.each { |x| config['services'][File.basename(x[/(.*)\.json$/, 1])] = parseconfig(x) }
|
62
|
+
cfiles = Dir.glob(File.join(cdir, '*.{yaml,json}'))
|
63
|
+
cfiles.each { |x| config['services'][File.basename(x[/(.*)\.(yaml|json)$/, 1])] = parseconfig(x) }
|
64
|
+
end
|
65
|
+
|
66
|
+
if options[:instance_id] && !options[:instance_id].empty?
|
67
|
+
config['instance_id'] = options[:instance_id]
|
58
68
|
end
|
59
69
|
|
60
70
|
# create nerve object
|
data/example/nerve.conf.json
CHANGED
@@ -3,8 +3,9 @@
|
|
3
3
|
"service_conf_dir": "example/nerve_services",
|
4
4
|
"services": {
|
5
5
|
"your_http_service": {
|
6
|
+
"host": "1.2.3.4",
|
6
7
|
"port": 3000,
|
7
|
-
"
|
8
|
+
"reporter_type": "zookeeper",
|
8
9
|
"zk_hosts": ["localhost:2181"],
|
9
10
|
"zk_path": "/nerve/services/your_http_service/services",
|
10
11
|
"check_interval": 2,
|
@@ -19,8 +20,9 @@
|
|
19
20
|
]
|
20
21
|
},
|
21
22
|
"your_tcp_service": {
|
23
|
+
"host": "1.2.3.4",
|
22
24
|
"port": 6379,
|
23
|
-
"
|
25
|
+
"reporter_type": "zookeeper",
|
24
26
|
"zk_hosts": ["localhost:2181"],
|
25
27
|
"zk_path": "/nerve/services/your_tcp_service/services",
|
26
28
|
"check_interval": 2,
|
@@ -34,8 +36,9 @@
|
|
34
36
|
]
|
35
37
|
},
|
36
38
|
"rabbitmq_service": {
|
39
|
+
"host": "1.2.3.4",
|
37
40
|
"port": 5672,
|
38
|
-
"
|
41
|
+
"reporter_type": "zookeeper",
|
39
42
|
"zk_hosts": ["localhost:2181"],
|
40
43
|
"zk_path": "/nerve/services/your_rabbitmq_service/services",
|
41
44
|
"check_interval": 2,
|
@@ -0,0 +1,26 @@
|
|
1
|
+
|
2
|
+
class Nerve::Reporter
|
3
|
+
class Base
|
4
|
+
include Nerve::Utils
|
5
|
+
include Nerve::Logging
|
6
|
+
|
7
|
+
def initialize(opts)
|
8
|
+
end
|
9
|
+
|
10
|
+
def start
|
11
|
+
end
|
12
|
+
|
13
|
+
def report_up
|
14
|
+
end
|
15
|
+
|
16
|
+
def report_down
|
17
|
+
end
|
18
|
+
|
19
|
+
def update_data(new_data='')
|
20
|
+
end
|
21
|
+
|
22
|
+
def ping?
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
@@ -0,0 +1,70 @@
|
|
1
|
+
require 'nerve/reporter/base'
|
2
|
+
require 'zk'
|
3
|
+
|
4
|
+
class Nerve::Reporter
|
5
|
+
class Zookeeper < Base
|
6
|
+
def initalize(service)
|
7
|
+
%w{zk_hosts zk_path instance_id host port}.each do |required|
|
8
|
+
raise ArgumentError, "missing required argument #{required} for new service watcher" unless service[required]
|
9
|
+
end
|
10
|
+
@path = service['zk_hosts'].shuffle.join(',') + opts['zk_path']
|
11
|
+
@data = parse_data({'host' => service['host'], 'port' => service['port'], 'name' => service['instance_id']})
|
12
|
+
|
13
|
+
@key = "/#{service['instance_id']}_"
|
14
|
+
@full_key = nil
|
15
|
+
end
|
16
|
+
|
17
|
+
def start()
|
18
|
+
log.info "nerve: waiting to connect to zookeeper at #{@path}"
|
19
|
+
@zk = ZK.new(@path)
|
20
|
+
|
21
|
+
log.info "nerve: successfully created zk connection to #{@path}"
|
22
|
+
end
|
23
|
+
|
24
|
+
def report_up()
|
25
|
+
zk_save
|
26
|
+
end
|
27
|
+
|
28
|
+
def report_down
|
29
|
+
zk_delete
|
30
|
+
end
|
31
|
+
|
32
|
+
def update_data(new_data='')
|
33
|
+
@data = parse_data(new_data)
|
34
|
+
zk_save
|
35
|
+
end
|
36
|
+
|
37
|
+
def ping?
|
38
|
+
return @zk.ping?
|
39
|
+
end
|
40
|
+
|
41
|
+
private
|
42
|
+
|
43
|
+
def zk_delete
|
44
|
+
if @full_key
|
45
|
+
@zk.delete(@full_key, :ignore => :no_node)
|
46
|
+
@full_key = nil
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
def zk_create
|
51
|
+
@full_key = @zk.create(@key, :data => @data, :mode => :ephemeral_sequential)
|
52
|
+
end
|
53
|
+
|
54
|
+
def zk_save
|
55
|
+
return zk_create unless @full_key
|
56
|
+
|
57
|
+
begin
|
58
|
+
@zk.set(@full_key, @data)
|
59
|
+
rescue ZK::Exceptions::NoNode
|
60
|
+
zk_create
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
def parse_data(data)
|
65
|
+
return data if data.class == String
|
66
|
+
return data.to_json
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
data/lib/nerve/reporter.rb
CHANGED
@@ -1,64 +1,15 @@
|
|
1
|
-
require 'zk'
|
2
1
|
|
3
2
|
module Nerve
|
4
3
|
class Reporter
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
@path = opts['hosts'].shuffle.join(',') + opts['path']
|
14
|
-
@data = parse_data(opts['data'] || '')
|
15
|
-
@key = opts['key']
|
16
|
-
@key.insert(0,'/') unless @key[0] == '/'
|
17
|
-
end
|
18
|
-
|
19
|
-
def start()
|
20
|
-
log.info "nerve: waiting to connect to zookeeper at #{@path}"
|
21
|
-
@zk = ZK.new(@path)
|
22
|
-
|
23
|
-
log.info "nerve: successfully created zk connection to #{@path}"
|
24
|
-
end
|
25
|
-
|
26
|
-
def report_up()
|
27
|
-
zk_save
|
28
|
-
end
|
29
|
-
|
30
|
-
def report_down
|
31
|
-
zk_delete
|
32
|
-
end
|
33
|
-
|
34
|
-
def update_data(new_data='')
|
35
|
-
@data = parse_data(new_data)
|
36
|
-
zk_save
|
37
|
-
end
|
38
|
-
|
39
|
-
def ping?
|
40
|
-
return @zk.ping?
|
41
|
-
end
|
42
|
-
|
43
|
-
private
|
44
|
-
|
45
|
-
def zk_delete
|
46
|
-
@zk.delete(@key, :ignore => :no_node)
|
47
|
-
end
|
48
|
-
|
49
|
-
def zk_save
|
50
|
-
log.debug "nerve: writing data #{@data.class} to zk at #{@key} with #{@data.inspect}"
|
51
|
-
begin
|
52
|
-
@zk.set(@key,@data)
|
53
|
-
rescue ZK::Exceptions::NoNode => e
|
54
|
-
@zk.create(@key,:data => @data, :mode => :ephemeral)
|
4
|
+
def self.new_from_service(service)
|
5
|
+
type = service['reporter_type'] || 'zookeeper'
|
6
|
+
reporter = begin
|
7
|
+
require "nerve/reporter/#{type.downcase}"
|
8
|
+
self.const_get(type.downcase.capitalize)
|
9
|
+
rescue Exception => e
|
10
|
+
raise ArgumentError, "specified a reporter_type of #{type}, which could not be found: #{e}"
|
55
11
|
end
|
12
|
+
reporter.new(service)
|
56
13
|
end
|
57
|
-
|
58
|
-
def parse_data(data)
|
59
|
-
return data if data.class == String
|
60
|
-
return data.to_json
|
61
|
-
end
|
62
|
-
|
63
14
|
end
|
64
15
|
end
|
@@ -11,19 +11,14 @@ module Nerve
|
|
11
11
|
log.debug "nerve: creating service watcher object"
|
12
12
|
|
13
13
|
# check that we have all of the required arguments
|
14
|
-
%w{name instance_id host port
|
14
|
+
%w{name instance_id host port}.each do |required|
|
15
15
|
raise ArgumentError, "missing required argument #{required} for new service watcher" unless service[required]
|
16
16
|
end
|
17
17
|
|
18
18
|
@name = service['name']
|
19
19
|
|
20
20
|
# configure the reporter, which we use for talking to zookeeper
|
21
|
-
@reporter = Reporter.
|
22
|
-
'hosts' => service['zk_hosts'],
|
23
|
-
'path' => service['zk_path'],
|
24
|
-
'key' => "#{service['instance_id']}_#{@name}",
|
25
|
-
'data' => {'host' => service['host'], 'port' => service['port']},
|
26
|
-
})
|
21
|
+
@reporter = Reporter.new_from_service(service)
|
27
22
|
|
28
23
|
# instantiate the checks for this service
|
29
24
|
@service_checks = []
|
@@ -52,9 +47,7 @@ module Nerve
|
|
52
47
|
def run()
|
53
48
|
log.info "nerve: starting service watch #{@name}"
|
54
49
|
|
55
|
-
# begin by reporting down
|
56
50
|
@reporter.start()
|
57
|
-
@reporter.report_down
|
58
51
|
was_up = false
|
59
52
|
|
60
53
|
until $EXIT
|
data/lib/nerve/version.rb
CHANGED
data/lib/nerve.rb
CHANGED
@@ -42,9 +42,12 @@ module Nerve
|
|
42
42
|
|
43
43
|
begin
|
44
44
|
sleep
|
45
|
-
rescue
|
46
|
-
log.
|
45
|
+
rescue StandardError => e
|
46
|
+
log.error 'nerve: encountered unexpected exception #{e.inspect} in main thread'
|
47
|
+
raise e
|
48
|
+
ensure
|
47
49
|
$EXIT = true
|
50
|
+
log.warn 'nerve: reaping all watchers'
|
48
51
|
@watchers.each do |name, watcher_thread|
|
49
52
|
reap_watcher(name)
|
50
53
|
end
|
data/nerve.gemspec
CHANGED
@@ -18,5 +18,8 @@ Gem::Specification.new do |gem|
|
|
18
18
|
gem.require_paths = ["lib"]
|
19
19
|
|
20
20
|
gem.add_runtime_dependency "zk", "~> 1.9.2"
|
21
|
-
gem.add_runtime_dependency "bunny", "= 1.
|
21
|
+
gem.add_runtime_dependency "bunny", "= 1.1.0"
|
22
|
+
|
23
|
+
gem.add_development_dependency "rake"
|
24
|
+
gem.add_development_dependency "rspec"
|
22
25
|
end
|
data/spec/.gitkeep
ADDED
File without changes
|
@@ -0,0 +1,27 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Nerve::Reporter do
|
4
|
+
let(:subject) { {
|
5
|
+
'zk_hosts' => ['zkhost1', 'zkhost2'],
|
6
|
+
'zk_path' => 'zk_path',
|
7
|
+
'instance_id' => 'instance_id',
|
8
|
+
'host' => 'host',
|
9
|
+
'port' => 'port'
|
10
|
+
}
|
11
|
+
}
|
12
|
+
it 'can new_from_service' do
|
13
|
+
expect(Nerve::Reporter::Zookeeper).to receive(:new).with(subject).and_return('kerplunk')
|
14
|
+
expect(Nerve::Reporter.new_from_service(subject)).to eq('kerplunk')
|
15
|
+
end
|
16
|
+
it 'actually constructs an instance of a specific backend' do
|
17
|
+
expect(Nerve::Reporter.new_from_service(subject).is_a?(Nerve::Reporter::Zookeeper)).to eql(true)
|
18
|
+
end
|
19
|
+
it 'the reporter backend inherits from the base class' do
|
20
|
+
expect(Nerve::Reporter.new_from_service(subject).is_a?(Nerve::Reporter::Base)).to eql(true)
|
21
|
+
end
|
22
|
+
it 'throws ArgumentError if you ask for a reporter type which does not exist' do
|
23
|
+
subject['reporter_type'] = 'does_not_exist'
|
24
|
+
expect { Nerve::Reporter.new_from_service(subject) }.to raise_error(ArgumentError)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
@@ -0,0 +1,17 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'nerve/reporter/zookeeper'
|
3
|
+
|
4
|
+
describe Nerve::Reporter::Zookeeper do
|
5
|
+
let(:subject) { {
|
6
|
+
'zk_hosts' => ['zkhost1', 'zkhost2'],
|
7
|
+
'zk_path' => 'zk_path',
|
8
|
+
'instance_id' => 'instance_id',
|
9
|
+
'host' => 'host',
|
10
|
+
'port' => 'port'
|
11
|
+
}
|
12
|
+
}
|
13
|
+
it 'actually constructs an instance' do
|
14
|
+
expect(Nerve::Reporter::Zookeeper.new(subject).is_a?(Nerve::Reporter::Zookeeper)).to eql(true)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
# This file was generated by the `rspec --init` command. Conventionally, all
|
2
|
+
# specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`.
|
3
|
+
# Require this file using `require "spec_helper"` to ensure that it is only
|
4
|
+
# loaded once.
|
5
|
+
#
|
6
|
+
# See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
|
7
|
+
require "#{File.dirname(__FILE__)}/../lib/nerve"
|
8
|
+
|
9
|
+
RSpec.configure do |config|
|
10
|
+
config.treat_symbols_as_metadata_keys_with_true_values = true
|
11
|
+
config.run_all_when_everything_filtered = true
|
12
|
+
config.filter_run :focus
|
13
|
+
config.include Config
|
14
|
+
|
15
|
+
# Run specs in random order to surface order dependencies. If you find an
|
16
|
+
# order dependency and want to debug it, you can fix the order by providing
|
17
|
+
# the seed, which is printed after each run.
|
18
|
+
# --seed 1234
|
19
|
+
config.order = 'random'
|
20
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: nerve
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.5.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -11,7 +11,7 @@ authors:
|
|
11
11
|
autorequire:
|
12
12
|
bindir: bin
|
13
13
|
cert_chain: []
|
14
|
-
date: 2014-
|
14
|
+
date: 2014-03-03 00:00:00.000000000 Z
|
15
15
|
dependencies:
|
16
16
|
- !ruby/object:Gem::Dependency
|
17
17
|
name: zk
|
@@ -36,7 +36,7 @@ dependencies:
|
|
36
36
|
requirements:
|
37
37
|
- - '='
|
38
38
|
- !ruby/object:Gem::Version
|
39
|
-
version: 1.
|
39
|
+
version: 1.1.0
|
40
40
|
type: :runtime
|
41
41
|
prerelease: false
|
42
42
|
version_requirements: !ruby/object:Gem::Requirement
|
@@ -44,7 +44,39 @@ dependencies:
|
|
44
44
|
requirements:
|
45
45
|
- - '='
|
46
46
|
- !ruby/object:Gem::Version
|
47
|
-
version: 1.
|
47
|
+
version: 1.1.0
|
48
|
+
- !ruby/object:Gem::Dependency
|
49
|
+
name: rake
|
50
|
+
requirement: !ruby/object:Gem::Requirement
|
51
|
+
none: false
|
52
|
+
requirements:
|
53
|
+
- - ! '>='
|
54
|
+
- !ruby/object:Gem::Version
|
55
|
+
version: '0'
|
56
|
+
type: :development
|
57
|
+
prerelease: false
|
58
|
+
version_requirements: !ruby/object:Gem::Requirement
|
59
|
+
none: false
|
60
|
+
requirements:
|
61
|
+
- - ! '>='
|
62
|
+
- !ruby/object:Gem::Version
|
63
|
+
version: '0'
|
64
|
+
- !ruby/object:Gem::Dependency
|
65
|
+
name: rspec
|
66
|
+
requirement: !ruby/object:Gem::Requirement
|
67
|
+
none: false
|
68
|
+
requirements:
|
69
|
+
- - ! '>='
|
70
|
+
- !ruby/object:Gem::Version
|
71
|
+
version: '0'
|
72
|
+
type: :development
|
73
|
+
prerelease: false
|
74
|
+
version_requirements: !ruby/object:Gem::Requirement
|
75
|
+
none: false
|
76
|
+
requirements:
|
77
|
+
- - ! '>='
|
78
|
+
- !ruby/object:Gem::Version
|
79
|
+
version: '0'
|
48
80
|
description: description
|
49
81
|
email:
|
50
82
|
- martin.rhoads@airbnb.com
|
@@ -57,6 +89,8 @@ files:
|
|
57
89
|
- .gitignore
|
58
90
|
- .mailmap
|
59
91
|
- .nerve.rc
|
92
|
+
- .travis.yml
|
93
|
+
- CONTRIBUTING.md
|
60
94
|
- Gemfile
|
61
95
|
- Gemfile.lock
|
62
96
|
- LICENSE.txt
|
@@ -69,6 +103,8 @@ files:
|
|
69
103
|
- lib/nerve.rb
|
70
104
|
- lib/nerve/log.rb
|
71
105
|
- lib/nerve/reporter.rb
|
106
|
+
- lib/nerve/reporter/base.rb
|
107
|
+
- lib/nerve/reporter/zookeeper.rb
|
72
108
|
- lib/nerve/ring_buffer.rb
|
73
109
|
- lib/nerve/service_watcher.rb
|
74
110
|
- lib/nerve/service_watcher/base.rb
|
@@ -78,6 +114,10 @@ files:
|
|
78
114
|
- lib/nerve/utils.rb
|
79
115
|
- lib/nerve/version.rb
|
80
116
|
- nerve.gemspec
|
117
|
+
- spec/.gitkeep
|
118
|
+
- spec/lib/nerve/reporter_spec.rb
|
119
|
+
- spec/lib/nerve/reporter_zookeeper_spec.rb
|
120
|
+
- spec/spec_helper.rb
|
81
121
|
homepage: ''
|
82
122
|
licenses: []
|
83
123
|
post_install_message:
|
@@ -102,4 +142,8 @@ rubygems_version: 1.8.23
|
|
102
142
|
signing_key:
|
103
143
|
specification_version: 3
|
104
144
|
summary: summary
|
105
|
-
test_files:
|
145
|
+
test_files:
|
146
|
+
- spec/.gitkeep
|
147
|
+
- spec/lib/nerve/reporter_spec.rb
|
148
|
+
- spec/lib/nerve/reporter_zookeeper_spec.rb
|
149
|
+
- spec/spec_helper.rb
|