arborist 0.0.1.pre20160128152542 → 0.0.1.pre20160606141735

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 (66) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data.tar.gz.sig +2 -0
  4. data/ChangeLog +426 -1
  5. data/Manifest.txt +17 -2
  6. data/Nodes.md +70 -0
  7. data/Protocol.md +68 -9
  8. data/README.md +3 -5
  9. data/Rakefile +4 -1
  10. data/TODO.md +52 -20
  11. data/lib/arborist.rb +19 -6
  12. data/lib/arborist/cli.rb +39 -25
  13. data/lib/arborist/client.rb +97 -4
  14. data/lib/arborist/command/client.rb +2 -1
  15. data/lib/arborist/command/start.rb +51 -5
  16. data/lib/arborist/dependency.rb +286 -0
  17. data/lib/arborist/event.rb +7 -2
  18. data/lib/arborist/event/{node_matching.rb → node.rb} +11 -5
  19. data/lib/arborist/event/node_acked.rb +5 -7
  20. data/lib/arborist/event/node_delta.rb +30 -3
  21. data/lib/arborist/event/node_disabled.rb +16 -0
  22. data/lib/arborist/event/node_down.rb +10 -0
  23. data/lib/arborist/event/node_quieted.rb +11 -0
  24. data/lib/arborist/event/node_unknown.rb +10 -0
  25. data/lib/arborist/event/node_up.rb +10 -0
  26. data/lib/arborist/event/node_update.rb +2 -11
  27. data/lib/arborist/event/sys_node_added.rb +10 -0
  28. data/lib/arborist/event/sys_node_removed.rb +10 -0
  29. data/lib/arborist/exceptions.rb +4 -0
  30. data/lib/arborist/manager.rb +188 -18
  31. data/lib/arborist/manager/event_publisher.rb +1 -1
  32. data/lib/arborist/manager/tree_api.rb +92 -13
  33. data/lib/arborist/mixins.rb +17 -0
  34. data/lib/arborist/monitor.rb +10 -1
  35. data/lib/arborist/monitor/socket.rb +123 -2
  36. data/lib/arborist/monitor_runner.rb +6 -5
  37. data/lib/arborist/node.rb +420 -94
  38. data/lib/arborist/node/ack.rb +72 -0
  39. data/lib/arborist/node/host.rb +43 -8
  40. data/lib/arborist/node/resource.rb +73 -0
  41. data/lib/arborist/node/root.rb +6 -0
  42. data/lib/arborist/node/service.rb +89 -22
  43. data/lib/arborist/observer.rb +1 -1
  44. data/lib/arborist/subscription.rb +11 -6
  45. data/spec/arborist/client_spec.rb +93 -5
  46. data/spec/arborist/dependency_spec.rb +375 -0
  47. data/spec/arborist/event/node_delta_spec.rb +66 -0
  48. data/spec/arborist/event/node_down_spec.rb +84 -0
  49. data/spec/arborist/event/node_spec.rb +59 -0
  50. data/spec/arborist/event/node_update_spec.rb +14 -3
  51. data/spec/arborist/event_spec.rb +3 -3
  52. data/spec/arborist/manager/tree_api_spec.rb +295 -3
  53. data/spec/arborist/manager_spec.rb +240 -57
  54. data/spec/arborist/monitor_spec.rb +26 -3
  55. data/spec/arborist/node/ack_spec.rb +74 -0
  56. data/spec/arborist/node/host_spec.rb +79 -0
  57. data/spec/arborist/node/resource_spec.rb +56 -0
  58. data/spec/arborist/node/service_spec.rb +68 -2
  59. data/spec/arborist/node_spec.rb +288 -11
  60. data/spec/arborist/subscription_spec.rb +23 -14
  61. data/spec/arborist_spec.rb +0 -4
  62. data/spec/data/observers/webservices.rb +10 -2
  63. data/spec/spec_helper.rb +8 -0
  64. metadata +58 -15
  65. metadata.gz.sig +0 -0
  66. data/LICENSE +0 -29
@@ -3,7 +3,6 @@
3
3
  ChangeLog
