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.
Files changed (74) hide show
  1. checksums.yaml +7 -0
  2. data/.document +4 -0
  3. data/.simplecov +9 -0
  4. data/ChangeLog +417 -0
  5. data/Events.md +20 -0
  6. data/History.md +4 -0
  7. data/LICENSE +29 -0
  8. data/Manifest.txt +72 -0
  9. data/Monitors.md +141 -0
  10. data/Nodes.md +0 -0
  11. data/Observers.md +72 -0
  12. data/Protocol.md +214 -0
  13. data/README.md +75 -0
  14. data/Rakefile +81 -0
  15. data/TODO.md +24 -0
  16. data/bin/amanagerd +10 -0
  17. data/bin/amonitord +12 -0
  18. data/bin/aobserverd +12 -0
  19. data/lib/arborist.rb +182 -0
  20. data/lib/arborist/client.rb +191 -0
  21. data/lib/arborist/event.rb +61 -0
  22. data/lib/arborist/event/node_acked.rb +18 -0
  23. data/lib/arborist/event/node_delta.rb +20 -0
  24. data/lib/arborist/event/node_matching.rb +34 -0
  25. data/lib/arborist/event/node_update.rb +19 -0
  26. data/lib/arborist/event/sys_reloaded.rb +15 -0
  27. data/lib/arborist/exceptions.rb +21 -0
  28. data/lib/arborist/manager.rb +508 -0
  29. data/lib/arborist/manager/event_publisher.rb +97 -0
  30. data/lib/arborist/manager/tree_api.rb +207 -0
  31. data/lib/arborist/mixins.rb +363 -0
  32. data/lib/arborist/monitor.rb +377 -0
  33. data/lib/arborist/monitor/socket.rb +163 -0
  34. data/lib/arborist/monitor_runner.rb +217 -0
  35. data/lib/arborist/node.rb +700 -0
  36. data/lib/arborist/node/host.rb +87 -0
  37. data/lib/arborist/node/root.rb +60 -0
  38. data/lib/arborist/node/service.rb +112 -0
  39. data/lib/arborist/observer.rb +176 -0
  40. data/lib/arborist/observer/action.rb +125 -0
  41. data/lib/arborist/observer/summarize.rb +105 -0
  42. data/lib/arborist/observer_runner.rb +181 -0
  43. data/lib/arborist/subscription.rb +82 -0
  44. data/spec/arborist/client_spec.rb +282 -0
  45. data/spec/arborist/event/node_update_spec.rb +71 -0
  46. data/spec/arborist/event_spec.rb +64 -0
  47. data/spec/arborist/manager/event_publisher_spec.rb +66 -0
  48. data/spec/arborist/manager/tree_api_spec.rb +458 -0
  49. data/spec/arborist/manager_spec.rb +442 -0
  50. data/spec/arborist/mixins_spec.rb +195 -0
  51. data/spec/arborist/monitor/socket_spec.rb +195 -0
  52. data/spec/arborist/monitor_runner_spec.rb +152 -0
  53. data/spec/arborist/monitor_spec.rb +251 -0
  54. data/spec/arborist/node/host_spec.rb +104 -0
  55. data/spec/arborist/node/root_spec.rb +29 -0
  56. data/spec/arborist/node/service_spec.rb +98 -0
  57. data/spec/arborist/node_spec.rb +552 -0
  58. data/spec/arborist/observer/action_spec.rb +205 -0
  59. data/spec/arborist/observer/summarize_spec.rb +294 -0
  60. data/spec/arborist/observer_spec.rb +146 -0
  61. data/spec/arborist/subscription_spec.rb +71 -0
  62. data/spec/arborist_spec.rb +146 -0
  63. data/spec/data/monitors/pings.rb +80 -0
  64. data/spec/data/monitors/port_checks.rb +27 -0
  65. data/spec/data/monitors/system_resources.rb +30 -0
  66. data/spec/data/monitors/web_services.rb +17 -0
  67. data/spec/data/nodes/duir.rb +20 -0
  68. data/spec/data/nodes/localhost.rb +15 -0
  69. data/spec/data/nodes/sidonie.rb +29 -0
  70. data/spec/data/nodes/yevaud.rb +26 -0
  71. data/spec/data/observers/auditor.rb +23 -0
  72. data/spec/data/observers/webservices.rb +18 -0
  73. data/spec/spec_helper.rb +117 -0
  74. metadata +368 -0
@@ -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
+
@@ -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.
@@ -0,0 +1,10 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'arborist'
4
+ require 'arborist/manager'
5
+
6
+ $0 = "Arborist::Manager"
7
+
8
+ Arborist.load_config( ARGV.pop )
9
+ mgr = Arborist.manager_for( ARGV.shift )
10
+ mgr.run
@@ -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
@@ -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
@@ -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