arborist 0.0.1.pre20160128152542 → 0.0.1.pre20160606141735

Sign up to get free protection for your applications and to get access to all the features.
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
  #