arborist 0.2.0 → 0.3.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 755dd41faeb4ed205809c646017026c078f4aa9dfe59f194eeef91b8cd0ed77c
4
- data.tar.gz: '0080619e822e2a8fac94d9c3bc5c4c723bf1f1c1b33c6ca1de0951c70070cb35'
3
+ metadata.gz: 8e381c42854fa4ee4d530c7ac6a0ec35a626ebf60c56966a034f3cf42e56d277
4
+ data.tar.gz: 583b4bc03a562550d8e6840c46fcd357e2bfeedc1986bb1813850a9a5fcf4b62
5
5
  SHA512:
6
- metadata.gz: e9ef21ce54e29b1b1b46bbed628cb752bacc79c0a1ce9af32b945952bf96532677e2c29c5953dcb516bc2b13f316589b57294d9391aeed353234688b4c057f62
7
- data.tar.gz: a8b4fbc85de0b4fa636a2e82cc086980f97b5bc666da0f8c11d8d8e0ed9d99d7d014b34a5b61ad8cd53f4aa7f869967f41ca49487d635253ff2d072c286172c2
6
+ metadata.gz: 0d53eee53ff4d17916bb90aa3def361179cd4a81cc16e102701e05a9f1548dafef24962ffb23542adb044b8757af3089ac92da0abdb90022d8fcabaaeedb3a10
7
+ data.tar.gz: 5b26f1215719f2746f092b9230acdf1350f7a241481b327dc3c74a230d3d5be390413d7db60287e83ac6e7d95365aed8440b0f60424e34445bdc3f1da48cfe31
Binary file
data.tar.gz.sig CHANGED
Binary file
data/ChangeLog CHANGED
@@ -1,8 +1,66 @@
1
+ 2018-08-29 Michael Granger <ged@FaerieMUD.org>
2
+
3
+ * lib/arborist/command/run_once.rb:
4
+ Add a `run` command for testing monitors
5
+ [1bc6155c5e9c] [tip]
6
+
7
+ * lib/arborist/node/host.rb:
8
+ Shut up warnings about uninitialized instance vars
9
+ [4329c98ea325]
10
+
11
+ 2018-08-29 Mahlon E. Smith <mahlon@martini.nu>
12
+
13
+ * lib/arborist/node.rb, spec/arborist/node_spec.rb:
14
+ Acking an already acked node transitions the node to disabled.
15
+ [141000d6bec3]
16
+
17
+ 2018-08-28 Michael Granger <ged@FaerieMUD.org>
18
+
19
+ * spec/spec_helper.rb:
20
+ Enabled RSpec warnings, example profiles
21
+ [404f8d609524]
22
+
23
+ 2018-08-24 Mahlon E. Smith <mahlon@martini.nu>
24
+
25
+ * lib/arborist/client.rb:
26
+ Use the proper exception when raising errors from the client,
27
+ instead of RuntimeError.
28
+ [ff0b0fea9a9f]
29
+
30
+ 2018-08-15 Mahlon E. Smith <mahlon@martini.nu>
31
+
32
+ * lib/arborist/command/tree.rb:
33
+ Add raw formatting for YAML and JSON to the tree command.
34
+ [f0b978d49569] [github/master]
35
+
36
+ * Rakefile, lib/arborist/command/ack.rb:
37
+ Optionally continue attempting to ack/clear nodes if some are
38
+ invalid.
39
+ [d379568d92cc]
40
+
41
+ * lib/arborist/monitor/socket.rb:
42
+ Expose socket batch size to configurability.
43
+ [17866a8a66d6]
44
+
45
+ 2018-08-08 Michael Granger <ged@FaerieMUD.org>
46
+
47
+ * .hgtags:
48
+ Added tag v0.2.0 for changeset b5d07bcc4762
49
+ [0a39e734c94d]
50
+
51
+ * .hgsigs:
52
+ Added signature for changeset b7725c5136bc
53
+ [b5d07bcc4762] [v0.2.0]
54
+
55
+ * History.md, README.md, TODO.md, arborist.gemspec, lib/arborist.rb:
56
+ Bump the minor version, update history and the to-do file.
57
+ [b7725c5136bc]
58
+
1
59
  2018-08-01 Mahlon E. Smith <mahlon@martini.nu>
2
60
 
3
61
  * lib/arborist/manager.rb:
4
62
  Add debug log for checkpoint timing.
5
- [734e01730be6] [tip]
63
+ [734e01730be6]
6
64
 
