Class: Arborist::Client

Inherits:
Object
  • Object
show all
Extended by:
Loggability
Defined in:
lib/arborist/client.rb

Overview

Unified Arborist Manager client for both the Tree and Event APIs

Constant Summary collapse

API_VERSION =

The version of the client.

1

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(tree_api_url: nil, event_api_url: nil) ⇒ Client

Create a new Client with the given API socket URIs.



29
30
31
32
# File 'lib/arborist/client.rb', line 29

def initialize( tree_api_url: nil, event_api_url: nil )
	@tree_api_url  = tree_api_url  || Arborist.tree_api_url
	@event_api_url = event_api_url || Arborist.event_api_url
end

Instance Attribute Details

#event_api_urlObject

The ZeroMQ URI required to speak to the Arborist event API.



43
44
45
# File 'lib/arborist/client.rb', line 43

def event_api_url
  @event_api_url
end

#tree_api_urlObject

The ZeroMQ URI required to speak to the Arborist tree API.



40
41
42
# File 'lib/arborist/client.rb', line 40

def tree_api_url
  @tree_api_url
end

Class Method Details

.instanceObject

Create and return a singleton instance with configured endpoints.



23
24
25
# File 'lib/arborist/client.rb', line 23

def self::instance
	return @instance ||= new
end

Instance Method Details

#acknowledge(**args) ⇒ Object Also known as: ack

Mark a node as ‘acknowledged’ if it’s down, or ‘disabled’ if it’s up. (A pre-emptive acknowledgement.) Requires the node identifier, an acknowledgement message, and sender. You can optionally include a via (source), and override the default time of now.



264
265
266
267
268
# File 'lib/arborist/client.rb', line 264

def acknowledge( **args )
	request = self.make_acknowledge_request( **args )
	self.send_tree_api_request( request )
	return true
end

#clear_acknowledgement(**args) ⇒ Object Also known as: unack, clear_ack, unacknowledge

Clear the acknowledgement for a node.



287
288
289
290
291
# File 'lib/arborist/client.rb', line 287

def clear_acknowledgement( **args )
	request = self.make_unack_request( **args )
	self.send_tree_api_request( request )
	return true
end

#dependencies_of(identifier, partition: nil, properties: :all) ⇒ Object

Return dependencies of the given identifier as an array.



52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
# File 'lib/arborist/client.rb', line 52

def dependencies_of( identifier, partition: nil, properties: :all )
	dependencies = self.deps( identifier: identifier )[ 'deps' ]
	dependencies = self.search(
		criteria: { identifier: dependencies },
		options:  { properties: properties }
	)

	if partition
		partition = partition.to_s
		dependencies.keys.each{|id| dependencies[id]['identifier'] = id }
		dependencies = dependencies.values.group_by do |node|
			node[ partition ]
		end
	end

	return dependencies
end

#deps(identifier:) ⇒ Object

Return the identifiers that have a dependency on the node with the specified identifier.



136
137
138
139
# File 'lib/arborist/client.rb', line 136

def deps( identifier: )
	request = self.make_deps_request( identifier )
	return self.send_tree_api_request( request )
end

#event_apiObject

Return a ZMQ SUB socket connected to the manager’s event API, instantiating it if necessary.



343
344
345
# File 'lib/arborist/client.rb', line 343

def event_api
	return @event_api ||= self.make_event_api_socket
end

#fetch(**args) ⇒ Object

Fetch the manager’s current node tree.



96
97
98
99
# File 'lib/arborist/client.rb', line 96

def fetch( **args )
	request = self.make_fetch_request( **args )
	return self.send_tree_api_request( request )
end

#fetch_node(identifier) ⇒ Object

Retreive a single node.



72
73
74
75
# File 'lib/arborist/client.rb', line 72

def fetch_node( identifier )
	request = self.make_fetch_request( from: identifier, depth: 0 )
	return self.send_tree_api_request( request ).first
end

#graft(**args) ⇒ Object

Add a new node to the tree.



220
221
222
223
224
# File 'lib/arborist/client.rb', line 220

def graft( **args )
	request = self.make_graft_request( **args )
	response = self.send_tree_api_request( request )
	return response
end

#make_acknowledge_request(identifier:, message:, sender:, via: nil, time: Time.now) ⇒ Object