4
4
  Events.md
5
5
  History.md
6
- LICENSE
7
6
  Manifest.txt
8
7
  Monitors.md
9
8
  Nodes.md
@@ -21,11 +20,19 @@ lib/arborist/command/client.rb
21
20
  lib/arborist/command/config.rb
22
21
  lib/arborist/command/start.rb
23
22
  lib/arborist/command/watch.rb
23
+ lib/arborist/dependency.rb
24
24
  lib/arborist/event.rb
25
+ lib/arborist/event/node.rb
25
26
  lib/arborist/event/node_acked.rb
26
27
  lib/arborist/event/node_delta.rb
27
- lib/arborist/event/node_matching.rb
28
+ lib/arborist/event/node_disabled.rb
29
+ lib/arborist/event/node_down.rb
30
+ lib/arborist/event/node_quieted.rb
31
+ lib/arborist/event/node_unknown.rb
32
+ lib/arborist/event/node_up.rb
28
33
  lib/arborist/event/node_update.rb
34
+ lib/arborist/event/sys_node_added.rb
35
+ lib/arborist/event/sys_node_removed.rb
29
36
  lib/arborist/event/sys_reloaded.rb
30
37
  lib/arborist/exceptions.rb
31
38
  lib/arborist/loader.rb
@@ -38,7 +45,9 @@ lib/arborist/monitor.rb
38
45
  lib/arborist/monitor/socket.rb
39
46
  lib/arborist/monitor_runner.rb
40
47
  lib/arborist/node.rb
48
+ lib/arborist/node/ack.rb
41
49
  lib/arborist/node/host.rb
50
+ lib/arborist/node/resource.rb
42
51
  lib/arborist/node/root.rb
43
52
  lib/arborist/node/service.rb
44
53
  lib/arborist/observer.rb
@@ -47,6 +56,10 @@ lib/arborist/observer/summarize.rb
47
56
  lib/arborist/observer_runner.rb
48
57
  lib/arborist/subscription.rb
49
58
  spec/arborist/client_spec.rb
59
+ spec/arborist/dependency_spec.rb
60
+ spec/arborist/event/node_delta_spec.rb
61
+ spec/arborist/event/node_down_spec.rb
62
+ spec/arborist/event/node_spec.rb
50
63
  spec/arborist/event/node_update_spec.rb
51
64
  spec/arborist/event_spec.rb
52
65
  spec/arborist/manager/event_publisher_spec.rb
@@ -56,7 +69,9 @@ spec/arborist/mixins_spec.rb
56
69
  spec/arborist/monitor/socket_spec.rb
57
70
  spec/arborist/monitor_runner_spec.rb
58
71
  spec/arborist/monitor_spec.rb
72
+ spec/arborist/node/ack_spec.rb
59
73
  spec/arborist/node/host_spec.rb
74
+ spec/arborist/node/resource_spec.rb
60
75
  spec/arborist/node/root_spec.rb
61
76
  spec/arborist/node/service_spec.rb
62
77
  spec/arborist/node_spec.rb