7
65
  2018-07-27 Mahlon E. Smith <mahlon@martini.nu>
8
66
 
@@ -29,7 +87,7 @@
29
87
 
30
88
  * lib/arborist/node.rb, spec/arborist/node_spec.rb:
31
89
  Add acknowledgement changes to delta events.
32
- [f6b57c73929e] [github/master]
90
+ [f6b57c73929e]
33
91
 
34
92
  * Manifest.txt, lib/arborist/monitor/connection_batching.rb,
35
93
  lib/arborist/monitor/socket.rb:
data/History.md CHANGED
@@ -1,3 +1,21 @@
1
+ ## v0.3.0 [2018-08-29] Michael Granger <ged@FaerieMUD.org>
2
+
3
+ Enhancements:
4
+
5
+ - Add a `run_once` command for testing monitors
6
+ - Acking an already acked node transitions the node to disabled.
7
+ - Add raw formatting for YAML and JSON to the tree command.
8
+ - Optionally continue attempting to ack/clear nodes if some are
9
+ invalid.
10
+ - Expose socket batch size to configurability.
11
+
12
+ Fixes:
13
+
14
+ - Use the proper exception when raising errors from the client,
15
+ instead of RuntimeError.
16
+
17
+
18
+
1
19
  ## v0.2.0 [2018-08-08] Michael Granger <ged@FaerieMUD.org>
2
20
 
3
21
  Breaking:
@@ -14,6 +14,7 @@ lib/arborist/command/ack.rb
14
14
  lib/arborist/command/client.rb
15
15
  lib/arborist/command/config.rb
16
16
  lib/arborist/command/reset.rb
17
+ lib/arborist/command/run_once.rb
17
18
  lib/arborist/command/start.rb
18
19
  lib/arborist/command/summary.rb
19
20
  lib/arborist/command/tree.rb
data/Rakefile CHANGED
@@ -56,7 +56,6 @@ hoespec = Hoe.spec 'arborist' do |spec|
56
56
  spec.dependency 'simplecov', '~> 0.9', :developer
57
57
  spec.dependency 'timecop', '~> 0.7', :developer
58
58
  spec.dependency 'rdoc', '~> 5.1', :developer
59
- spec.dependency 'rdoc', '~> 5.1', :developer
60
59
  spec.dependency 'state_machines-graphviz', '~> 0.0', :developer
61
60
 
62
61
  spec.require_ruby_version( '>=2.3.1' )
@@ -14,10 +14,10 @@ module Arborist
14
14
  Configurability
15
15
 
16
16
  # Package version
17
- VERSION = '0.2.0'
17
+ VERSION = '0.3.0'
18
18
 
19
19
  # Version control revision
20
- REVISION = %q$Revision: b7725c5136bc $
20
+ REVISION = %q$Revision: db70f921e653 $
21
21
 
22
22
 
23
23
  # The name of the environment variable which can be used to set the config path
@@ -312,7 +312,8 @@ class Arborist::Client
312
312
 
313
313
  header, body = Arborist::TreeAPI.decode( res )
314
314
  unless header[ 'success' ]
315
- raise "Arborist manager said: %s" % [ header['reason'] ]
315
+ exception = header['category'] == 'client' ? Arborist::ClientError : Arborist::ServerError
316
+ raise exception, "Arborist manager said: %s" % [ header['reason'] ]
316
317
  end
317
318
 
318
319
  return body
@@ -19,6 +19,9 @@ module Arborist::CLI::Ack
19
19
  cmd.switch :clear, default: false,
20
20
  desc: "Clear the ack instead of setting it.",
21
21
  negatable: false
22
+ cmd.switch [ :k, 'keep-going' ], default: false,
23
+ desc: "Continue in the event of errors.",
24
+ negatable: false
22
25
 
23
26
  cmd.flag [ :u, :user ],
24
27
  desc: "The user to mark the nodes with."
@@ -46,12 +49,17 @@ module Arborist::CLI::Ack
46
49
 
47
50
  identifiers.each do |id|
48
51
  res[ id ] = unless_dryrun( "Acking #{id}...", true ) do
49
- client.ack(
50
- identifier: id,
51
- message: message,
52
- sender: userid,
53
- via: "command line"
54
- )
52
+ begin
53
+ client.ack(
54
+ identifier: id,
55
+ message: message,
56
+ sender: userid,
57
+ via: "command line"
58
+ )
59
+ rescue => err
60
+ raise unless options[ 'keep-going' ]
61
+ err.message
62
+ end
55
63
  end