Return an ‘ack` request as a zmq message (a CZTop::Message) with the specified attributes.



274
275
276
277
278
279
280
281
282
283
# File 'lib/arborist/client.rb', line 274

def make_acknowledge_request( identifier:, message:, sender:, via: nil, time: Time.now )
	ack = {
		message: message,
		sender:  sender,
		via:     via,
		time:    time.to_s
	}

	return Arborist::TreeAPI.request( :ack, {identifier: identifier}, ack )
end

#make_deps_request(identifier) ⇒ Object

Return a ‘deps` request as a ZMQ message (a CZTop::Message) with the given identifier.



144
145
146
# File 'lib/arborist/client.rb', line 144

def make_deps_request( identifier )
	return Arborist::TreeAPI.request( :deps, { from: identifier }, nil )
end

#make_event_api_socketObject

Create a new ZMQ SUB socket connected to the manager’s event API.



349
350
351
352
# File 'lib/arborist/client.rb', line 349

def make_event_api_socket
	self.log.info "Connecting to the event socket %p" % [ self.event_api_url ]
	return CZTop::Socket::SUB.new( self.event_api_url )
end

#make_fetch_request(from: nil, depth: nil, tree: false) ⇒ Object

Return a ‘fetch` request as a ZMQ message (a CZTop::Message) with the given attributes.



104
105
106
107
108
109
110
111
112
# File 'lib/arborist/client.rb', line 104

def make_fetch_request( from: nil, depth: nil, tree: false )
	header = {}
	self.log.debug "From is: %p" % [ from ]
	header[:from] = from if from
	header[:depth] = depth if depth
	header[:tree] = 'true' if tree

	return Arborist::TreeAPI.request( :fetch, header, nil )
end

#make_graft_request(identifier:, type:, parent: nil, attributes: {}) ⇒ Object

Return a ‘graft` request as a zmq message (a CZTop::Message) with the specified attributes.



229
230
231
232
233
234
235
236
237
238
239
# File 'lib/arborist/client.rb', line 229

def make_graft_request( identifier:, type:, parent: nil, attributes:{} )
	self.log.debug "Making graft request for identifer: %s" % [ identifier ]

	header = {
		identifier: identifier,
		parent:     parent,
		type:       type
	}

	return Arborist::TreeAPI.request( :graft, header, attributes )
end

#make_modify_request(identifier:, attributes:) ⇒ Object

Return a ‘modify` request as a zmq message (a CZTop::Message) with the specified attributes.



252
253
254
255
256
# File 'lib/arborist/client.rb', line 252

def make_modify_request( identifier:, attributes: )
	self.log.debug "Making modify request for identifer: %s" % [ identifier ]

	return Arborist::TreeAPI.request( :modify, {identifier: identifier}, attributes )
end

#make_prune_request(identifier:) ⇒ Object

Return a ‘prune` request as a zmq message (a CZTop::Message) with the specified identifier.



212
213
214
215
216
# File 'lib/arborist/client.rb', line 212

def make_prune_request( identifier: )
	self.log.debug "Making prune request for identifier: %s" % [ identifier ]

	return Arborist::TreeAPI.request( :prune, {identifier: identifier}, nil )
end

#make_search_request(criteria, exclude_down: false, properties: :all, exclude: {}) ⇒ Object

Return a ‘search` request as a ZMQ message (a CZTop::Message) with the given attributes.



125
126
127
128
129
130
131
# File 'lib/arborist/client.rb', line 125

def make_search_request( criteria, exclude_down: false, properties: :all, exclude: {} )
	header = {}
	header[ :exclude_down ] = true if exclude_down
	header[ :return ] = properties if properties != :all

	return Arborist::TreeAPI.request( :search, header, [ criteria, exclude ] )
end

#make_status_requestObject

Return a ‘status` request as a ZMQ message (a CZTop::Message).



90
91
92
# File 'lib/arborist/client.rb', line 90

def make_status_request
	return Arborist::TreeAPI.request( :status )
end

#make_subscribe_request(criteria: {}, identifier: nil, event_type: nil, exclude: {}) ⇒ Object