data/Nodes.md CHANGED
@@ -0,0 +1,70 @@
1
+ # Nodes
2
+
3
+
4
+
5
+ Arborist::Host 'sidonie' do
6
+ parent 'duir'
7
+ description "NAS and media server"
8
+ address '192.168.16.3'
9
+
10
+ tags :infrastructure,
11
+ :storage,
12
+ :media,
13
+ :rip_status_check
14
+
15
+ service 'ssh'
16
+ service 'demon-http', port: 6666, protocol: 'http'
17
+ service 'postgresql'
18
+
19
+ service 'smtp'
20
+
21
+ service 'http',
22
+ depends_on: 'postgresql'
23
+ service 'sabnzbd', port: 8080, protocol: 'http'
24
+ service 'sickbeard', port: 8081, protocol: 'http'
25
+ service 'pms', port: 32400, protocol: 'http'
26
+ service 'couchpotato', port: 5050, protocol: 'http'
27
+ end
28
+
29
+
30
+ Arborist::Host 'jhereg' do
31
+ parent 'duir'
32
+ description "Directory server"
33
+ address '192.168.16.7'
34
+
35
+ service 'ldaps'
36
+ end
37
+
38
+
39
+ Arborist::Host 'webserver' do
40
+ description "Public webserver"
41
+ address '54.16.62.181'
42
+
43
+ service 'http',
44
+ depends_on: 'foo'
45
+ depends_on: all_of( 'postgresql', 'daemon-http', on: 'sidonie' ),
46
+ all_of( 'ldaps', on: 'jhereg' )
47
+ end
48
+
49
+
50
+ An application server depends on one each of the 'http' services and 'ldaps' services
51
+ to be up.
52
+
53
+ Arborist::Host 'appserver1' do
54
+ description "Public application webserver"
55
+ address '54.16.62.185'
56
+ service 'http',
57
+ depends_on: all_of(
58
+ any_of( 'http', on: %w[service1 service2 service3] ),
59
+ any_of( 'ldaps', on: %w[directory1 directory2] ),
60
+ all_of( 'else', on: 'something' )
61
+ )
62
+ end
63
+
64
+
65
+ [ :all_of,
66
+ [ :any_of, 'service1-http', 'service2-http', 'service3-http' ],
67
+ [ :any_of, 'directory1-ldaps', 'directory2-ldaps' ],
68
+ 'something-else'
69
+ ]
70
+
@@ -1,6 +1,6 @@
1
1
  # Monitors
2
2
 
3
- ## Protocol
3
+ ## Basic Protocol
4
4
 
5
5
  ZMQ REQ socket, msgpack message consisting of an Array of two elements:
6
6
 
@@ -20,7 +20,25 @@ Header is a Map of the form:
20
20
  Body is either Nil, a Map of key-value pairs, or an Array of Maps appropriate to the `action`.
21
21
 
22
22
 
23
- ## status
23
+ ## Commands
24
+
25
+
26
+ ### «commandname»
27
+
28
+ «description»
29
+
30
+ #### Header
31
+
32
+ #### Body
33
+
34
+ #### Return
35
+
36
+ #### Examples
37
+
38
+
39
+
40
+
41
+ ### status
24
42
 
25
43
  Fetch the status of the Manager.
26
44
 
@@ -43,7 +61,13 @@ Response:
43
61
  }
44
62
 
45
63
 
46
- ## list
64
+ ### list
65
+
66
+ Retrieve an Array of Maps that describes all or part of the node tree.
67
+
68
+ #### Required
69
+ from the node with the specified `identifier`, or the root node if no `identifier` is specified.
70
+
47
71
 
48
72
  Request:
49
73
 
@@ -52,6 +76,7 @@ Request:
52
76
  action: list,
53
77
  version: 1
54
78
  [from: «identifier»]
79
+ [depth: «arg»]
55
80
  }
56
81
  ]
57
82
 
@@ -89,11 +114,9 @@ failure example:
89
114
  }
90
115
  ]
91
116
 
92
- Fetch a data structure describing the node tree from the node with the specified
93
- `identifier`, or the root node if no `identifier` is specified.
94
117
 
95
118
 
96
- ## fetch
119
+ ### fetch
97
120
 
98
121
  Fetch the `address`, `description`, and `status` of all nodes.
99
122
 
@@ -119,7 +142,7 @@ Fetch the `address`, `description`, and `status` of all nodes.
119
142
  ]
120
143
 
121
144
 
122
- ### return
145
+ #### return
123
146
 
124
147
  - not specified : returns everything.
125
148
  - `Nil` : returns just identifiers
@@ -128,7 +151,7 @@ Fetch the `address`, `description`, and `status` of all nodes.
128
151
  Search for nodes that match the filter given in the request body, returning a serialized map of node identifiers to requested state.
129
152
 
130
153
 
131
- ## update
154
+ ### update
132
155
 