56
64
  end
57
65
  end
@@ -59,7 +67,7 @@ module Arborist::CLI::Ack
59
67
  res.each_pair do |identifier, result|
60
68
  prompt.say "%s: %s" % [
61
69
  hl.bold.bright_blue( identifier ),
62
- result == true ? "Okay." : hl.red( res.to_s )
70
+ result == true ? "Okay." : hl.red( res[identifier].to_s )
63
71
  ]
64
72
  end
65
73
  end
@@ -0,0 +1,113 @@
1
+ # -*- ruby -*-
2
+ #encoding: utf-8
3
+
4
+ require 'tty-screen'
5
+ require 'arborist/cli' unless defined?( Arborist::CLI )
6
+
7
+
8
+ # Command to run a monitor in single-run mode
9
+ module Arborist::CLI::RunOnce
10
+ extend Arborist::CLI::Subcommand
11
+
12
+ desc 'Run an Arborist monitor once'
13
+ long_desc <<-EOF
14
+ Run monitor(s) once.
15
+
16
+ If the MONITOR argument is a file, it is loaded and any monitors contained
17
+ in it are run once and their output is dumped. If it is not a readable file,
18
+ it is assumed to be the name of a monitor callback module, and that is
19
+ run inside of a simple monitor object instead.
20
+ EOF
21
+
22
+ arg :MONITOR
23
+
24
+ command :run_once do |cmd|
25
+
26
+ cmd.flag :type,
27
+ desc: "Specify the types of nodes to run a monitor class against. Ignored for monitor files.",
28
+ default_value: 'host'
29
+ cmd.flag :require, desc: "Require a file before instantiating monitor(s)."
30
+
31
+ cmd.action do |globals, options, args|
32
+ monitors = monitors_from_args( args, options )
33
+ client = Arborist.client
34
+
35
+ monitors.each do |monitor|
36
+ # :TODO: Should the client maybe have a method for searching for the nodes for a
37
+ # monitor instead of having to stitch them together like this?
38
+ nodes = client.search(
39
+ criteria: monitor.positive_criteria,
40
+ exclude: monitor.negative_criteria,
41
+ exclude_down: monitor.exclude_down?,
42
+ properties: monitor.node_properties
43
+ )
44
+
45
+ desc = "running %p against %d nodes" % [ monitor, nodes.length ]
46
+ unless_dryrun( desc ) do
47
+ prompt.say( highlight_string(monitor.description) )
48
+ results = monitor.run( nodes )
49
+ display_results( results )
50
+ end
51
+
52
+ end
53
+ end
54
+ end
55
+
56
+
57
+ ###############
58
+ module_function
59
+ ###############
60
+
61
+
62
+ ### Figure out what kind of monitor is being run from the provided +args+ and
63
+ ### +options+ and return instances of them.
64
+ def monitors_from_args( args, options )
65
+ return args.flat_map do |monitor|
66
+ if File.exist?( monitor )
67
+ Arborist::Monitor.load( monitor )
68
+ else
69
+ wrap_monitor_callback( monitor, options )
70
+ end
71
+ end
72
+ end
73
+
74
+
75
+ ### Try to load the monitor callback with the specified +mod_name+ and return
76
+ ### it inside a plain monitor object.
77
+ def wrap_monitor_callback( mod_name, options )
78
+ filename = fileize( mod_name )
79
+ required_file = options[ :require ] || "arborist/monitor/%s" % [ filename ]
80
+ self.log.debug "Loading monitor callback from %p" % [ required_file ]
81
+
82
+ require( required_file )
83
+
84
+ exec_module = Arborist::Monitor.const_get( mod_name )
85
+ monitor = Arborist::Monitor.new( exec_module.name, filename )
86
+ monitor.exec( exec_module )
87
+ monitor.match( type: options[:type] )
88
+
89
+ return [ monitor ]
90
+ end
91
+
92
+
93
+ ### Return the specified +mod_name+ as the corresponding file name.
94
+ def fileize( mod_name )
95
+ return mod_name.sub( /.*::/, '' ).
96
+ gsub( /([a-z0-9])([A-Z])/, '\\1_\\2' ).downcase
97
+ end
98
+
99
+
100
+ ### Display the results of running a monitor.
101
+ def display_results( results )
102
+ width = TTY::Screen.width
103
+
104
+ results.keys.sort.each do |identifier|
105
+ result = results[ identifier ]
106
+ prompt.say( highlight_string(identifier) )
107
+ prompt.say( PP.pp(result, '', width) )
108
+ prompt.say "\n"
109
+ end
110
+ end
111
+
112
+ end # module Arborist::CLI::Start
113
+
@@ -2,6 +2,8 @@
2
2
  #encoding: utf-8
