nerve_pharmeasy 0.7.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.
- checksums.yaml +7 -0
- data/.gitignore +22 -0
- data/.mailmap +2 -0
- data/.nerve.rc +2 -0
- data/.travis.yml +8 -0
- data/CONTRIBUTING.md +28 -0
- data/Gemfile +2 -0
- data/Gemfile.lock +75 -0
- data/LICENSE.txt +22 -0
- data/README.md +116 -0
- data/Rakefile +7 -0
- data/Vagrantfile +121 -0
- data/bin/nerve +16 -0
- data/example/nerve.conf.json +54 -0
- data/example/nerve_services/etcd_service1.json +19 -0
- data/example/nerve_services/zookeeper_service1.json +18 -0
- data/lib/nerve/configuration_manager.rb +106 -0
- data/lib/nerve/log.rb +24 -0
- data/lib/nerve/reporter/base.rb +61 -0
- data/lib/nerve/reporter/etcd.rb +73 -0
- data/lib/nerve/reporter/zookeeper.rb +101 -0
- data/lib/nerve/reporter.rb +18 -0
- data/lib/nerve/ring_buffer.rb +30 -0
- data/lib/nerve/service_watcher/base.rb +65 -0
- data/lib/nerve/service_watcher/http.rb +70 -0
- data/lib/nerve/service_watcher/rabbitmq.rb +68 -0
- data/lib/nerve/service_watcher/tcp.rb +56 -0
- data/lib/nerve/service_watcher.rb +152 -0
- data/lib/nerve/utils.rb +17 -0
- data/lib/nerve/version.rb +3 -0
- data/lib/nerve.rb +249 -0
- data/nerve.conf.json +23 -0
- data/nerve.gemspec +33 -0
- data/spec/.gitkeep +0 -0
- data/spec/configuration_manager_spec.rb +31 -0
- data/spec/example_services_spec.rb +42 -0
- data/spec/factories/check.rb +16 -0
- data/spec/factories/service.rb +26 -0
- data/spec/lib/nerve/reporter_etcd_spec.rb +18 -0
- data/spec/lib/nerve/reporter_spec.rb +86 -0
- data/spec/lib/nerve/reporter_zookeeper_spec.rb +32 -0
- data/spec/lib/nerve/service_watcher_spec.rb +89 -0
- data/spec/lib/nerve_spec.rb +186 -0
- data/spec/spec_helper.rb +33 -0
- metadata +216 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 7fa208f63d742675316279d2dada16d3675a2cb8
|
4
|
+
data.tar.gz: d858a5049890b8f90a0e3113f4d2add354777f39
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 968b7d526d0db51e38b14f379d3c376a3597c2484f39f3320d872fa9314150709372ecd88c28f8b81ab187a060742f13a383d13e1619588e2b015df0f9e75379
|
7
|
+
data.tar.gz: f008dee705d0cff7412e36236c8a3549c98fd6d5e9d6e49b06aea5e8a82d2938577483c217fad62d9d5ea413b0f09662a096d85209b134ae42581ac1fe038f58
|
data/.gitignore
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
*.gem
|
2
|
+
*.rbc
|
3
|
+
.bundle
|
4
|
+
.config
|
5
|
+
.yardoc
|
6
|
+
InstalledFiles
|
7
|
+
_yardoc
|
8
|
+
coverage
|
9
|
+
doc/
|
10
|
+
lib/bundler/man
|
11
|
+
pkg
|
12
|
+
rdoc
|
13
|
+
spec/reports
|
14
|
+
test/tmp
|
15
|
+
test/version_tmp
|
16
|
+
tmp
|
17
|
+
*.sw?
|
18
|
+
\#*\#
|
19
|
+
.\#*
|
20
|
+
vendor
|
21
|
+
.vagrant
|
22
|
+
.ruby-version
|
data/.mailmap
ADDED
data/.nerve.rc
ADDED
data/.travis.yml
ADDED
data/CONTRIBUTING.md
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
# Contributing Guidelines #
|
2
|
+
|
3
|
+
Thanks for contributing to SmartStack!
|
4
|
+
|
5
|
+
If you are opening a new PR, please ask for a merge into the `master` branch.
|
6
|
+
|
7
|
+
## Writing Reporters ##
|
8
|
+
Nerve supports *pluggable* reporters, which means that you can easily add
|
9
|
+
a reporter by making your own gem that contains your reporter available for
|
10
|
+
require at ``nerve/reporter/#{name.downcase}``. If you do this please do
|
11
|
+
submit a PR with a link to your gem/repo and we can reference it from the
|
12
|
+
README.
|
13
|
+
|
14
|
+
In general it is preferred to keep reporters that require specific dependencies
|
15
|
+
out of nerve because that way you can select the version of dependencies that
|
16
|
+
you need (for example if you have a particular version of the docker api or
|
17
|
+
etcd). That being said, if your reporter has no external dependencies
|
18
|
+
(e.g. files) or is extremely common (e.g. zookeeper, etcd), we may choose to
|
19
|
+
support it in the repo itself.
|
20
|
+
|
21
|
+
## Writing Checks ##
|
22
|
+
|
23
|
+
We welcome additional service checks into the core of nerve.
|
24
|
+
However, your checks must follow a few guidelines or they will not be accepted:
|
25
|
+
|
26
|
+
* be sure to respect timeouts; checks that do not time-out will not be accepted
|
27
|
+
* do NOT shell out; this becomes very expensive when done frequently
|
28
|
+
* use well-tested, stable, core libraries whenever possible
|
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,75 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
nerve (0.7.0)
|
5
|
+
bunny (= 1.1.0)
|
6
|
+
etcd (~> 0.2.3)
|
7
|
+
json
|
8
|
+
zk (~> 1.9.2)
|
9
|
+
|
10
|
+
GEM
|
11
|
+
remote: https://rubygems.org/
|
12
|
+
specs:
|
13
|
+
activesupport (4.2.0)
|
14
|
+
i18n (~> 0.7)
|
15
|
+
json (~> 1.7, >= 1.7.7)
|
16
|
+
minitest (~> 5.1)
|
17
|
+
thread_safe (~> 0.3, >= 0.3.4)
|
18
|
+
tzinfo (~> 1.1)
|
19
|
+
amq-protocol (1.9.2)
|
20
|
+
bunny (1.1.0)
|
21
|
+
amq-protocol (>= 1.9.2)
|
22
|
+
coderay (1.1.0)
|
23
|
+
diff-lcs (1.2.5)
|
24
|
+
etcd (0.2.4)
|
25
|
+
mixlib-log
|
26
|
+
factory_girl (4.5.0)
|
27
|
+
activesupport (>= 3.0.0)
|
28
|
+
i18n (0.7.0)
|
29
|
+
json (1.8.2)
|
30
|
+
little-plugger (1.1.3)
|
31
|
+
logging (1.8.2)
|
32
|
+
little-plugger (>= 1.1.3)
|
33
|
+
multi_json (>= 1.8.4)
|
34
|
+
method_source (0.8.2)
|
35
|
+
minitest (5.5.1)
|
36
|
+
mixlib-log (1.6.0)
|
37
|
+
multi_json (1.11.2)
|
38
|
+
pry (0.10.1)
|
39
|
+
coderay (~> 1.1.0)
|
40
|
+
method_source (~> 0.8.1)
|
41
|
+
slop (~> 3.4)
|
42
|
+
rake (10.1.1)
|
43
|
+
rspec (3.1.0)
|
44
|
+
rspec-core (~> 3.1.0)
|
45
|
+
rspec-expectations (~> 3.1.0)
|
46
|
+
rspec-mocks (~> 3.1.0)
|
47
|
+
rspec-core (3.1.7)
|
48
|
+
rspec-support (~> 3.1.0)
|
49
|
+
rspec-expectations (3.1.2)
|
50
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
51
|
+
rspec-support (~> 3.1.0)
|
52
|
+
rspec-mocks (3.1.3)
|
53
|
+
rspec-support (~> 3.1.0)
|
54
|
+
rspec-support (3.1.2)
|
55
|
+
slop (3.6.0)
|
56
|
+
thread_safe (0.3.4)
|
57
|
+
tzinfo (1.2.2)
|
58
|
+
thread_safe (~> 0.1)
|
59
|
+
zk (1.9.5)
|
60
|
+
logging (~> 1.8.2)
|
61
|
+
zookeeper (~> 1.4.0)
|
62
|
+
zookeeper (1.4.10)
|
63
|
+
|
64
|
+
PLATFORMS
|
65
|
+
ruby
|
66
|
+
|
67
|
+
DEPENDENCIES
|
68
|
+
factory_girl
|
69
|
+
nerve!
|
70
|
+
pry
|
71
|
+
rake
|
72
|
+
rspec (~> 3.1.0)
|
73
|
+
|
74
|
+
BUNDLED WITH
|
75
|
+
1.10.5
|
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2013 Airbnb, Inc.
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,116 @@
|
|
1
|
+
[](https://travis-ci.org/airbnb/nerve)
|
2
|
+
|
3
|
+
# Nerve
|
4
|
+
|
5
|
+
Nerve is a utility for tracking the status of machines and services.
|
6
|
+
It runs locally on the boxes which make up a distributed system, and reports state information to a distributed key-value store.
|
7
|
+
At Airbnb, we use Zookeeper as our key-value store.
|
8
|
+
The combination of Nerve and [Synapse](https://github.com/airbnb/synapse) make service discovery in the cloud easy!
|
9
|
+
|
10
|
+
## Motivation ##
|
11
|
+
|
12
|
+
We already use [Synapse](https://github.com/airbnb/synapse) to discover remote services.
|
13
|
+
However, those services needed boilerplate code to register themselves in [Zookeeper](http://zookeeper.apache.org/).
|
14
|
+
Nerve simplifies underlying services, enables code reuse, and allows us to create a more composable system.
|
15
|
+
It does so by factoring out the boilerplate into it's own application, which independenly handles monitoring and reporting.
|
16
|
+
|
17
|
+
Beyond those benefits, nerve also acts as a general watchdog on systems.
|
18
|
+
The information it reports can be used to take action from a centralized automation center: action like scaling distributed systems up or down or alerting ops or engineering about downtime.
|
19
|
+
|
20
|
+
## Installation ##
|
21
|
+
|
22
|
+
To download and run the nerve binary, first install a version of ruby. Then,
|
23
|
+
install nerve with:
|
24
|
+
|
25
|
+
```bash
|
26
|
+
$ mkdir -p /opt/smartstack/nerve
|
27
|
+
|
28
|
+
# If you want to install specific versions of dependencies such as an older
|
29
|
+
# version of the aws-sdk, the docker-api, etc, gem install that here *before*
|
30
|
+
# gem installing nerve. This is also where you would gem install
|
31
|
+
# custom reporters.
|
32
|
+
|
33
|
+
# If you are on Ruby 2.X use --no-document instead of --no-ri --no-rdoc
|
34
|
+
$ gem install nerve --install-dir /opt/smartstack/nerve --no-ri --no-rdoc
|
35
|
+
```
|
36
|
+
|
37
|
+
This will download nerve and its dependencies into /opt/smartstack/nerve. You
|
38
|
+
might wish to omit the `--install-dir` flag to use your system's default gem
|
39
|
+
path, however this will require you to run `gem install nerve` with root
|
40
|
+
permissions. You can also install via bundler, but keep in mind you'll pick up
|
41
|
+
Nerve's version of library dependencies and possibly not the ones you need
|
42
|
+
for your infra/apps.
|
43
|
+
|
44
|
+
## Configuration ##
|
45
|
+
|
46
|
+
Nerve depends on a single configuration file, in json format.
|
47
|
+
It is usually called `nerve.conf.json`.
|
48
|
+
An example config file is available in `example/nerve.conf.json`.
|
49
|
+
The config file is composed of two main sections:
|
50
|
+
|
51
|
+
* `instance_id`: the name nerve will submit when registering services; makes debugging easier
|
52
|
+
* `heartbeat_path`: a path to a file on disk to touch as nerve makes progress. This allows you to work around https://github.com/zk-ruby/zk/issues/50 by restarting a stuck nerve.
|
53
|
+
* `services`: the hash (from service name to config) of the services nerve will be monitoring
|
54
|
+
* `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
|
55
|
+
|
56
|
+
### Services Config ###
|
57
|
+
|
58
|
+
Each service that nerve will be monitoring is specified in the `services` hash.
|
59
|
+
The key is the name of the service, and the value is a configuration hash telling nerve how to monitor the service.
|
60
|
+
The configuration contains the following options:
|
61
|
+
|
62
|
+
* `host`: the default host on which to make service checks; you should make this your *public* ip to ensure your service is publically accessible
|
63
|
+
* `port`: the default port for service checks; nerve will report the `host`:`port` combo via your chosen reporter
|
64
|
+
* `reporter_type`: the mechanism used to report up/down information; depending on the reporter you choose, additional parameters may be required. Defaults to `zookeeper`
|
65
|
+
* `check_interval`: the frequency with which service checks will be initiated; defaults to `500ms`
|
66
|
+
* `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
|
67
|
+
* `weight` (optional): a positive integer weight value which can be used to affect the haproxy backend weighting in synapse.
|
68
|
+
* `haproxy_server_options` (optional): a string containing any special haproxy server options for this service instance. For example if you wanted to set a service instance as a backup.
|
69
|
+
* `labels` (optional): an object containing user-defined key-value pairs that describe this service instance. For example, you could label service instances with datacenter information.
|
70
|
+
|
71
|
+
#### Zookeeper Reporter ####
|
72
|
+
|
73
|
+
If you set your `reporter_type` to `"zookeeper"` you should also set these parameters:
|
74
|
+
|
75
|
+
* `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
|
76
|
+
* `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
|
77
|
+
|
78
|
+
#### Etcd Reporter ####
|
79
|
+
|
80
|
+
Note: Etcd support is currently experimental!
|
81
|
+
|
82
|
+
If you set your `reporter_type` to `"etcd"` you should also set these parameters:
|
83
|
+
|
84
|
+
* `etcd_host`: etcd host that nerve will submit registration to
|
85
|
+
* `etcd_port`: port to connect to etcd.
|
86
|
+
* `etcd_path`: the path where the registration will be created; nerve will create a node with a 30s ttl that is the registration as a child of this path, and then update it every few seconds
|
87
|
+
|
88
|
+
### Checks ###
|
89
|
+
|
90
|
+
The core of nerve is a set of service checks.
|
91
|
+
Each service can define a number of checks, and all of them must pass for the service to be registered.
|
92
|
+
Although the exact parameters passed to each check are different, all take a number of common arguments:
|
93
|
+
|
94
|
+
* `type`: (required) the kind of check; you can see available check types in the `lib/nerve/service_watcher` dir of this repo
|
95
|
+
* `name`: (optional) a descriptive, human-readable name for the check; it will be auto-generated based on the other parameters if not specified
|
96
|
+
* `host`: (optional) the host on which the check will be performed; defaults to the `host` of the service to which the check belongs
|
97
|
+
* `port`: (optional) the port on which the check will be performed; like `host`, it defaults to the `port` of the service
|
98
|
+
* `timeout`: (optional) maximum time the check can take; defaults to `100ms`
|
99
|
+
* `rise`: (optional) how many consecutive checks must pass before the check is considered passing; defaults to 1
|
100
|
+
* `fall`: (optional) how many consecutive checks must fail before the check is considered failing; defaults to 1
|
101
|
+
|
102
|
+
#### Custom External Checks ####
|
103
|
+
|
104
|
+
If you would like to run a custom check but don't feel like trying to get it merged into this project, there is a mechanism for including external checks thanks to @bakins (airbnb/nerve#36).
|
105
|
+
Build your custom check as a separate gem and make sure to `bundle install` it on your system.
|
106
|
+
|
107
|
+
Ideally, you should name your gem `"nerve-watcher-#{type}"`, as that is what nerve will `require` on boot.
|
108
|
+
However, if you have a custom name for your gem, you can specify that in the `module` argument to the check.
|
109
|
+
|
110
|
+
## Contributing
|
111
|
+
|
112
|
+
1. Fork it
|
113
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
114
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
115
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
116
|
+
5. Create new Pull Request
|
data/Rakefile
ADDED
data/Vagrantfile
ADDED
@@ -0,0 +1,121 @@
|
|
1
|
+
# -*- mode: ruby -*-
|
2
|
+
# vi: set ft=ruby :
|
3
|
+
|
4
|
+
unless ENV['COOKBOOK_DIR'] and ENV['DATA_BAG_DIR']
|
5
|
+
STDERR.puts "you need to set COOKBOOK_DIR and DATA_BAG_DIR as environment variables"
|
6
|
+
Kernel.exit 1
|
7
|
+
end
|
8
|
+
|
9
|
+
this_dir = File.dirname(File.expand_path __FILE__)
|
10
|
+
|
11
|
+
STDERR.puts "mounting #{this_dir} as /root/this_dir"
|
12
|
+
|
13
|
+
Vagrant::Config.run do |config|
|
14
|
+
# All Vagrant configuration is done here. The most common configuration
|
15
|
+
# options are documented and commented below. For a complete reference,
|
16
|
+
# please see the online documentation at vagrantup.com.
|
17
|
+
|
18
|
+
# Every Vagrant virtual environment requires a box to build off of.
|
19
|
+
config.vm.box = "precise64"
|
20
|
+
|
21
|
+
# The url from where the 'config.vm.box' box will be fetched if it
|
22
|
+
# doesn't already exist on the user's system.
|
23
|
+
# config.vm.box_url = "http://domain.com/path/to/above.box"
|
24
|
+
|
25
|
+
config.vm.box_url = 'http://files.vagrantup.com/precise64.box'
|
26
|
+
|
27
|
+
# Boot with a GUI so you can see the screen. (Default is headless)
|
28
|
+
# config.vm.boot_mode = :gui
|
29
|
+
|
30
|
+
# Assign this VM to a host-only network IP, allowing you to access it
|
31
|
+
# via the IP. Host-only networks can talk to the host machine as well as
|
32
|
+
# any other machines on the same network, but cannot be accessed (through this
|
33
|
+
# network interface) by any external networks.
|
34
|
+
# config.vm.network :hostonly, "192.168.33.10"
|
35
|
+
|
36
|
+
# Assign this VM to a bridged network, allowing you to connect directly to a
|
37
|
+
# network using the host's network device. This makes the VM appear as another
|
38
|
+
# physical device on your network.
|
39
|
+
# config.vm.network :bridged
|
40
|
+
|
41
|
+
# Forward a port from the guest to the host, which allows for outside
|
42
|
+
# computers to access the VM, whereas host only networking does not.
|
43
|
+
# config.vm.forward_port 80, 8080
|
44
|
+
|
45
|
+
# Share an additional folder to the guest VM. The first argument is
|
46
|
+
# an identifier, the second is the path on the guest to mount the
|
47
|
+
# folder, and the third is the path on the host to the actual folder.
|
48
|
+
# config.vm.share_folder "v-data", "/vagrant_data", "../data"
|
49
|
+
|
50
|
+
config.vm.share_folder 'this_dir', '/this_dir', this_dir
|
51
|
+
|
52
|
+
# Enable provisioning with Puppet stand alone. Puppet manifests
|
53
|
+
# are contained in a directory path relative to this Vagrantfile.
|
54
|
+
# You will need to create the manifests directory and a manifest in
|
55
|
+
# the file base.pp in the manifests_path directory.
|
56
|
+
#
|
57
|
+
# An example Puppet manifest to provision the message of the day:
|
58
|
+
#
|
59
|
+
# # group { "puppet":
|
60
|
+
# # ensure => "present",
|
61
|
+
# # }
|
62
|
+
# #
|
63
|
+
# # File { owner => 0, group => 0, mode => 0644 }
|
64
|
+
# #
|
65
|
+
# # file { '/etc/motd':
|
66
|
+
# # content => "Welcome to your Vagrant-built virtual machine!
|
67
|
+
# # Managed by Puppet.\n"
|
68
|
+
# # }
|
69
|
+
#
|
70
|
+
# config.vm.provision :puppet do |puppet|
|
71
|
+
# puppet.manifests_path = "manifests"
|
72
|
+
# puppet.manifest_file = "base.pp"
|
73
|
+
# end
|
74
|
+
|
75
|
+
# Enable provisioning with chef solo, specifying a cookbooks path, roles
|
76
|
+
# path, and data_bags path (all relative to this Vagrantfile), and adding
|
77
|
+
# some recipes and/or roles.
|
78
|
+
#
|
79
|
+
config.vm.provision :chef_solo do |chef|
|
80
|
+
# chef.cookbooks_path = "../my-recipes/cookbooks"
|
81
|
+
# chef.roles_path = "../my-recipes/roles"
|
82
|
+
# chef.data_bags_path = '/tmp/foo'
|
83
|
+
# chef.add_recipe "mysql"
|
84
|
+
# chef.add_role "web"
|
85
|
+
|
86
|
+
# You may also specify custom JSON attributes:
|
87
|
+
# chef.json = { :mysql_password => "foo" }
|
88
|
+
|
89
|
+
chef.data_bags_path = ENV['DATA_BAG_DIR']
|
90
|
+
chef.cookbooks_path = ENV['COOKBOOK_DIR']
|
91
|
+
chef.add_recipe 'vagrant'
|
92
|
+
chef.add_recipe 'nerve'
|
93
|
+
end
|
94
|
+
|
95
|
+
# Enable provisioning with chef server, specifying the chef server URL,
|
96
|
+
# and the path to the validation key (relative to this Vagrantfile).
|
97
|
+
#
|
98
|
+
# The Opscode Platform uses HTTPS. Substitute your organization for
|
99
|
+
# ORGNAME in the URL and validation key.
|
100
|
+
#
|
101
|
+
# If you have your own Chef Server, use the appropriate URL, which may be
|
102
|
+
# HTTP instead of HTTPS depending on your configuration. Also change the
|
103
|
+
# validation key to validation.pem.
|
104
|
+
#
|
105
|
+
# config.vm.provision :chef_client do |chef|
|
106
|
+
# chef.chef_server_url = "https://api.opscode.com/organizations/ORGNAME"
|
107
|
+
# chef.validation_key_path = "ORGNAME-validator.pem"
|
108
|
+
# end
|
109
|
+
#
|
110
|
+
# If you're using the Opscode platform, your validator client is
|
111
|
+
# ORGNAME-validator, replacing ORGNAME with your organization name.
|
112
|
+
#
|
113
|
+
# IF you have your own Chef Server, the default validation client name is
|
114
|
+
# chef-validator, unless you changed the configuration.
|
115
|
+
#
|
116
|
+
# chef.validation_client_name = "ORGNAME-validator"
|
117
|
+
|
118
|
+
# Vagrant::Config.run do |config|
|
119
|
+
# config.vm.provision :shell, :path => "vagrant/init.sh"
|
120
|
+
# end
|
121
|
+
end
|
data/bin/nerve
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'yaml'
|
4
|
+
require 'optparse'
|
5
|
+
|
6
|
+
require 'nerve'
|
7
|
+
require 'nerve/configuration_manager'
|
8
|
+
|
9
|
+
# Parse command line options and parse configuration
|
10
|
+
config_manager = Nerve::ConfigurationManager.new()
|
11
|
+
config_manager.parse_options!
|
12
|
+
|
13
|
+
nerve_application = Nerve::Nerve.new(config_manager)
|
14
|
+
nerve_application.run
|
15
|
+
|
16
|
+
puts "exiting nerve"
|
@@ -0,0 +1,54 @@
|
|
1
|
+
{
|
2
|
+
"instance_id": "mymachine",
|
3
|
+
"service_conf_dir": "example/nerve_services",
|
4
|
+
"services": {
|
5
|
+
"your_http_service": {
|
6
|
+
"host": "1.2.3.4",
|
7
|
+
"port": 3000,
|
8
|
+
"reporter_type": "zookeeper",
|
9
|
+
"zk_hosts": ["localhost:2181"],
|
10
|
+
"zk_path": "/nerve/services/your_http_service/services",
|
11
|
+
"check_interval": 2,
|
12
|
+
"checks": [
|
13
|
+
{
|
14
|
+
"type": "http",
|
15
|
+
"uri": "/health",
|
16
|
+
"timeout": 0.2,
|
17
|
+
"rise": 3,
|
18
|
+
"fall": 2
|
19
|
+
}
|
20
|
+
]
|
21
|
+
},
|
22
|
+
"your_tcp_service": {
|
23
|
+
"host": "1.2.3.4",
|
24
|
+
"port": 6379,
|
25
|
+
"reporter_type": "zookeeper",
|
26
|
+
"zk_hosts": ["localhost:2181"],
|
27
|
+
"zk_path": "/nerve/services/your_tcp_service/services",
|
28
|
+
"check_interval": 2,
|
29
|
+
"checks": [
|
30
|
+
{
|
31
|
+
"type": "tcp",
|
32
|
+
"timeout": 0.2,
|
33
|
+
"rise": 3,
|
34
|
+
"fall": 2
|
35
|
+
}
|
36
|
+
]
|
37
|
+
},
|
38
|
+
"rabbitmq_service": {
|
39
|
+
"host": "1.2.3.4",
|
40
|
+
"port": 5672,
|
41
|
+
"reporter_type": "zookeeper",
|
42
|
+
"zk_hosts": ["localhost:2181"],
|
43
|
+
"zk_path": "/nerve/services/your_rabbitmq_service/services",
|
44
|
+
"check_interval": 2,
|
45
|
+
"checks": [
|
46
|
+
{
|
47
|
+
"type": "rabbitmq",
|
48
|
+
"username": "guest",
|
49
|
+
"password": "guest"
|
50
|
+
}
|
51
|
+
]
|
52
|
+
}
|
53
|
+
}
|
54
|
+
}
|
@@ -0,0 +1,19 @@
|
|
1
|
+
{
|
2
|
+
"host": "1.2.3.4",
|
3
|
+
"port": 3000,
|
4
|
+
"reporter_type": "etcd",
|
5
|
+
"etcd_host": "localhost",
|
6
|
+
"etcd_port": 4001,
|
7
|
+
"etcd_path": "/nerve/services/your_http_service/services",
|
8
|
+
"check_interval": 2,
|
9
|
+
"weight": 2,
|
10
|
+
"checks": [
|
11
|
+
{
|
12
|
+
"type": "http",
|
13
|
+
"uri": "/health",
|
14
|
+
"timeout": 0.2,
|
15
|
+
"rise": 3,
|
16
|
+
"fall": 2
|
17
|
+
}
|
18
|
+
]
|
19
|
+
}
|
@@ -0,0 +1,18 @@
|
|
1
|
+
{
|
2
|
+
"host": "1.2.3.4",
|
3
|
+
"port": 3000,
|
4
|
+
"reporter_type": "zookeeper",
|
5
|
+
"zk_hosts": ["localhost:2181"],
|
6
|
+
"zk_path": "/nerve/services/your_http_service/services",
|
7
|
+
"check_interval": 2,
|
8
|
+
"weight": 2,
|
9
|
+
"checks": [
|
10
|
+
{
|
11
|
+
"type": "http",
|
12
|
+
"uri": "/health",
|
13
|
+
"timeout": 0.2,
|
14
|
+
"rise": 3,
|
15
|
+
"fall": 2
|
16
|
+
}
|
17
|
+
]
|
18
|
+
}
|
@@ -0,0 +1,106 @@
|
|
1
|
+
require 'yaml'
|
2
|
+
require 'optparse'
|
3
|
+
require 'nerve/log'
|
4
|
+
require 'logger'
|
5
|
+
|
6
|
+
|
7
|
+
module Nerve
|
8
|
+
class ConfigurationManager
|
9
|
+
include Logging
|
10
|
+
|
11
|
+
attr_reader :options
|
12
|
+
attr_reader :config
|
13
|
+
|
14
|
+
def parse_options_from_argv!
|
15
|
+
options = {}
|
16
|
+
# set command line options
|
17
|
+
optparse = OptionParser.new do |opts|
|
18
|
+
opts.banner =<<EOB
|
19
|
+
Welcome to nerve
|
20
|
+
|
21
|
+
Usage: nerve --config /path/to/nerve/config
|
22
|
+
EOB
|
23
|
+
|
24
|
+
options[:config] = ENV['NERVE_CONFIG']
|
25
|
+
opts.on('-c config','--config config', String, 'path to nerve config') do |key,value|
|
26
|
+
options[:config] = key
|
27
|
+
end
|
28
|
+
|
29
|
+
options[:instance_id] = ENV['NERVE_INSTANCE_ID']
|
30
|
+
opts.on('-i instance_id','--instance_id instance_id', String,
|
31
|
+
'reported as `name` to ZK; overrides instance id from config file') do |key,value|
|
32
|
+
options[:instance_id] = key
|
33
|
+
end
|
34
|
+
|
35
|
+
options[:check_config] = ENV['NERVE_CHECK_CONFIG']
|
36
|
+
opts.on('-k', '--check-config',
|
37
|
+
'Validate the nerve config ONLY and exit 0 if valid (non zero otherwise)') do |_|
|
38
|
+
options[:check_config] = true
|
39
|
+
end
|
40
|
+
|
41
|
+
opts.on('-h', '--help', 'Display this screen') do
|
42
|
+
puts opts
|
43
|
+
exit
|
44
|
+
end
|
45
|
+
end
|
46
|
+
optparse.parse!
|
47
|
+
options.each do|key, value|
|
48
|
+
log.info key
|
49
|
+
log.info value
|
50
|
+
end
|
51
|
+
options
|
52
|
+
end
|
53
|
+
|
54
|
+
def parse_options!
|
55
|
+
@options = parse_options_from_argv!
|
56
|
+
end
|
57
|
+
|
58
|
+
def generate_nerve_config(options)
|
59
|
+
|
60
|
+
config = parse_config_file(options[:config])
|
61
|
+
config['services'] ||= {}
|
62
|
+
|
63
|
+
if config.has_key?('service_conf_dir')
|
64
|
+
cdir = File.expand_path(config['service_conf_dir'])
|
65
|
+
if ! Dir.exists?(cdir) then
|
66
|
+
raise "service conf dir does not exist:#{cdir}"
|
67
|
+
end
|
68
|
+
cfiles = Dir.glob(File.join(cdir, '*.{yaml,json}'))
|
69
|
+
cfiles.each { |x| config['services'][File.basename(x[/(.*)\.(yaml|json)$/, 1])] = parse_config_file(x) }
|
70
|
+
end
|
71
|
+
|
72
|
+
if options[:instance_id] && !options[:instance_id].empty?
|
73
|
+
config['instance_id'] = options[:instance_id]
|
74
|
+
end
|
75
|
+
|
76
|
+
config
|
77
|
+
end
|
78
|
+
|
79
|
+
def parse_config_file(filename)
|
80
|
+
# parse nerve config file
|
81
|
+
begin
|
82
|
+
c = YAML::parse(File.read(filename))
|
83
|
+
rescue Errno::ENOENT => e
|
84
|
+
raise ArgumentError, "config file does not exist:\n#{e.inspect}"
|
85
|
+
rescue Errno::EACCES => e
|
86
|
+
raise ArgumentError, "could not open config file:\n#{e.inspect}"
|
87
|
+
rescue YAML::SyntaxError => e
|
88
|
+
raise "config file #{filename} is not proper yaml:\n#{e.inspect}"
|
89
|
+
end
|
90
|
+
return c.to_ruby
|
91
|
+
end
|
92
|
+
|
93
|
+
def reload!
|
94
|
+
raise "You must parse command line options before reloading config" if @options.nil?
|
95
|
+
@config = generate_nerve_config(@options)
|
96
|
+
end
|
97
|
+
|
98
|
+
def setConfig(configuration)
|
99
|
+
@config = configuration
|
100
|
+
@options = {}
|
101
|
+
@options[:check_config]=false
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
|
data/lib/nerve/log.rb
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
module Nerve
|
2
|
+
module Logging
|
3
|
+
|
4
|
+
def log
|
5
|
+
@logger ||= Logging.logger_for(self.class.name)
|
6
|
+
end
|
7
|
+
|
8
|
+
# Use a hash class-ivar to cache a unique Logger per class:
|
9
|
+
@loggers = {}
|
10
|
+
|
11
|
+
class << self
|
12
|
+
def logger_for(classname)
|
13
|
+
@loggers[classname] ||= configure_logger_for(classname)
|
14
|
+
end
|
15
|
+
|
16
|
+
def configure_logger_for(classname)
|
17
|
+
logger = Logger.new(STDERR)
|
18
|
+
logger.level = Logger::INFO unless ENV['DEBUG']
|
19
|
+
logger.progname = classname
|
20
|
+
return logger
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|