133
156
  [
134
157
  {
@@ -164,7 +187,7 @@ With a failure:
164
187
  ]
165
188
 
166
189
 
167
- ## subscribe
190
+ ### subscribe
168
191
 
169
192
  Get node change delta events for every 'host' type node.
170
193
 
@@ -212,3 +235,39 @@ Get notified of every system event (startup, shutdown, reload, etc.)
212
235
  Nil
213
236
 
214
237
 
238
+ ### graft
239
+
240
+ {
241
+ action: graft,
242
+ version: 1,
243
+ type: 'host',
244
+ identifier: 'joliet',
245
+ parent: 'bennett' # defaults to root
246
+ },
247
+ {
248
+ addresses: [],
249
+ tags: []
250
+ }
251
+
252
+
253
+ ### prune
254
+
255
+ {
256
+ action: prune,
257
+ version: 1,
258
+ identifier: 'bennett'
259
+ },
260
+ Nil
261
+
262
+
263
+ ### modify
264
+
265
+ {
266
+ action: modify,
267
+ version: 1,
268
+ identifier: 'bennett'
269
+ },
270
+ {
271
+ addresses: ['10.13.0.22', '10.1.0.23']
272
+ }
273
+
data/README.md CHANGED
@@ -29,12 +29,10 @@ customizability.
29
29
 
30
30
  ## Installation
31
31
 
32
- $ gem install arborist
33
-
32
+ This isn't really ready for serious usage yet, but when it is you can install
33
+ it like so:
34
34
 
35
- ## Further Reading
36
-
37
- You'll likely want to start with [the Tutorial](Tutorial.html).
35
+ $ gem install arborist
38
36
 
39
37
 
40
38
  ## Contributing
data/Rakefile CHANGED
@@ -38,6 +38,8 @@ hoespec = Hoe.spec 'arborist' do |spec|
38
38
  spec.dependency 'state_machines', '~> 0.2'
39
39
  spec.dependency 'msgpack', '~> 0.6'
40
40
  spec.dependency 'rbczmq', '~> 1.7'
41
+ spec.dependency 'gli', '~> 2.3'
42
+ spec.dependency 'highline', '~> 1.7'
41
43
 
42
44
  spec.dependency 'rspec', '~> 3.2', :developer
43
45
  spec.dependency 'simplecov', '~> 0.9', :developer
@@ -80,10 +82,11 @@ if File.directory?( '.hg' )
80
82
  end
81
83
  end
82
84
 
83
- task :gemspec => GEMSPEC
85
+ task :gemspec => [ 'ChangeLog', GEMSPEC ]
84
86
  file GEMSPEC => __FILE__ do |task|
85
87
  spec = $hoespec.spec
86
88
  spec.files.delete( '.gemtest' )
89
+ spec.files.delete( 'LICENSE' )
87
90
  spec.signing_key = nil
88
91
  spec.version = "#{spec.version}.pre#{Time.now.strftime("%Y%m%d%H%M%S")}"
89
92
  File.open( task.name, 'w' ) do |fh|
data/TODO.md CHANGED
@@ -1,33 +1,65 @@
1
1
  # To-Do
2
2
 
3
- ## Manager
3
+ ## First Release (0.1)
4
4
 
5
- * Serialize nodes on shutdown
6
- * Include a node's subscriptions in its serialized data
7
- * Implement loading/reloading nodes.
8
- * Implement the system events (sys.acked, sys.reloaded, etc.)
5
+ * README, Tutorial, Setup docs
9
6
 
10
- ## Tree API
7
+ * Performance/profiling examination
11
8
 
12
- * Add "grafting": node add/removal
13
9
 
14
- ## Observers
10
+ ### Manager
15
11
 
16
- * Scheduling time periods for action/summarizing
17
- * Summarizing and Actions should be 1st order objects
18
- * Unsubscribe from Arborist and ZMQ subscriptions on shutdown
19
- * Figure out how to match on delta events: the criteria
20
- for matching nodes has to be separated from that which matches
21
- the delta pairs.
12
+ * Only restore timestamps from serialized node dependencies, not the deps themselves.
22
13
 
23
- ## Node
14
+ * Broadcast system events:
15
+ - `sys.node.added`
16
+ - `sys.node.removed`
17
+ - `sys.startup`
18
+ - `sys.shutdown`
24
19
 
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
20
 
21
+ ### Observers
28
22
 
29
- ## Setup/Installation
23
+ * Re-subscribe on `sys.startup`, `sys.reloaded`, `sys.node.added`
24
+ * Add `except` to observers DSL
30
25
 
31
- * Add a CLI for generating a basic setup and then adding
32
- nodes/monitors/observers to it.
33
26
 
27
+ ### Nodes
28
+
29
+ * Allow a service node to not inherit all of its host's addresses (i.e., be bound to one address only or whatever)
30
+ * Resource nodes: disk, load, process checks, etc. Anything that might
31
+ be considered a problem, that you'd want to ack independantly of the
32
+ Host node they are attached to.
33
+
34
+ ### Monitor
35
+
36
+ * Add some default monitor types and utilities
37
+ - UDP socket check
38
+ - Basic monitors for stdlib Net::* protocols/services
39
+ -
40
+
41
+ * Gems for monitor types that have external dependency
42
+ - SNMP
43
+
44
+ ### Watch Command
45
+
46
+ * Re-subscribe on `sys.startup`, `sys.reloaded`, `sys.node.added`
47
+
48
+
49
+ ## Second Release (0.2)
50
+
51
+ ### Setup/Installation
52
+
53
+ * Add a CLI for generating a basic setup and then adding nodes/monitors/observers to it.
54
+ * Potential federation / referral for sibling managers
55
+
56
+ ### Nodes
57
+
58
+ * Ask a node (via tree-api or otherwise) what nodes it affects (immediate children, secondary dependents)
59
+
60
+ ### Observers
61
+
62
+ * Action dependencies -- as an example, if an action sends an email,
63
+ don't trigger if the email service is offline. Potential action
64
+ "chains", ie: If the email service is down, use a separate
65
+ out-of-band action that sends SMS.
@@ -17,7 +17,7 @@ module Arborist
17
17
  VERSION = '0.0.1'
18
18
 
19
19
  # Version control revision
20
- REVISION = %q$Revision: e23d2b9f8f31 $
20
+ REVISION = %q$Revision: ed4f0655b4b6 $
21
21
 
22
22
 
23
23
  # The name of the environment variable which can be used to set the config path
@@ -32,7 +32,7 @@ module Arborist
32
32
  # Configurability API -- default configuration values
33
33
  CONFIG_DEFAULTS = {
34
34
  tree_api_url: 'ipc:///tmp/arborist_tree.sock',
35
- event_api_url: 'ipc:///tmp/arborist_events.sock'
35
+ event_api_url: 'ipc:///tmp/arborist_events.sock',
36
36
  }
37
37
 
38
38
 
@@ -103,10 +103,17 @@ module Arborist
103
103
 
104
104
  ### Add a constructor function to the Arborist namespace called +name+
105
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 )
106
+ def self::add_dsl_constructor( subclass, &method_body )
107
+ name = subclass.name
108
+
109
+ if name
110
+ name.sub!( /.*::/, '' )
111
+ self.log.debug "Adding factory method for %p: %p" % [ name, method_body ]
112
+ singleton_class.instance_exec( name, method_body ) do |name, body|
113
+ define_method( name, &body )
114
+ end
115
+ else
116
+ self.log.info "Skipping DSL constructor for anonymous class."
110
117
  end