3
3
 
4
4
  require 'pp'
5
+ require 'json'
6
+ require 'yaml'
5
7
  require 'msgpack'
6
8
  require 'tty-tree'
7
9
 
@@ -23,6 +25,9 @@ module Arborist::CLI::Tree
23
25
  desc: "Include the parent path back to root, when using --from.",
24
26
  negatable: false
25
27
 
28
+ cmd.flag :format,
29
+ desc: "When dumping the tree using --raw, serialize to this format.",
30
+ must_match: %w[ yaml json ]
26
31
  cmd.flag [:f, :from],
27
32
  type: String,
28
33
  desc: "Start at a node other than the root.",
@@ -42,7 +47,14 @@ module Arborist::CLI::Tree
42
47
  nodes = client.fetch( opts )
43
48
 
44
49
  if options[:raw]
45
- pp nodes.first
50
+ case options[:format]
51
+ when 'json'
52
+ puts JSON.dump( nodes.first )
53
+ when 'yaml'
54
+ puts YAML.dump( nodes.first )
55
+ else
56
+ pp nodes.first
57
+ end
46
58
 
47
59
  else
48
60
  status = client.status
@@ -24,6 +24,11 @@ module Arborist::Monitor::Socket
24
24
  Float( val )
25
25
  end
26
26
 
27
+ ##
28
+ # The number of socket connections to attempt simultaneously.
29
+ setting :batch_size, default: 150 do |val|
30
+ Integer( val )
31
+ end
27
32
  end
28
33
 
29
34
 
@@ -55,8 +60,11 @@ module Arborist::Monitor::Socket
55
60
  ###
56
61
  ### +:timeout+
57
62
  ### Set the number of seconds to wait for a connection for each node.
58
- def initialize( timeout: Arborist::Monitor::Socket.default_timeout )
63
+ ### +:batch_size+
64
+ ### The number of UDP connection attempts to perform simultaneously.
65
+ def initialize( timeout: Arborist::Monitor::Socket.default_timeout, batch_size: Arborist::Monitor::Socket.batch_size )
59
66
  self.timeout = timeout
67
+ self.batch_size = batch_size
60
68
  end
61
69
 
62
70
 
@@ -127,12 +135,6 @@ module Arborist::Monitor::Socket
127
135
 
128
136
  log_to :arborist
129
137
 
130
-
131
- # Defaults for instances of this monitor
132
- DEFAULT_OPTIONS = {
133
- timeout: 0.001
134
- }
135
-
136
138
  # Always request the node addresses and port.
137
139
  USED_PROPERTIES = [ :addresses, :port ].freeze
138
140
 
@@ -153,8 +155,11 @@ module Arborist::Monitor::Socket
153
155
  ###
154
156
  ### +:timeout+
155
157
  ### Set the number of seconds to wait for a connection for each node.
156
- def initialize( timeout: Arborist::Monitor::Socket.default_timeout )
158
+ ### +:batch_size+
159
+ ### The number of UDP connection attempts to perform simultaneously.
160
+ def initialize( timeout: Arborist::Monitor::Socket.default_timeout, batch_size: Arborist::Monitor::Socket.batch_size )
157
161
  self.timeout = timeout
162
+ self.batch_size = batch_size
158
163
  end
159
164
 
160
165
 
@@ -129,8 +129,8 @@ class Arborist::Node
129
129
  end
130
130
 
131
131
  event :acknowledge do
132
- transition any - [:down, :acked] => :disabled
133
- transition [:down, :acked] => :acked
132
+ transition any - [:down] => :disabled
133
+ transition :down => :acked
134
134
  end
135
135
 
136
136
  event :unacknowledge do
@@ -156,7 +156,7 @@ class Arborist::Node
156
156
  after_transition :down => :up, do: :on_node_up
157
157
  after_transition :up => :warn, do: :on_node_warn
158
158
  after_transition [:unknown, :warn, :up] => :down, do: :on_node_down
159
- after_transition [:unknown, :warn, :up] => :disabled, do: :on_node_disabled
159
+ after_transition [:acked, :unknown, :warn, :up] => :disabled, do: :on_node_disabled
160
160
  after_transition any => :quieted, do: :on_node_quieted
