arborist 0.0.1.pre20160106113421 → 0.0.1.pre20160128152542

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 9556233dcdad66412d5cabd6df2a7f3235dc616d
4
- data.tar.gz: 04d28c6e8168ff42793194506fa13c6a3261ba11
3
+ metadata.gz: ff35c627aec6f851ab5771166be2e66540abc85e
4
+ data.tar.gz: 3b424125fb3f00a0dcafb5be8b9fabd33bd62785
5
5
  SHA512:
6
- metadata.gz: a257132168202d1b7540286aad139cf52f3052924f64af76192ea65244ed591aff0dfc28241ee4e17497ab399b68639478e6200943757321b2a73c71fbd619fc
7
- data.tar.gz: c027d0fad82b687ae3d3f56335f7d81f50818f964a0d659b14bef3697124539efccd74e6dd72434bae896d3a30f508c411e36c113c0c8c61a55500ae8d1ab3d2
6
+ metadata.gz: 43fcf881e75fc6a9a78b00e1e69eb352c79aac330153fadf5df20f7e4dfda8c0da42b18ca5e25fd1e84cd897201024ffccd82e84210c919c2e750a9b7c8c1573
7
+ data.tar.gz: 769e82ffa9da3bed89475ef155a5c66e36263cd53cd9a61ae545183b5ad631da704f69abe650ba8080080bcae5943dba787df325d6f614dcbf5db60ba6b58e5d
data/Manifest.txt CHANGED
@@ -12,11 +12,15 @@ Protocol.md
12
12
  README.md
13
13
  Rakefile
14
14
  TODO.md
15
- bin/amanagerd
16
- bin/amonitord
17
- bin/aobserverd
15
+ Tutorial.md
16
+ bin/arborist
18
17
  lib/arborist.rb
18
+ lib/arborist/cli.rb
19
19
  lib/arborist/client.rb
20
+ lib/arborist/command/client.rb
21
+ lib/arborist/command/config.rb
22
+ lib/arborist/command/start.rb
23
+ lib/arborist/command/watch.rb
20
24
  lib/arborist/event.rb
21
25
  lib/arborist/event/node_acked.rb
22
26
  lib/arborist/event/node_delta.rb
@@ -24,6 +28,8 @@ lib/arborist/event/node_matching.rb
24
28
  lib/arborist/event/node_update.rb
25
29
  lib/arborist/event/sys_reloaded.rb
26
30
  lib/arborist/exceptions.rb
31
+ lib/arborist/loader.rb
32
+ lib/arborist/loader/file.rb
27
33
  lib/arborist/manager.rb
28
34
  lib/arborist/manager/event_publisher.rb
29
35
  lib/arborist/manager/tree_api.rb
data/README.md CHANGED
@@ -1,17 +1,26 @@
1
1
  # Arborist
2
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
3
+ home
4
+ : http://deveiate.org/projects/Arborist
5
+
6
+ code
7
+ : http://bitbucket.org/ged/Arborist
8
+
9
+ github
10
+ : https://github.com/ged/arborist
11
+
12
+ docs
13
+ : http://deveiate.org/code/arborist
7
14
 
8
15
 
9
16
  ## Description
10
17
 
11
- Arborist is a monitoring framework that follows the UNIX philosophy
18
+ Arborist is a monitoring toolkit that follows the UNIX philosophy
12
19
  of small parts and loose coupling for stability, reliability, and
13
20
  customizability.
14
21
 