111
118
  end
112
119
 
@@ -165,6 +172,12 @@ module Arborist
165
172
  end
166
173
 
167
174
 
175
+ ### Set the ZMQ context if it's already been created by something else.
176
+ def self::zmq_context=( existing_context )
177
+ @zmq_context = existing_context
178
+ end
179
+
180
+
168
181
  require 'arborist/exceptions'
169
182
  require 'arborist/mixins'
170
183
 
@@ -43,7 +43,7 @@ module Arborist::CLI
43
43
  version Arborist::VERSION
44
44
 
45
45
  # Use an OpenStruct for options instead of a Hash
46
- use_openstruct( true )
46
+ # use_openstruct( true )
47
47
 
48
48
  # Subcommand options are independent of global[:ones]
49
49
  subcommand_option_handling :normal
@@ -62,7 +62,8 @@ module Arborist::CLI
62
62
 
63
63
 
64
64
  # Global options
65
- desc "Specify the config file to load"
65
+ desc "Load the specified CONFIGFILE."
66
+ arg_name :CONFIGFILE
66
67
  flag [:c, :config], type: Pathname
67
68
 
68
69
  desc 'Enable debugging output'
@@ -72,7 +73,7 @@ module Arborist::CLI
72
73
  switch [:v, :verbose]
73
74
 