161
161
  after_transition :disabled => :unknown, do: :on_node_enabled
162
162
  after_transition :quieted => :unknown, do: :on_node_unquieted
@@ -1324,6 +1324,8 @@ class Arborist::Node
1324
1324
 
1325
1325
  ### Callback for when a node goes from up to disabled
1326
1326
  def on_node_disabled( transition )
1327
+ self.errors.clear
1328
+ self.warnings.clear
1327
1329
  self.log.warn "%s is %s" % [ self.identifier, self.status_description ]
1328
1330
  end
1329
1331
 
@@ -36,6 +36,7 @@ class Arborist::Node::Host < Arborist::Node
36
36
  ### Create a new Host node.
37
37
  def initialize( identifier, attributes={}, &block )
38
38
  @addresses = []
39
+ @hostname = nil
39
40
  super
40
41
  end
41
42
 
@@ -19,6 +19,7 @@ describe Arborist::Client do
19
19
  describe "synchronous API", :testing_manager do
20
20
 
21
21
  before( :each ) do
22
+ @manager = nil
22
23
  @manager_thread = Thread.new do
23
24
  @manager = make_testing_manager()
24
25
  Loggability[ Arborist ].info "Starting a testing manager: %p" % [ @manager ]
@@ -454,17 +454,16 @@ describe Arborist::Node do
454
454
 
455
455
  let( :node ) do
456
456
  obj = super()
457
- obj.status = 'acked'
457
+ obj.status = 'down'
458
458
  obj.errors['moldovia'] = 'Something is wrong | he falls | betraying the trust | "\
459
459
  "there is a disaster in his life.'
460
- obj.acknowledge( message: "Leitmotiv", sender: 'ged' )
460
+ obj.acknowledge( message: "Leitmotiv", sender: 'ged' ) # ack!
461
461
  obj
462
462
  end
463
463
 
464
464
 
465
465
  it_behaves_like "a reachable node"
466
466
 
467
-
468
467
  it "transitions to `up` status if its error is cleared" do
469
468
  expect {
470
469
  node.update( {error: nil}, 'moldovia' )
@@ -472,6 +471,14 @@ describe Arborist::Node do
472
471
  end
473
472
 
474
473
 
474
+ it "transitions to `disabled` status if its acked twice" do
475
+ expect {
476
+ node.acknowledge( message: "Leitmotiv", sender: 'ged' )
477
+ }.to change { node.status }.from( 'acked' ).to( 'disabled' )
478
+ expect( node.errors ).to be_empty
479
+ end
480
+
481
+
475
482
  it "stays `up` if it is updated twice with an error key" do
476
483
  node.update( {error: nil}, 'moldovia' )
477
484
 
@@ -67,6 +67,7 @@ describe Arborist::ObserverRunner do
67
67
  describe "a runner with loaded observers", :testing_manager do
68
68
 
69
69
  before( :each ) do
70
+ @manager = nil
70
71
  @manager_thread = Thread.new do
71
72
  @manager = make_testing_manager()
72
73
  Thread.current.abort_on_exception = true
@@ -172,6 +172,8 @@ RSpec.configure do |config|
172
172
  config.mock_with( :rspec ) do |mock|
173
173
  mock.syntax = :expect
174
174
  end
175
+ config.warnings = true
176
+ config.profile_examples = 5
175
177
 
176
178
  config.after( :each ) do
177
179
  Arborist::Node::Root.reset
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: arborist
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Michael Granger
@@ -36,7 +36,7 @@ cert_chain:
36
36
  X0qdrKi+2aZZ0NGuFj9AItBsVmAvkBGIpX4TEKQp5haEbPpmaqO5nIIhV26PXmyT
37
37
  OMKv6pWsoS81vw5KAGBmfX8nht/Py90DQrbRvakATGI=
38
38
  -----END CERTIFICATE-----
39
- date: 2018-08-09 00:00:00.000000000 Z
39
+ date: 2018-08-29 00:00:00.000000000 Z
40
40
  dependencies:
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: schedulability
@@ -378,6 +378,7 @@ files:
378
378
  - lib/arborist/command/client.rb
379
379
  - lib/arborist/command/config.rb
380
380
  - lib/arborist/command/reset.rb
381
+ - lib/arborist/command/run_once.rb
381
382
  - lib/arborist/command/start.rb
382
383
  - lib/arborist/command/summary.rb
383
384
  - lib/arborist/command/tree.rb
metadata.gz.sig CHANGED
Binary file