arborist 0.2.0 → 0.3.0

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
  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