74
75
  desc 'Set log level to LEVEL (one of %s)' % [Loggability::LOG_LEVELS.keys.join(', ')]
75
- default_value Loggability[self].level
76
+ arg_name :LEVEL
76
77
  flag [:l, :loglevel], must_match: Loggability::LOG_LEVELS.keys
77
78
 
78
79
  desc "Don't actually do anything, just show what would happen."
@@ -86,24 +87,41 @@ module Arborist::CLI
86
87
  # GLI Event callbacks
87
88
  #
88
89
 
90
+ # Set up global options
89
91
  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
92
+ self.set_logging_level( global[:l] )
95
93
 
96
94
  # Include a 'lib' directory if there is one
97
95
  $LOAD_PATH.unshift( 'lib' ) if File.directory?( 'lib' )
98
96
 
99
- self.require_additional_libs( global.requires ) if global.requires
97
+ self.require_additional_libs( global[:r] ) if global[:r]
100
98
  self.load_config( global )
99
+ self.set_logging_level( global[:l] ) if global[:l] # again; override config file
101
100
  self.install_highline_colorscheme
102
101
 
102
+ self.setup_output( global )
103
+
103
104
  true
104
105
  end
105
106
 
106
107
 
108
+ # Write the error to the log on exceptions.
109
+ on_error do |exception|
110
+ case exception
111
+ when OptionParser::ParseError, GLI::CustomExit
112
+ self.log.debug( exception )
113
+ else
114
+ self.log.error( exception )
115
+ end
116
+
117
+ exception.backtrace.each {|frame| self.log.debug(frame) }
118
+
119
+ true
120
+ end
121
+
122
+
123
+
124
+
107
125
  ##
108
126
  # Registered subcommand modules
109
127
  singleton_attr_accessor :subcommand_modules
@@ -162,6 +180,16 @@ module Arborist::CLI
162
180
  end
163
181
 
164
182
 
183
+ ### Set the global logging +level+ if it's defined.
184
+ def self::set_logging_level( level=nil )
185
+ if level
186
+ Loggability.level = level.to_sym
187
+ else
188
+ Loggability.level = :fatal
189
+ end
190
+ end
191
+
192
+
165
193
  ### Load any additional Ruby libraries given with the -r global option.
166
194
  def self::require_additional_libs( requires)
167
195
  requires.each do |path|
@@ -181,6 +209,7 @@ module Arborist::CLI
181
209
  cs[:down] = [ :red ]
182
210
  cs[:unknown] = [ :dark, :yellow ]
183
211
  cs[:disabled] = [ :dark, :white ]
212
+ cs[:quieted] = [ :dark, :green ]
184
213
  cs[:acked] = [ :yellow ]
185
214
  cs[:highlight] = [ :bold, :yellow ]
186
215
  cs[:search_hit] = [ :black, :on_white ]
@@ -194,7 +223,7 @@ module Arborist::CLI
194
223
  ### Load the config file using either arborist-base's config-loader if available, or
195
224
  ### fall back to DEFAULT_CONFIG_FILE
196
225
  def self::load_config( global={} )
197
- Arborist.load_config( global.config ) if global.config
226
+ Arborist.load_config( global[:c] ) if global[:c]
198
227
 
199
228
  # Set up the logging formatter
200
229
  Loggability.format_with( :color ) if $stdout.tty?
@@ -224,21 +253,6 @@ module Arborist::CLI
224
253
  end
225
254
 
226
255
 
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
256
  #
243
257
  # GLI subcommands
244
258
  #