Return a ‘subscribe` request as a zmq message (a CZTop::Message) with the specified attributes.



174
175
176
177
178
179
180
181
182
# File 'lib/arborist/client.rb', line 174

def make_subscribe_request( criteria: {}, identifier: nil, event_type: nil, exclude: {} )
	self.log.debug "Making subscription request for identifier: %p, event_type: %p, criteria: %p" %
		[ identifier, event_type, criteria ]
	header = {}
	header[ :identifier ] = identifier if identifier
	header[ :event_type ] = event_type

	return Arborist::TreeAPI.request( :subscribe, header, [ criteria, exclude ] )
end

#make_tree_api_socketObject

Create a new ZMQ REQ socket connected to the manager’s tree API.



335
336
337
338
# File 'lib/arborist/client.rb', line 335

def make_tree_api_socket
	self.log.info "Connecting to the tree socket %p" % [ self.tree_api_url ]
	return CZTop::Socket::REQ.new( self.tree_api_url )
end

#make_unack_request(identifier:) ⇒ Object

Return an ‘unack` request as a zmq message (a CZTop::Message) with the specified attribute.



299
300
301
# File 'lib/arborist/client.rb', line 299

def make_unack_request( identifier: )
	return Arborist::TreeAPI.request( :unack, {identifier: identifier}, nil )
end

#make_unsubscribe_request(subid) ⇒ Object

Return an ‘unsubscribe` request as a zmq message (a CZTop::Message) with the specified subid.



195
196
197
198
199
# File 'lib/arborist/client.rb', line 195

def make_unsubscribe_request( subid )
	self.log.debug "Making unsubscribe request for subid: %s" % [ subid ]

	return Arborist::TreeAPI.request( :unsubscribe, {subscription_id: subid}, nil )
end

#make_update_request(data, header = {}) ⇒ Object

Return an ‘update` request as a zmq message (a CZTop::Message) with the given data.



159
160
161
# File 'lib/arborist/client.rb', line 159

def make_update_request( data, header={} )
	return Arborist::TreeAPI.request( :update, header, data )
end

#modify(**args) ⇒ Object

Modify operational attributes of a node.



243
244
245
246
247
# File 'lib/arborist/client.rb', line 243

def modify( **args )
	request = self.make_modify_request( **args )
	self.send_tree_api_request( request )
	return true
end

#prune(**args) ⇒ Object

Remove a node



203
204
205
206
207
# File 'lib/arborist/client.rb', line 203

def prune( **args )
	request = self.make_prune_request( **args )
	response = self.send_tree_api_request( request )
	return response
end

#search(criteria: {}, options: {}, **args) ⇒ Object

Return the manager’s current node tree.



116
117
118
119
120
# File 'lib/arborist/client.rb', line 116

def search( criteria:{}, options:{}, **args )
	criteria = args if criteria.empty?
	request = self.make_search_request( criteria, **options )
	return self.send_tree_api_request( request )
end

#send_tree_api_request(request) ⇒ Object

Send the packed request via the Tree API socket, raise an error on unsuccessful response, and return the response body.



306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
# File 'lib/arborist/client.rb', line 306

def send_tree_api_request( request )
	self.log.debug "Sending request: %p" % [ request ]
	request.send_to( self.tree_api )

	res = CZTop::Message.receive_from( self.tree_api )
	self.log.debug "Received response: %p" % [ res ]

	header, body = Arborist::TreeAPI.decode( res )
	unless header[ 'success' ]
		exception = header['category'] == 'client' ? Arborist::ClientError : Arborist::ServerError
		raise exception, "Arborist manager said: %s" % [ header['reason'] ]
	end

	return body
end

#statusObject

Return the manager’s current status as a hash.



83
84
85
86
# File 'lib/arborist/client.rb', line 83

def status
	request = self.make_status_request
	return self.send_tree_api_request( request )
end

#subscribe(**args) ⇒ Object

Add a subscription



165
166
167
168
169
# File 'lib/arborist/client.rb', line 165

def subscribe( **args )
	request = self.make_subscribe_request( **args )
	response = self.send_tree_api_request( request )
	return response['id']
end

#tree_apiObject

Return a ZeroMQ REQ socket connected to the manager’s tree API, instantiating it if necessary.



329
330
331
# File 'lib/arborist/client.rb', line 329

def tree_api
	return @tree_api ||= self.make_tree_api_socket
end

#unsubscribe(*args) ⇒ Object

Remove a subscription



186
187
188
189
190
# File 'lib/arborist/client.rb', line 186

def unsubscribe( *args )
	request = self.make_unsubscribe_request( *args )
	response = self.send_tree_api_request( request )
	return response
end

#update(*args) ⇒ Object

Update the identified nodes in the manager with the specified data.



150
151
152
153
154
# File 'lib/arborist/client.rb', line 150

def update( *args )
	request = self.make_update_request( *args )
	self.send_tree_api_request( request )
	return true
end