arborist 0.0.1.pre20160106113421
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/.document +4 -0
- data/.simplecov +9 -0
- data/ChangeLog +417 -0
- data/Events.md +20 -0
- data/History.md +4 -0
- data/LICENSE +29 -0
- data/Manifest.txt +72 -0
- data/Monitors.md +141 -0
- data/Nodes.md +0 -0
- data/Observers.md +72 -0
- data/Protocol.md +214 -0
- data/README.md +75 -0
- data/Rakefile +81 -0
- data/TODO.md +24 -0
- data/bin/amanagerd +10 -0
- data/bin/amonitord +12 -0
- data/bin/aobserverd +12 -0
- data/lib/arborist.rb +182 -0
- data/lib/arborist/client.rb +191 -0
- data/lib/arborist/event.rb +61 -0
- data/lib/arborist/event/node_acked.rb +18 -0
- data/lib/arborist/event/node_delta.rb +20 -0
- data/lib/arborist/event/node_matching.rb +34 -0
- data/lib/arborist/event/node_update.rb +19 -0
- data/lib/arborist/event/sys_reloaded.rb +15 -0
- data/lib/arborist/exceptions.rb +21 -0
- data/lib/arborist/manager.rb +508 -0
- data/lib/arborist/manager/event_publisher.rb +97 -0
- data/lib/arborist/manager/tree_api.rb +207 -0
- data/lib/arborist/mixins.rb +363 -0
- data/lib/arborist/monitor.rb +377 -0
- data/lib/arborist/monitor/socket.rb +163 -0
- data/lib/arborist/monitor_runner.rb +217 -0
- data/lib/arborist/node.rb +700 -0
- data/lib/arborist/node/host.rb +87 -0
- data/lib/arborist/node/root.rb +60 -0
- data/lib/arborist/node/service.rb +112 -0
- data/lib/arborist/observer.rb +176 -0
- data/lib/arborist/observer/action.rb +125 -0
- data/lib/arborist/observer/summarize.rb +105 -0
- data/lib/arborist/observer_runner.rb +181 -0
- data/lib/arborist/subscription.rb +82 -0
- data/spec/arborist/client_spec.rb +282 -0
- data/spec/arborist/event/node_update_spec.rb +71 -0
- data/spec/arborist/event_spec.rb +64 -0
- data/spec/arborist/manager/event_publisher_spec.rb +66 -0
- data/spec/arborist/manager/tree_api_spec.rb +458 -0
- data/spec/arborist/manager_spec.rb +442 -0
- data/spec/arborist/mixins_spec.rb +195 -0
- data/spec/arborist/monitor/socket_spec.rb +195 -0
- data/spec/arborist/monitor_runner_spec.rb +152 -0
- data/spec/arborist/monitor_spec.rb +251 -0
- data/spec/arborist/node/host_spec.rb +104 -0
- data/spec/arborist/node/root_spec.rb +29 -0
- data/spec/arborist/node/service_spec.rb +98 -0
- data/spec/arborist/node_spec.rb +552 -0
- data/spec/arborist/observer/action_spec.rb +205 -0
- data/spec/arborist/observer/summarize_spec.rb +294 -0
- data/spec/arborist/observer_spec.rb +146 -0
- data/spec/arborist/subscription_spec.rb +71 -0
- data/spec/arborist_spec.rb +146 -0
- data/spec/data/monitors/pings.rb +80 -0
- data/spec/data/monitors/port_checks.rb +27 -0
- data/spec/data/monitors/system_resources.rb +30 -0
- data/spec/data/monitors/web_services.rb +17 -0
- data/spec/data/nodes/duir.rb +20 -0
- data/spec/data/nodes/localhost.rb +15 -0
- data/spec/data/nodes/sidonie.rb +29 -0
- data/spec/data/nodes/yevaud.rb +26 -0
- data/spec/data/observers/auditor.rb +23 -0
- data/spec/data/observers/webservices.rb +18 -0
- data/spec/spec_helper.rb +117 -0
- metadata +368 -0
data/README.md
ADDED
@@ -0,0 +1,75 @@
|
|
1
|
+
# Arborist
|
2
|
+
|
3
|
+
home :: http://deveiate.org/projects/Arborist
|
4
|
+
code :: http://bitbucket.org/ged/Arborist
|
5
|
+
github :: https://github.com/ged/arborist
|
6
|
+
docs :: http://deveiate.org/code/arborist
|
7
|
+
|
8
|
+
|
9
|
+
## Description
|
10
|
+
|
11
|
+
Arborist is a monitoring framework that follows the UNIX philosophy
|
12
|
+
of small parts and loose coupling for stability, reliability, and
|
13
|
+
customizability.
|
14
|
+
|
15
|
+
|
16
|
+
## Prerequisites
|
17
|
+
|
18
|
+
* Ruby 2.2 or better
|
19
|
+
|
20
|
+
|
21
|
+
## Installation
|
22
|
+
|
23
|
+
$ gem install arborist
|
24
|
+
|
25
|
+
|
26
|
+
## Further Reading
|
27
|
+
|
28
|
+
You'll likely want to start with [the Tutorial](Tutorial.html).
|
29
|
+
|
30
|
+
|
31
|
+
## Contributing
|
32
|
+
|
33
|
+
You can check out the current development source with Mercurial via its
|
34
|
+
[project page](http://bitbucket.org/ged/Arborist). Or if you prefer Git, via
|
35
|
+
[its Github mirror](https://github.com/ged/arborist).
|
36
|
+
|
37
|
+
After checking out the source, run:
|
38
|
+
|
39
|
+
$ rake newb
|
40
|
+
|
41
|
+
This task will install any missing dependencies, run the tests/specs,
|
42
|
+
and generate the API documentation.
|
43
|
+
|
44
|
+
|
45
|
+
## License
|
46
|
+
|
47
|
+
Copyright (c) 2015, Michael Granger and Mahlon E. Smith
|
48
|
+
All rights reserved.
|
49
|
+
|
50
|
+
Redistribution and use in source and binary forms, with or without
|
51
|
+
modification, are permitted provided that the following conditions are met:
|
52
|
+
|
53
|
+
* Redistributions of source code must retain the above copyright notice,
|
54
|
+
this list of conditions and the following disclaimer.
|
55
|
+
|
56
|
+
* Redistributions in binary form must reproduce the above copyright notice,
|
57
|
+
this list of conditions and the following disclaimer in the documentation
|
58
|
+
and/or other materials provided with the distribution.
|
59
|
+
|
60
|
+
* Neither the name of the author/s, nor the names of the project's
|
61
|
+
contributors may be used to endorse or promote products derived from this
|
62
|
+
software without specific prior written permission.
|
63
|
+
|
64
|
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
65
|
+
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
66
|
+
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
67
|
+
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
|
68
|
+
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
69
|
+
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
70
|
+
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
71
|
+
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
72
|
+
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
73
|
+
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
74
|
+
|
75
|
+
|
data/Rakefile
ADDED
@@ -0,0 +1,81 @@
|
|
1
|
+
#!/usr/bin/env rake
|
2
|
+
|
3
|
+
begin
|
4
|
+
require 'hoe'
|
5
|
+
rescue LoadError
|
6
|
+
abort "This Rakefile requires hoe (gem install hoe)"
|
7
|
+
end
|
8
|
+
|
9
|
+
GEMSPEC = 'arborist.gemspec'
|
10
|
+
|
11
|
+
|
12
|
+
Hoe.plugin :mercurial
|
13
|
+
Hoe.plugin :signing
|
14
|
+
Hoe.plugin :deveiate
|
15
|
+
|
16
|
+
Hoe.plugins.delete :rubyforge
|
17
|
+
Hoe.plugins.delete :gemcutter
|
18
|
+
|
19
|
+
hoespec = Hoe.spec 'arborist' do |spec|
|
20
|
+
spec.readme_file = 'README.md'
|
21
|
+
spec.history_file = 'History.md'
|
22
|
+
spec.extra_rdoc_files = FileList[ '*.rdoc', '*.md' ]
|
23
|
+
self.license 'BSD-3-Clause'
|
24
|
+
spec.urls = {
|
25
|
+
home: 'http://deveiate.org/projects/arborist',
|
26
|
+
code: 'http://bitbucket.org/ged/arborist',
|
27
|
+
docs: 'http://deveiate.org/code/arborist',
|
28
|
+
github: 'http://github.com/ged/arborist',
|
29
|
+
}
|
30
|
+
|
31
|
+
spec.developer 'Michael Granger', 'ged@FaerieMUD.org'
|
32
|
+
spec.developer 'Mahlon E. Smith', 'mahlon@martini.nu'
|
33
|
+
|
34
|
+
spec.dependency 'schedulability', '~> 0.1'
|
35
|
+
spec.dependency 'loggability', '~> 0.11'
|
36
|
+
spec.dependency 'configurability', '~> 2.2'
|
37
|
+
spec.dependency 'pluggability', '~> 0.4'
|
38
|
+
spec.dependency 'state_machines', '~> 0.2'
|
39
|
+
spec.dependency 'msgpack', '~> 0.6'
|
40
|
+
spec.dependency 'rbczmq', '~> 1.7'
|
41
|
+
|
42
|
+
spec.dependency 'rspec', '~> 3.2', :developer
|
43
|
+
spec.dependency 'simplecov', '~> 0.9', :developer
|
44
|
+
spec.dependency 'timecop', '~> 0.7', :developer
|
45
|
+
|
46
|
+
spec.require_ruby_version( '>=2.2.0' )
|
47
|
+
spec.hg_sign_tags = true if spec.respond_to?( :hg_sign_tags= )
|
48
|
+
|
49
|
+
self.rdoc_locations << "deveiate:/usr/local/www/public/code/#{remote_rdoc_dir}"
|
50
|
+
end
|
51
|
+
|
52
|
+
|
53
|
+
ENV['VERSION'] ||= hoespec.spec.version.to_s
|
54
|
+
|
55
|
+
# Run the tests before checking in
|
56
|
+
task 'hg:precheckin' => [ :check_history, :check_manifest, :gemspec, :spec ]
|
57
|
+
|
58
|
+
# Rebuild the ChangeLog immediately before release
|
59
|
+
task :prerelease => 'ChangeLog'
|
60
|
+
CLOBBER.include( 'ChangeLog' )
|
61
|
+
|
62
|
+
desc "Build a coverage report"
|
63
|
+
task :coverage do
|
64
|
+
ENV["COVERAGE"] = 'yes'
|
65
|
+
Rake::Task[:spec].invoke
|
66
|
+
end
|
67
|
+
|
68
|
+
|
69
|
+
task :gemspec => GEMSPEC
|
70
|
+
file GEMSPEC => __FILE__ do |task|
|
71
|
+
spec = $hoespec.spec
|
72
|
+
spec.files.delete( '.gemtest' )
|
73
|
+
spec.signing_key = nil
|
74
|
+
spec.version = "#{spec.version}.pre#{Time.now.strftime("%Y%m%d%H%M%S")}"
|
75
|
+
File.open( task.name, 'w' ) do |fh|
|
76
|
+
fh.write( spec.to_ruby )
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
task :default => :gemspec
|
81
|
+
|
data/TODO.md
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
# To-Do
|
2
|
+
|
3
|
+
## Manager
|
4
|
+
|
5
|
+
* Serialize nodes on shutdown
|
6
|
+
* Include a node's subscriptions in its serialized data
|
7
|
+
* Implement loading/reloading nodes.
|
8
|
+
|
9
|
+
## Tree API
|
10
|
+
|
11
|
+
* Add "grafting": node add/removal
|
12
|
+
|
13
|
+
## Observers
|
14
|
+
|
15
|
+
* Scheduling time periods for action/summarizing
|
16
|
+
* Summarizing and Actions should be 1st order objects
|
17
|
+
* Unsubscribe from Arborist and ZMQ subscriptions on shutdown
|
18
|
+
* Figure out how to match on delta events: the criteria
|
19
|
+
for matching nodes has to be separated from that which matches
|
20
|
+
the delta pairs.
|
21
|
+
|
22
|
+
## Node
|
23
|
+
|
24
|
+
* Add a 'disabled' state, can be set on 'up' nodes by acking them.
|
data/bin/amanagerd
ADDED
data/bin/amonitord
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'arborist'
|
4
|
+
require 'arborist/monitor_runner'
|
5
|
+
|
6
|
+
monitors_path = ARGV.shift or raise "No monitor file specified."
|
7
|
+
|
8
|
+
Arborist.load_config( ARGV.shift )
|
9
|
+
Arborist.load_all
|
10
|
+
|
11
|
+
runner = Arborist.monitor_runner_for( monitors_path )
|
12
|
+
runner.run
|
data/bin/aobserverd
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'arborist'
|
4
|
+
require 'arborist/observer_runner'
|
5
|
+
|
6
|
+
observers_path = ARGV.shift or raise "No observer file specified."
|
7
|
+
|
8
|
+
Arborist.load_config( ARGV.shift )
|
9
|
+
Arborist.load_all
|
10
|
+
|
11
|
+
runner = Arborist.observer_runner_for( observers_path )
|
12
|
+
runner.run
|
data/lib/arborist.rb
ADDED
@@ -0,0 +1,182 @@
|
|
1
|
+
# -*- ruby -*-
|
2
|
+
#encoding: utf-8
|
3
|
+
|
4
|
+
require 'rbczmq'
|
5
|
+
|
6
|
+
require 'pathname'
|
7
|
+
require 'configurability'
|
8
|
+
require 'loggability'
|
9
|
+
|
10
|
+
|
11
|
+
# Arborist namespace
|
12
|
+
module Arborist
|
13
|
+
extend Loggability,
|
14
|
+
Configurability
|
15
|
+
|
16
|
+
# Package version
|
17
|
+
VERSION = '0.0.1'
|
18
|
+
|
19
|
+
# Version control revision
|
20
|
+
REVISION = %q$Revision: fddcbace9b6d $
|
21
|
+
|
22
|
+
|
23
|
+
# The name of the environment variable which can be used to set the config path
|
24
|
+
CONFIG_ENV = 'ARBORIST_CONFIG'
|
25
|
+
|
26
|
+
# The name of the config file for local overrides.
|
27
|
+
LOCAL_CONFIG_FILE = Pathname( '~/.arborist.yml' ).expand_path
|
28
|
+
|
29
|
+
# The name of the config file that's loaded if none is specified.
|
30
|
+
DEFAULT_CONFIG_FILE = Pathname( 'arborist.yml' ).expand_path
|
31
|
+
|
32
|
+
# Configurability API -- default configuration values
|
33
|
+
CONFIG_DEFAULTS = {
|
34
|
+
tree_api_url: 'ipc:///tmp/arborist_tree.sock',
|
35
|
+
event_api_url: 'ipc:///tmp/arborist_events.sock'
|
36
|
+
}
|
37
|
+
|
38
|
+
|
39
|
+
##
|
40
|
+
# Set up a logger for the Arborist namespace
|
41
|
+
log_as :arborist
|
42
|
+
|
43
|
+
# Configurability API -- use the 'arborist'
|
44
|
+
config_key :arborist
|
45
|
+
|
46
|
+
|
47
|
+
require 'arborist/mixins'
|
48
|
+
extend Arborist::MethodUtilities
|
49
|
+
|
50
|
+
|
51
|
+
##
|
52
|
+
# The ZMQ REP socket for the API for accessing the node tree.
|
53
|
+
singleton_attr_accessor :tree_api_url
|
54
|
+
@tree_api_url = CONFIG_DEFAULTS[ :tree_api_url ]
|
55
|
+
|
56
|
+
##
|
57
|
+
# The ZMQ PUB socket for published events
|
58
|
+
singleton_attr_accessor :event_api_url
|
59
|
+
@event_api_url = CONFIG_DEFAULTS[ :event_api_url ]
|
60
|
+
|
61
|
+
|
62
|
+
#
|
63
|
+
# :section: Configuration API
|
64
|
+
#
|
65
|
+
|
66
|
+
### Configurability API.
|
67
|
+
def self::configure( config=nil )
|
68
|
+
config = self.defaults.merge( config || {} )
|
69
|
+
|
70
|
+
self.tree_api_url = config[ :tree_api_url ]
|
71
|
+
self.event_api_url = config[ :event_api_url ]
|
72
|
+
end
|
73
|
+
|
74
|
+
|
75
|
+
### Get the loaded config (a Configurability::Config object)
|
76
|
+
def self::config
|
77
|
+
Configurability.loaded_config
|
78
|
+
end
|
79
|
+
|
80
|
+
|
81
|
+
### Returns +true+ if the configuration has been loaded at least once.
|
82
|
+
def self::config_loaded?
|
83
|
+
return self.config ? true : false
|
84
|
+
end
|
85
|
+
|
86
|
+
|
87
|
+
### Load the specified +config_file+, install the config in all objects with
|
88
|
+
### Configurability, and call any callbacks registered via #after_configure.
|
89
|
+
def self::load_config( config_file=nil, defaults=nil )
|
90
|
+
config_file ||= ENV[ CONFIG_ENV ]
|
91
|
+
config_file ||= LOCAL_CONFIG_FILE if LOCAL_CONFIG_FILE.exist?
|
92
|
+
config_file ||= DEFAULT_CONFIG_FILE
|
93
|
+
|
94
|
+
defaults ||= Configurability.gather_defaults
|
95
|
+
|
96
|
+
self.log.info "Loading config from %p with defaults for sections: %p." %
|
97
|
+
[ config_file, defaults.keys ]
|
98
|
+
config = Configurability::Config.load( config_file, defaults )
|
99
|
+
|
100
|
+
config.install
|
101
|
+
end
|
102
|
+
|
103
|
+
|
104
|
+
### Add a constructor function to the Arborist namespace called +name+
|
105
|
+
### with the specified +method_body+.
|
106
|
+
def self::add_dsl_constructor( name, &method_body )
|
107
|
+
self.log.debug "Adding constructor for %p: %p" % [ name, method_body ]
|
108
|
+
singleton_class.instance_exec( name, method_body ) do |name, body|
|
109
|
+
define_method( name, &body )
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
|
114
|
+
### Return a new Arborist::Manager for the nodes described in files under
|
115
|
+
### the specified +directory+.
|
116
|
+
def self::manager_for( directory )
|
117
|
+
self.load_all
|
118
|
+
nodes = Arborist::Node.each_in( directory )
|
119
|
+
manager = Arborist::Manager.new
|
120
|
+
manager.load_tree( nodes )
|
121
|
+
|
122
|
+
return manager
|
123
|
+
end
|
124
|
+
|
125
|
+
|
126
|
+
### Return a new Arborist::MonitorRunner for the monitors described in files under
|
127
|
+
### the specified +directory+.
|
128
|
+
def self::monitor_runner_for( directory )
|
129
|
+
self.load_all
|
130
|
+
monitors = Arborist::Monitor.each_in( directory )
|
131
|
+
runner = Arborist::MonitorRunner.new
|
132
|
+
runner.load_monitors( monitors )
|
133
|
+
|
134
|
+
return runner
|
135
|
+
end
|
136
|
+
|
137
|
+
|
138
|
+
### Return a new Arborist::ObserverRunner for the observers described in files under
|
139
|
+
### the specified +directory+.
|
140
|
+
def self::observer_runner_for( directory )
|
141
|
+
self.load_all
|
142
|
+
observers = Arborist::Observer.each_in( directory )
|
143
|
+
runner = Arborist::ObserverRunner.new
|
144
|
+
runner.load_observers( observers )
|
145
|
+
|
146
|
+
return runner
|
147
|
+
end
|
148
|
+
|
149
|
+
|
150
|
+
### Load all node and event types
|
151
|
+
def self::load_all
|
152
|
+
Arborist::Node.load_all
|
153
|
+
end
|
154
|
+
|
155
|
+
|
156
|
+
### Destroy any existing ZMQ state.
|
157
|
+
def self::reset_zmq_context
|
158
|
+
@zmq_context.destroy if @zmq_context.respond_to?( :destroy )
|
159
|
+
@zmq_context = nil
|
160
|
+
end
|
161
|
+
|
162
|
+
|
163
|
+
### Fetch the ZMQ context for Arborist.
|
164
|
+
def self::zmq_context
|
165
|
+
return @zmq_context ||= ZMQ::Context.new
|
166
|
+
end
|
167
|
+
|
168
|
+
|
169
|
+
require 'arborist/exceptions'
|
170
|
+
require 'arborist/mixins'
|
171
|
+
|
172
|
+
autoload :Client, 'arborist/client'
|
173
|
+
autoload :Event, 'arborist/event'
|
174
|
+
autoload :Manager, 'arborist/manager'
|
175
|
+
autoload :Monitor, 'arborist/monitor'
|
176
|
+
autoload :MonitorRunner, 'arborist/monitor_runner'
|
177
|
+
autoload :Node, 'arborist/node'
|
178
|
+
autoload :Observer, 'arborist/observer'
|
179
|
+
autoload :Subscription, 'arborist/subscription'
|
180
|
+
|
181
|
+
end # module Arborist
|
182
|
+
|
@@ -0,0 +1,191 @@
|
|
1
|
+
# -*- ruby -*-
|
2
|
+
#encoding: utf-8
|
3
|
+
|
4
|
+
require 'arborist' unless defined?( Arborist )
|
5
|
+
require 'msgpack'
|
6
|
+
|
7
|
+
|
8
|
+
# Unified Arborist Manager client for both the Tree and Event APIs
|
9
|
+
class Arborist::Client
|
10
|
+
extend Loggability
|
11
|
+
|
12
|
+
# The version of the client.
|
13
|
+
API_VERSION = 1
|
14
|
+
|
15
|
+
# Loggability API -- log to the Arborist log host
|
16
|
+
log_to :arborist
|
17
|
+
|
18
|
+
|
19
|
+
### Create a new Client with the given API socket URIs.
|
20
|
+
def initialize( tree_api_url: nil, event_api_url: nil )
|
21
|
+
@tree_api_url = tree_api_url || Arborist.tree_api_url
|
22
|
+
@event_api_url = event_api_url || Arborist.event_api_url
|
23
|
+
|
24
|
+
@request_queue = nil
|
25
|
+
@event_subscriptions = nil
|
26
|
+
end
|
27
|
+
|
28
|
+
|
29
|
+
######
|
30
|
+
public
|
31
|
+
######
|
32
|
+
|
33
|
+
# The ZMQ URI required to speak to the Arborist tree API.
|
34
|
+
attr_accessor :tree_api_url
|
35
|
+
|
36
|
+
# The ZMQ URI required to speak to the Arborist event API.
|
37
|
+
attr_accessor :event_api_url
|
38
|
+
|
39
|
+
|
40
|
+
### Return the manager's current status as a hash.
|
41
|
+
def status
|
42
|
+
request = self.make_status_request
|
43
|
+
return self.send_tree_api_request( request )
|
44
|
+
end
|
45
|
+
|
46
|
+
|
47
|
+
### Return the manager's current status as a hash.
|
48
|
+
def make_status_request
|
49
|
+
return self.pack_message( :status )
|
50
|
+
end
|
51
|
+
|
52
|
+
|
53
|
+
### Return the manager's current node tree.
|
54
|
+
def list( *args )
|
55
|
+
request = self.make_list_request( *args )
|
56
|
+
return self.send_tree_api_request( request )
|
57
|
+
end
|
58
|
+
|
59
|
+
|
60
|
+
### Return the manager's current node tree.
|
61
|
+
def make_list_request( from: nil )
|
62
|
+
header = {}
|
63
|
+
self.log.debug "From is: %p" % [ from ]
|
64
|
+
header[:from] = from if from
|
65
|
+
|
66
|
+
return self.pack_message( :list, header )
|
67
|
+
end
|
68
|
+
|
69
|
+
|
70
|
+
### Return the manager's current node tree.
|
71
|
+
def fetch( criteria={}, *args )
|
72
|
+
request = self.make_fetch_request( criteria, *args )
|
73
|
+
return self.send_tree_api_request( request )
|
74
|
+
end
|
75
|
+
|
76
|
+
|
77
|
+
### Return the manager's current node tree.
|
78
|
+
def make_fetch_request( criteria, include_down: false, properties: :all )
|
79
|
+
header = {}
|
80
|
+
header[ :include_down ] = true if include_down
|
81
|
+
header[ :return ] = properties if properties != :all
|
82
|
+
|
83
|
+
return self.pack_message( :fetch, header, criteria )
|
84
|
+
end
|
85
|
+
|
86
|
+
|
87
|
+
### Update the identified nodes in the manager with the specified data.
|
88
|
+
def update( *args )
|
89
|
+
request = self.make_update_request( *args )
|
90
|
+
return self.send_tree_api_request( request )
|
91
|
+
end
|
92
|
+
|
93
|
+
|
94
|
+
### Update the identified nodes in the manager with the specified data.
|
95
|
+
def make_update_request( data )
|
96
|
+
return self.pack_message( :update, nil, data )
|
97
|
+
end
|
98
|
+
|
99
|
+
|
100
|
+
### Add a subscription
|
101
|
+
def subscribe( *args )
|
102
|
+
request = self.make_subscribe_request( *args )
|
103
|
+
response = self.send_tree_api_request( request )
|
104
|
+
return response.first
|
105
|
+
end
|
106
|
+
|
107
|
+
|
108
|
+
### Make a subscription request for the specified +criteria+, +identifier+, and +event_type+.
|
109
|
+
def make_subscribe_request( criteria: {}, identifier: nil, event_type: nil )
|
110
|
+
self.log.debug "Making subscription request for identifier: %p, event_type: %p, criteria: %p" %
|
111
|
+
[ identifier, event_type, criteria ]
|
112
|
+
header = {}
|
113
|
+
header[ :identifier ] = identifier if identifier
|
114
|
+
header[ :event_type ] = event_type
|
115
|
+
|
116
|
+
return self.pack_message( :subscribe, header, criteria )
|
117
|
+
end
|
118
|
+
|
119
|
+
|
120
|
+
### Send the packed +request+ via the Tree API socket, raise an error on
|
121
|
+
### unsuccessful response, and return the response body.
|
122
|
+
def send_tree_api_request( request )
|
123
|
+
self.log.debug "Sending request: %p" % [ request ]
|
124
|
+
self.tree_api.send( request )
|
125
|
+
|
126
|
+
res = self.tree_api.recv
|
127
|
+
self.log.debug "Received response: %p" % [ res ]
|
128
|
+
|
129
|
+
header, body = self.unpack_message( res )
|
130
|
+
unless header[ 'success' ]
|
131
|
+
raise "Arborist manager said: %s" % [ header['reason'] ]
|
132
|
+
end
|
133
|
+
|
134
|
+
return body
|
135
|
+
end
|
136
|
+
|
137
|
+
|
138
|
+
|
139
|
+
### Format ruby +data+ for communicating with the Arborist manager.
|
140
|
+
def pack_message( verb, *data )
|
141
|
+
header = data.shift || {}
|
142
|
+
body = data.shift
|
143
|
+
|
144
|
+
header.merge!( action: verb, version: API_VERSION )
|
145
|
+
|
146
|
+
self.log.debug "Packing message; header: %p, body: %p" % [ header, body ]
|
147
|
+
|
148
|
+
return MessagePack.pack([ header, body ])
|
149
|
+
end
|
150
|
+
|
151
|
+
|
152
|
+
### De-serialize an Arborist manager response.
|
153
|
+
def unpack_message( msg )
|
154
|
+
return MessagePack.unpack( msg )
|
155
|
+
end
|
156
|
+
|
157
|
+
|
158
|
+
### Return a ZMQ REQ socket connected to the manager's tree API, instantiating
|
159
|
+
### it if necessary.
|
160
|
+
def tree_api
|
161
|
+
return @tree_api ||= self.make_tree_api_socket
|
162
|
+
end
|
163
|
+
|
164
|
+
|
165
|
+
### Create a new ZMQ REQ socket connected to the manager's tree API.
|
166
|
+
def make_tree_api_socket
|
167
|
+
self.log.info "Connecting to the tree socket %p" % [ self.tree_api_url ]
|
168
|
+
sock = Arborist.zmq_context.socket( :REQ )
|
169
|
+
sock.connect( self.tree_api_url )
|
170
|
+
|
171
|
+
return sock
|
172
|
+
end
|
173
|
+
|
174
|
+
|
175
|
+
### Return a ZMQ SUB socket connected to the manager's event API, instantiating
|
176
|
+
### it if necessary.
|
177
|
+
def event_api
|
178
|
+
return @event_api ||= self.make_event_api_socket
|
179
|
+
end
|
180
|
+
|
181
|
+
|
182
|
+
### Create a new ZMQ SUB socket connected to the manager's event API.
|
183
|
+
def make_event_api_socket
|
184
|
+
self.log.info "Connecting to the event socket %p" % [ self.event_api_url ]
|
185
|
+
sock = Arborist.zmq_context.socket( :SUB )
|
186
|
+
sock.connect( self.event_api_url )
|
187
|
+
|
188
|
+
return sock
|
189
|
+
end
|
190
|
+
|
191
|
+
end # class Arborist::Client
|