22
+ [![Build Status](https://semaphoreci.com/api/v1/projects/13677b60-5f81-4e6e-a9c6-e21d30daa4ca/461532/badge.svg)](https://semaphoreci.com/ged/arborist)
23
+
15
24
 
16
25
  ## Prerequisites
17
26
 
@@ -44,7 +53,7 @@ and generate the API documentation.
44
53
 
45
54
  ## License
46
55
 
47
- Copyright (c) 2015, Michael Granger and Mahlon E. Smith
56
+ Copyright (c) 2015-2016, Michael Granger and Mahlon E. Smith
48
57
  All rights reserved.
49
58
 
50
59
  Redistribution and use in source and binary forms, with or without
data/Rakefile CHANGED
@@ -20,7 +20,7 @@ hoespec = Hoe.spec 'arborist' do |spec|
20
20
  spec.readme_file = 'README.md'
21
21
  spec.history_file = 'History.md'
22
22
  spec.extra_rdoc_files = FileList[ '*.rdoc', '*.md' ]
23
- self.license 'BSD-3-Clause'
23
+ spec.license 'BSD-3-Clause'
24
24
  spec.urls = {
25
25
  home: 'http://deveiate.org/projects/arborist',
26
26
  code: 'http://bitbucket.org/ged/arborist',
@@ -46,7 +46,7 @@ hoespec = Hoe.spec 'arborist' do |spec|
46
46
  spec.require_ruby_version( '>=2.2.0' )
47
47
  spec.hg_sign_tags = true if spec.respond_to?( :hg_sign_tags= )
48
48
 
49
- self.rdoc_locations << "deveiate:/usr/local/www/public/code/#{remote_rdoc_dir}"
49
+ spec.rdoc_locations << "deveiate:/usr/local/www/public/code/#{remote_rdoc_dir}"
50
50
  end
51
51
 
52
52
 
@@ -66,6 +66,20 @@ task :coverage do
66
66
  end
67
67
 
68
68
 
69
+ # Use the fivefish formatter for docs generated from development checkout
70
+ if File.directory?( '.hg' )
71
+ require 'rdoc/task'
72
+
73
+ Rake::Task[ 'docs' ].clear
74
+ RDoc::Task.new( 'docs' ) do |rdoc|
75
+ rdoc.main = "README.md"
76
+ rdoc.rdoc_files.include( "*.rdoc", "*.md", "ChangeLog", "lib/**/*.rb" )
77
+ rdoc.generator = :fivefish
78
+ rdoc.title = 'Arborist'
79
+ rdoc.rdoc_dir = 'doc'
80
+ end
81
+ end
82
+
69
83
  task :gemspec => GEMSPEC
70
84
  file GEMSPEC => __FILE__ do |task|
71
85
  spec = $hoespec.spec
data/TODO.md CHANGED
@@ -5,6 +5,7 @@
5
5
  * Serialize nodes on shutdown
6
6
  * Include a node's subscriptions in its serialized data
7
7
  * Implement loading/reloading nodes.
8
+ * Implement the system events (sys.acked, sys.reloaded, etc.)
8
9
 
9
10
  ## Tree API
10
11
 
@@ -21,4 +22,12 @@
21
22
 
22
23
  ## Node
23
24
 
24
- * Add a 'disabled' state, can be set on 'up' nodes by acking them.
25
+ * Allow (require?) node types to specify what kinds of nodes can be
26
+ their parent, and also adds the constructor DSL method to it
27
+
28
+
29
+ ## Setup/Installation
30
+
31
+ * Add a CLI for generating a basic setup and then adding
32
+ nodes/monitors/observers to it.
33
+
data/Tutorial.md ADDED
@@ -0,0 +1,8 @@
1
+ # Arborist Tutorial
2
+
3
+ Sorry, we're still building. We'll flesh this out once we get the software
4
+ stable and work out the kinks.
5
+
6
+ In the meantime, feel free to come chat us up in the
7
+ [Arborist Gitter channel](https://gitter.im/ged/arborist).
8
+
data/bin/arborist ADDED
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env ruby
2
+ # vim: set nosta noet ts=4 sw=4:
3
+
4
+ require 'arborist'
5
+ require 'arborist/cli'
6
+
7
+ Arborist::CLI.run( ARGV.dup )
8
+
data/lib/arborist.rb CHANGED
@@ -17,7 +17,7 @@ module Arborist
17
17
  VERSION = '0.0.1'
18
18
 
19
19
  # Version control revision
20
- REVISION = %q$Revision: fddcbace9b6d $
20
+ REVISION = %q$Revision: e23d2b9f8f31 $
21
21
 
22
22
 
23
23
  # The name of the environment variable which can be used to set the config path
@@ -111,11 +111,10 @@ module Arborist
111
111
  end
112
112
 
113
113
 
114
- ### Return a new Arborist::Manager for the nodes described in files under
115
- ### the specified +directory+.
116
- def self::manager_for( directory )
114
+ ### Return a new Arborist::Manager for the nodes loaded by the specified +loader+.
115
+ def self::manager_for( loader )
117
116
  self.load_all
118
- nodes = Arborist::Node.each_in( directory )
117
+ nodes = Arborist::Node.each_in( loader )
119
118
  manager = Arborist::Manager.new
120
119
  manager.load_tree( nodes )
121
120
 
@@ -124,10 +123,10 @@ module Arborist
124
123
 
125
124
 
126
125
  ### Return a new Arborist::MonitorRunner for the monitors described in files under
127
- ### the specified +directory+.
128
- def self::monitor_runner_for( directory )
126
+ ### the specified +loader+.
127
+ def self::monitor_runner_for( loader )
129
128
  self.load_all
130
- monitors = Arborist::Monitor.each_in( directory )
129
+ monitors = Arborist::Monitor.each_in( loader )
131
130
  runner = Arborist::MonitorRunner.new
132
131
  runner.load_monitors( monitors )
133
132
 
@@ -136,10 +135,10 @@ module Arborist
136
135
 
137
136
 
138
137
  ### Return a new Arborist::ObserverRunner for the observers described in files under
139
- ### the specified +directory+.
140
- def self::observer_runner_for( directory )
138
+ ### the specified +loader+.
139
+ def self::observer_runner_for( loader )
141
140
  self.load_all
142
- observers = Arborist::Observer.each_in( directory )
141
+ observers = Arborist::Observer.each_in( loader )
143
142
  runner = Arborist::ObserverRunner.new
144
143
  runner.load_observers( observers )
145
144
 
@@ -171,11 +170,13 @@ module Arborist
171
170
 
172
171
  autoload :Client, 'arborist/client'
173
172
  autoload :Event, 'arborist/event'
173
+ autoload :Loader, 'arborist/loader'
174
174
  autoload :Manager, 'arborist/manager'
175
175
  autoload :Monitor, 'arborist/monitor'
176
176
  autoload :MonitorRunner, 'arborist/monitor_runner'
177
177
  autoload :Node, 'arborist/node'
178
178
  autoload :Observer, 'arborist/observer'
179
+ autoload :ObserverRunner, 'arborist/observer_runner'
179
180
  autoload :Subscription, 'arborist/subscription'
180
181
 
181
182
  end # module Arborist
@@ -0,0 +1,380 @@
1
+ # -*- ruby -*-
2
+ #encoding: utf-8
3
+
4
+ require 'loggability'
5
+ require 'highline'
6
+ require 'gli'
7
+
8
+ require 'arborist' unless defined?( Arborist )
9
+ require 'arborist/mixins'
10
+
11
+
12
+ # The command-line interface to Arborist.
13
+ module Arborist::CLI
14
+ extend Arborist::MethodUtilities,
15
+ Loggability,
16
+ GLI::App
17
+
18
+
19
+ # Write logs to Arborist's logger
20
+ log_to :arborist
21
+
22
+
23
+ # Make a HighLine color scheme
24
+ COLOR_SCHEME = HighLine::ColorScheme.new do |scheme|
25
+ scheme[:header] = [ :bold, :yellow ]
26
+ scheme[:subheader] = [ :bold, :white ]
27
+ scheme[:key] = [ :white ]
28
+ scheme[:value] = [ :bold, :white ]
29
+ scheme[:error] = [ :red ]
30
+ scheme[:warning] = [ :yellow ]
31
+ scheme[:message] = [ :reset ]
32
+ end
33
+
34
+
35
+ #
36
+ # GLI
37
+ #
38
+
39
+ # Set up global[:description] and options
40
+ program_desc 'Arborist'
41
+
42
+ # The command version
43
+ version Arborist::VERSION
44
+
45
+ # Use an OpenStruct for options instead of a Hash
46
+ use_openstruct( true )
47
+
48
+ # Subcommand options are independent of global[:ones]
49
+ subcommand_option_handling :normal
50
+
51
+ # Strict argument validation
52
+ arguments :strict
53
+
54
+
55
+ # Custom parameter types
56
+ accept Array do |value|
57
+ value.strip.split(/\s*,\s*/)
58
+ end
59
+ accept Pathname do |value|
60
+ Pathname( value.strip )
61
+ end
62
+
63
+
64
+ # Global options
65
+ desc "Specify the config file to load"
66
+ flag [:c, :config], type: Pathname
67
+
68
+ desc 'Enable debugging output'
69
+ switch [:d, :debug]
70
+
71
+ desc 'Enable verbose output'
72
+ switch [:v, :verbose]
73
+
74
+ desc 'Set log level to LEVEL (one of %s)' % [Loggability::LOG_LEVELS.keys.join(', ')]
75
+ default_value Loggability[self].level
76
+ flag [:l, :loglevel], must_match: Loggability::LOG_LEVELS.keys
77
+
78
+ desc "Don't actually do anything, just show what would happen."
79
+ switch [:n, 'dry-run']
80
+
81
+ desc "Additional Ruby libs to require before doing anything."
82
+ flag [:r, 'requires'], type: Array
83
+
84
+
85
+ #
86
+ # GLI Event callbacks
87
+ #
88
+
89
+ pre do |global, command, options, args|
90
+ if loglevel = global[:loglevel]
91
+ Loggability.level = loglevel.to_sym
92
+ else
93
+ Loggability.level = :fatal
94
+ end
95
+
96
+ # Include a 'lib' directory if there is one
97
+ $LOAD_PATH.unshift( 'lib' ) if File.directory?( 'lib' )
98
+
99
+ self.require_additional_libs( global.requires ) if global.requires
100
+ self.load_config( global )
101
+ self.install_highline_colorscheme
102
+
103
+ true
104
+ end
105
+
106
+
107
+ ##
108
+ # Registered subcommand modules
109
+ singleton_attr_accessor :subcommand_modules
110
+
111
+ ##
112
+ # The IO opened to the output file
113
+ singleton_attr_accessor :outfile
114
+
115
+
116
+ ### Overridden -- Add registered subcommands immediately before running.
117
+ def self::run( * )
118
+ self.add_registered_subcommands
119
+ super
120
+ end
121
+
122
+
123
+ ### Add the specified +mod+ule containing subcommands to the 'arborist' command.
124
+ def self::register_subcommands( mod )
125
+ self.subcommand_modules ||= []
126
+ self.subcommand_modules.push( mod )
127
+ mod.extend( GLI::DSL, GLI::AppSupport, Loggability )
128
+ mod.log_to( :arborist )
129
+ end
130
+
131
+
132
+ ### Add the commands from the registered subcommand modules.
133
+ def self::add_registered_subcommands
134
+ self.subcommand_modules ||= []
135
+ self.subcommand_modules.each do |mod|
136
+ merged_commands = mod.commands.merge( self.commands )
137
+ self.commands.update( merged_commands )
138
+ command_objs = self.commands_declaration_order | self.commands.values
139
+ self.commands_declaration_order.replace( command_objs )
140
+ end
141
+ end
142
+
143
+
144
+ ### Return the HighLine prompt used by the command to communicate with the
145
+ ### user.
146
+ def self::prompt
147
+ @prompt ||= HighLine.new( $stdin, $stderr )
148
+ end
149
+
150
+
151
+ ### If the command's output was redirected to a file, return the open File object
152
+ ### for it.
153
+ def self::outfile
154
+ return @outfile
155
+ end
156
+
157
+
158
+ ### Discard the existing HighLine prompt object if one existed. Mostly useful for
159
+ ### testing.
160
+ def self::reset_prompt
161
+ @prompt = nil
162
+ end
163
+
164
+
165
+ ### Load any additional Ruby libraries given with the -r global option.
166
+ def self::require_additional_libs( requires)
167
+ requires.each do |path|
168
+ path = "arborist/#{path}" unless path.start_with?( 'arborist/' )
169
+ require( path )
170
+ end
171
+ end
172
+
173
+
174
+ ### Install the color scheme used by HighLine
175
+ def self::install_highline_colorscheme
176
+ HighLine.color_scheme = HighLine::ColorScheme.new do |cs|
177
+ cs[:headline] = [ :bold, :white, :on_black ]
178
+ cs[:success] = [ :bold, :green ]
179
+ cs[:error] = [ :bold, :red ]
180
+ cs[:up] = [ :green ]
181
+ cs[:down] = [ :red ]
182
+ cs[:unknown] = [ :dark, :yellow ]
183
+ cs[:disabled] = [ :dark, :white ]
184
+ cs[:acked] = [ :yellow ]
185
+ cs[:highlight] = [ :bold, :yellow ]
186
+ cs[:search_hit] = [ :black, :on_white ]
187
+ cs[:prompt] = [ :cyan ]
188
+ cs[:even_row] = [ :bold ]
189
+ cs[:odd_row] = [ :normal ]
190
+ end
191
+ end
192
+
193
+
194
+ ### Load the config file using either arborist-base's config-loader if available, or
195
+ ### fall back to DEFAULT_CONFIG_FILE
196
+ def self::load_config( global={} )
197
+ Arborist.load_config( global.config ) if global.config
198
+
199
+ # Set up the logging formatter
200
+ Loggability.format_with( :color ) if $stdout.tty?
201
+ end
202
+
203
+
204
+ ### Set up the output levels and globals based on the associated +global+ options.
205
+ def self::setup_output( global )
206
+
207
+ # Turn on Ruby debugging and/or verbosity if specified
208
+ if global[:n]
209
+ $DRYRUN = true
210
+ Loggability.level = :warn
211
+ else
212
+ $DRYRUN = false
213
+ end
214
+
215
+ if global[:verbose]
216
+ $VERBOSE = true
217
+ Loggability.level = :info
218
+ end
219
+
220
+ if global[:debug]
221
+ $DEBUG = true
222
+ Loggability.level = :debug
223
+ end
224
+ end
225
+
226
+
227
+ # Write the error to the log on exceptions.
228
+ on_error do |exception|
229
+ case exception
230
+ when OptionParser::ParseError, GLI::CustomExit
231
+ self.log.debug( exception )
232
+ else
233
+ self.log.error( exception )
234
+ end
235
+
236
+ exception.backtrace.each {|frame| self.log.debug(frame) }
237
+
238
+ true
239
+ end
240
+
241
+
242
+ #
243
+ # GLI subcommands
244
+ #
245
+
246
+
247
+ # Convenience module for subcommand registration syntax sugar.
248
+ module Subcommand
249
+
250
+ ### Extension callback -- register the extending object as a subcommand.
251
+ def self::extended( mod )
252
+ Arborist::CLI.log.debug "Registering subcommands from %p" % [ mod ]
253
+ Arborist::CLI.register_subcommands( mod )
254
+ end
255
+
256
+
257
+ ###############
258
+ module_function
259
+ ###############
260
+
261
+ ### Exit with the specified +exit_code+ after printing the given +message+.
262
+ def exit_now!( message, exit_code=1 )
263
+ raise GLI::CustomExit.new( message, exit_code )
264
+ end
265
+
266
+
267
+ ### Exit with a helpful +message+ and display the usage.
268
+ def help_now!( message=nil )
269
+ exception = OptionParser::ParseError.new( message )
270
+ def exception.exit_code; 64; end
271
+
272
+ raise exception
273
+ end
274
+
275
+
276
+ ### Get the prompt (a Highline object)
277
+ def prompt
278
+ return Arborist::CLI.prompt
279
+ end
280
+
281
+
282
+ ### Return the specified +text+ as a Highline::String for convenient formatting,
283
+ ### color, etc.
284
+ def hl( text )
285
+ return HighLine::String.new( text.to_s )
286
+ end
287
+
288
+
289
+ ### Return the specified +string+ in the 'headline' ANSI color.
290
+ def headline_string( string )
291
+ return hl( string ).color( :headline )
292
+ end
293
+
294
+
295
+ ### Return the specified +string+ in the 'highlight' ANSI color.
296
+ def highlight_string( string )
297
+ return hl( string ).color( :highlight )
298
+ end
299
+
300
+
301
+ ### Return the specified +string+ in the 'success' ANSI color.
302
+ def success_string( string )
303
+ return hl( string ).color( :success )
304
+ end
305
+
306
+
307
+ ### Return the specified +string+ in the 'error' ANSI color.
308
+ def error_string( string )
309
+ return hl( string ).color( :error )
310
+ end
311
+
312
+
313
+ ### Output a table with the given +rows+.
314
+ def display_table( rows )
315
+ colwidths = rows.transpose.map do |colvals|
316
+ colvals.map {|val| visible_chars(val) }.max
317
+ end
318
+
319
+ rows.each do |row|
320
+ row_string = row.zip( colwidths ).inject( '' ) do |accum, (val, colsize)|
321
+ padding = ' ' * (colsize - visible_chars(val) + 2)
322
+ accum + val.to_s + padding
323
+ end
324
+
325
+ Arborist::CLI.prompt.say( row_string + "\n" )
326
+ end
327
+ end
328
+
329
+
330
+ ### Return the count of visible (i.e., non-control) characters in the given +string+.
331
+ def visible_chars( string )
332
+ return string.to_s.gsub(/\e\[.*?m/, '').scan( /\P{Cntrl}/ ).size
333
+ end
334
+
335
+
336
+ ### In dry-run mode, output the description instead of running the provided block and
337
+ ### return the +return_value+.
338
+ ### If dry-run mode is not enabled, yield to the block.
339
+ def unless_dryrun( description, return_value=true )
340
+ if $DRYRUN
341
+ self.log.warn( "DRYRUN> #{description}" )
342
+ return return_value
343
+ else
344
+ return yield
345
+ end
346
+ end
347
+ alias_method :unless_dry_run, :unless_dryrun
348
+
349
+ end # module Subcommand
350
+
351
+
352
+ ### Register one or more subcommands with the 'arborist' command shell. The given
353
+ ### block will be evaluated in the context of Arborist::CLI.
354
+ def self::register( &block )
355
+ self.instance_eval( &block )
356
+ end
357
+
358
+
359
+ ### Custom command loader. The default one is silly.
360
+ def self::load_commands( path )
361
+ self.log.debug "Load commands from %s" % [ path ]
362
+ Pathname.glob( path + '*.rb' ).each do |rbfile|
363
+ self.log.debug " loading %s..." % [ rbfile ]
364
+ require( rbfile )
365
+ end
366
+ end
367
+
368
+
369
+ # Load commands from any files in the specified directory relative to LOAD_PATHs
370
+ def self::commands_from( subdir )
371
+ $LOAD_PATH.map {|path| Pathname(path) }.each do |libdir|
372
+ command_dir = libdir.expand_path + subdir
373
+ load_commands( command_dir )
374
+ end
375
+ end
376
+
377
+
378
+ commands_from 'arborist/command'
379
+
380
+ end # class Arborist::CLI