rumx 0.0.8 → 0.1.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.
Files changed (43) hide show
  1. data/History.md +28 -0
  2. data/README.md +8 -6
  3. data/examples/bean_hash/README +2 -0
  4. data/examples/bean_hash/config.ru +9 -0
  5. data/examples/bean_hash/my_bean.rb +44 -0
  6. data/examples/bean_list/my_bean.rb +3 -3
  7. data/examples/embedded/my_bean.rb +3 -2
  8. data/examples/hash/README +2 -0
  9. data/examples/hash/config.ru +9 -0
  10. data/examples/hash/my_bean.rb +30 -0
  11. data/examples/list/my_bean.rb +5 -2
  12. data/examples/monitor_script/README +8 -0
  13. data/examples/monitor_script/rumx_attributes +67 -0
  14. data/examples/simple/config.ru +3 -1
  15. data/examples/simple/my_other_bean.rb +11 -0
  16. data/examples/timer/README +1 -1
  17. data/examples/timer/my_bean.rb +2 -1
  18. data/examples/timer_hash/README +2 -0
  19. data/examples/timer_hash/config.ru +9 -0
  20. data/examples/timer_hash/my_bean.rb +29 -0
  21. data/lib/rumx.rb +5 -0
  22. data/lib/rumx/attribute.rb +26 -17
  23. data/lib/rumx/attribute_info.rb +12 -0
  24. data/lib/rumx/bean.rb +146 -248
  25. data/lib/rumx/beans.rb +2 -0
  26. data/lib/rumx/beans/error.rb +1 -1
  27. data/lib/rumx/beans/hash.rb +34 -0
  28. data/lib/rumx/beans/timer.rb +2 -2
  29. data/lib/rumx/beans/timer_and_error.rb +1 -1
  30. data/lib/rumx/beans/timer_hash.rb +9 -0
  31. data/lib/rumx/hash_attribute.rb +39 -0
  32. data/lib/rumx/hash_bean.rb +55 -0
  33. data/lib/rumx/list_attribute.rb +65 -0
  34. data/lib/rumx/list_bean.rb +52 -0
  35. data/lib/rumx/server.rb +65 -69
  36. data/lib/rumx/server/views/attribute_value_tag.haml +3 -3
  37. data/lib/rumx/server/views/content_attributes.haml +4 -4
  38. data/lib/rumx/server/views/content_operations.haml +2 -2
  39. data/lib/rumx/server/views/tree_bean_attributes.haml +0 -4
  40. data/lib/rumx/server/views/tree_bean_operations.haml +2 -2
  41. data/lib/rumx/type.rb +15 -7
  42. metadata +21 -3
  43. data/lib/rumx/server/views/content_attribute.haml +0 -35
data/History.md CHANGED
@@ -1,6 +1,34 @@
1
1
  Rumx Changelog
2
2
  =====================
3
3
 
4
+ 0.1.0
5
+
6
+ - Removed the following methods and the equivalient writers and accessors to hopefully make the commands more consistent:
7
+
8
+ OLD: bean_list_reader :foo, :string, 'Description'
9
+ NEW: bean_reader :foo, :list, 'Description', :list_type => :string
10
+
11
+ OLD: bean_list_attr_reader :foo, :string, 'Description'
12
+ NEW: bean_attr_reader :foo, :list, 'Description', :list_type => :string, :allow_write => true #Use allow_write if the accessing of list elements is different from the list.
13
+
14
+ OLD: bean_embed :foo, 'Description'
15
+ NEW: bean_reader :foo, :bean, 'Description'
16
+
17
+ OLD: bean_attr_embed :foo, 'Description'
18
+ NEW: bean_attr_reader :foo, :bean, 'Description'
19
+
20
+ OLD: bean_embed_list :foo, 'Description'
21
+ NEW: bean_reader :foo, :list, 'Description', :list_type => :bean
22
+
23
+ OLD: bean_attr_embed_list :foo, 'Description'
24
+ NEW: bean_attr_reader :foo, :list, 'Description', :list_type => :bean
25
+
26
+ - Added Hash type
27
+
28
+ - A lot of restructuring of the code so it isn't quite as repetitive for the bean iteration and such.
29
+
30
+ - Added example/monitor_script for an example script that could be used with a tool like munin or hyperic.
31
+
4
32
  0.0.8
5
33
 
6
34
  - Added /attributes query which can retrieve attributes for multiple beans in one call.
data/README.md CHANGED
@@ -6,7 +6,9 @@ http://github.com/ClarityServices/rumx
6
6
 
7
7
  Ruby Management Extensions
8
8
 
9
- Allows you to easily implement management interfaces for your Ruby application.
9
+ Allows you to easily implement management interfaces for your Ruby application by adding
10
+ Rumx beans. A Rumx bean is an object that allows external access to specified attributes
11
+ and operations. It is basically equivalent to a JMX MBean.
10
12
 
11
13
  ## Install:
12
14
 
@@ -51,8 +53,8 @@ Note that all Rumx::Bean public methods are prefixed with "bean_" to help avoid
51
53
  You create a tree of beans under Rumx::Bean.root. For instance, you might create a tree for the bean above with the following commands:
52
54
 
53
55
  my_folder = Rumx::Beans::Folder.new
54
- Rumx::Bean.root.bean_add_child(:my_folder, my_folder)
55
- my_folder.bean_add_child(:my_bean, MyBean.new)
56
+ Rumx::Bean.root.bean_add_child(:MyFolder, my_folder)
57
+ my_folder.bean_add_child(:MyBean, MyBean.new)
56
58
 
57
59
  Rumx includes a Sinatra server app called Rumx::Server. You could startup a server by creating the following config.ru and running "rackup -p 4567"
58
60
 
@@ -87,8 +89,10 @@ Refer to the timer example for more information.
87
89
 
88
90
  ## TODO
89
91
 
92
+ I'm rewriting the list logic. List stuff will soon be deprecated.
93
+
90
94
  Figure out the "NameError - uninitialized constant Rack::File:" error that occurs frequently on startup and seems related
91
- to the tree not displaying correctly. Works okay with refresh.
95
+ to the tree not displaying correctly. Works okay with refresh. (Current workaround is to require 'rack/file in server.rb)
92
96
 
93
97
  Api doc non-existent.
94
98
 
@@ -103,8 +107,6 @@ Allow validations in attribute declarations?
103
107
 
104
108
  New types :date and :datetime?
105
109
 
106
- Build in optional authentication or just let user extend Rumx::Server?
107
-
108
110
  Railtie it?
109
111
 
110
112
  ## Author
@@ -0,0 +1,2 @@
1
+ 1) Execute 'rackup -p 4567'
2
+ 2) Browse to http://localhost:4567, expand the tree and view/update the attributes and operations
@@ -0,0 +1,9 @@
1
+ # Allow examples to be run in-place without requiring a gem install
2
+ $LOAD_PATH.unshift File.dirname(__FILE__) + '/../../lib'
3
+
4
+ require 'rubygems'
5
+ require 'rumx'
6
+ require 'my_bean'
7
+
8
+ Rumx::Bean.root.bean_add_child(:MyBean, MyBean.new)
9
+ run Rumx::Server
@@ -0,0 +1,44 @@
1
+ require 'rumx'
2
+
3
+ class MyEntryBean
4
+ include Rumx::Bean
5
+
6
+ bean_attr_accessor :my_int, :integer, 'My integer'
7
+ bean_attr_reader :my_string, :string, 'My string'
8
+
9
+ def initialize(my_int, my_string)
10
+ @my_int, @my_string = my_int, my_string
11
+ end
12
+ end
13
+
14
+ class MyBean
15
+ include Rumx::Bean
16
+
17
+ bean_attr_reader :entries, :hash, 'My entries', :hash_type => :bean
18
+
19
+ bean_operation :put_entry, :void, 'Put entry into hash', [
20
+ [ :key, :symbol, 'Hash key'],
21
+ [ :my_int, :integer, 'An integer argument' ],
22
+ [ :my_string, :string, 'A string argument' ]
23
+ ]
24
+
25
+ bean_operation :remove_entry, :void, 'Remove entry from hash', [
26
+ [ :key, :symbol, 'Hash key']
27
+ ]
28
+
29
+ def initialize
30
+ @entries = {:foo => MyEntryBean.new(1, '#1')}
31
+ end
32
+
33
+ def put_entry(key, my_int, my_string)
34
+ @entries[key] = MyEntryBean.new(my_int, my_string)
35
+ return my_string
36
+ end
37
+
38
+ def remove_entry(key)
39
+ removed = @entries.delete(key)
40
+ return 'None' unless removed
41
+ return removed.my_string
42
+ end
43
+ end
44
+
@@ -14,9 +14,9 @@ end
14
14
  class MyBean
15
15
  include Rumx::Bean
16
16
 
17
- bean_attr_reader :greeting, :string, 'My greeting'
18
-
19
- bean_attr_embed_list :entries, 'My entries'
17
+ bean_attr_reader :greeting, :string, 'My greeting'
18
+ # old bean_attr_embed_list :entries, 'My entries'
19
+ bean_attr_reader :entries, :list, 'My entries', :list_type => :bean
20
20
 
21
21
  bean_operation :push_entry, :void, 'Push entry onto entry list', [
22
22
  [ :my_int, :integer, 'An integer argument' ],
@@ -4,8 +4,9 @@ require 'my_embedded_bean'
4
4
  class MyBean
5
5
  include Rumx::Bean
6
6
 
7
- bean_attr_accessor :greeting, :string, 'My greeting'
8
- bean_attr_embed :embedded, 'My embedded bean'
7
+ bean_attr_accessor :greeting, :string, 'My greeting'
8
+ #old bean_attr_embed :embedded, 'My embedded bean'
9
+ bean_attr_reader :embedded, :bean, 'My embedded bean'
9
10
 
10
11
  bean_operation :my_operation, :string, 'My operation', [
11
12
  [ :arg_int, :integer, 'An int argument' ]
@@ -0,0 +1,2 @@
1
+ 1) Execute 'rackup -p 4567'
2
+ 2) Browse to http://localhost:4567, expand the tree and view/update the attributes and operations
@@ -0,0 +1,9 @@
1
+ # Allow examples to be run in-place without requiring a gem install
2
+ $LOAD_PATH.unshift File.dirname(__FILE__) + '/../../lib'
3
+
4
+ require 'rubygems'
5
+ require 'rumx'
6
+ require 'my_bean'
7
+
8
+ Rumx::Bean.root.bean_add_child(:MyBean, MyBean.new)
9
+ run Rumx::Server
@@ -0,0 +1,30 @@
1
+ require 'rumx'
2
+
3
+ class MyBean
4
+ include Rumx::Bean
5
+
6
+ bean_attr_reader :messages, :hash, 'Message', :hash_type => :string, :allow_write => true
7
+
8
+ bean_operation :put_message, :string, 'Put message onto message hash', [
9
+ [ :key, :symbol, 'The hash key'],
10
+ [ :message, :string, 'The message' ]
11
+ ]
12
+
13
+ bean_operation :remove_message, :string, 'Remove message from message hash', [
14
+ [ :key, :symbol, 'The hash key']
15
+ ]
16
+
17
+ def initialize
18
+ @messages = {:foo => 'Foo message', :bar => 'Bar message'}
19
+ end
20
+
21
+ def put_message(key, message)
22
+ @messages[key] = message
23
+ return message
24
+ end
25
+
26
+ def remove_message(key)
27
+ @messages.delete(key)
28
+ end
29
+ end
30
+
@@ -3,8 +3,11 @@ require 'rumx'
3
3
  class MyBean
4
4
  include Rumx::Bean
5
5
 
6
- bean_attr_accessor :max_messages, :integer, 'The maximum number of messages to keep'
7
- bean_list_attr_accessor :messages, :string, 'Message', :max_size => :max_messages
6
+ # old bean_attr_accessor :max_messages, :integer, 'The maximum number of messages to keep'
7
+ bean_attr_accessor :max_messages, :integer, 'The maximum number of messages to keep'
8
+ # old bean_list_attr_accessor :messages, :string, 'Message', :max_size => :max_messages
9
+ # Uncomment allow_write part to allow write access to individual messages
10
+ bean_attr_reader :messages, :list, 'Message', :list_type => :string, :max_size => :max_messages#, :allow_write => true
8
11
 
9
12
  bean_operation :push_message, :string, 'Push message onto message list', [
10
13
  [ :message, :string, 'A string argument' ]
@@ -0,0 +1,8 @@
1
+ Startup example/simple and try the following:
2
+
3
+ ./rumx_attributes MyFolder/MyBean
4
+ ./rumx_attributes MyFolder/MyBean MyFolder/MyOtherBean
5
+ ./rumx_attributes bean=MyFolder/MyBean other=MyFolder/MyOtherBean
6
+ # Query params for GETs won't show until the next time you query
7
+ ./rumx_attributes bean=MyFolder/MyBean?my_accessor=42\&my_writer=123.45 other=MyFolder/MyOtherBean
8
+ ./rumx_attributes bean=MyFolder/MyBean other=MyFolder/MyOtherBean
@@ -0,0 +1,67 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'rubygems'
4
+ require 'net/http'
5
+ require 'optparse'
6
+ require 'cgi'
7
+
8
+ class MyOptions < Hash
9
+ def initialize(argv)
10
+ super
11
+
12
+ opts = OptionParser.new do |opts|
13
+ opts.banner = "Usage: #$0 [options]"
14
+
15
+ # Default values
16
+ self[:host] = 'localhost'
17
+ self[:port] = 4567
18
+ self[:username] = nil
19
+ self[:password] = nil
20
+ self[:format] = 'properties'
21
+ self[:mount] = nil
22
+
23
+ opts.on('-H', '--host [HOST]', "host to hit (defaults to #{self[:host]})") do |val|
24
+ self[:host] = val
25
+ end
26
+
27
+ opts.on('-P', '--port [PORT]', Integer, "port number to hit (defaults to #{self[:port]})") do |val|
28
+ self[:port] = val
29
+ end
30
+
31
+ opts.on('-u', '--username [USERNAME]', "username for basic authentication") do |val|
32
+ self[:username] = val
33
+ end
34
+
35
+ opts.on('-p', '--password [PASSWORD]', "password for basic authentication") do |val|
36
+ self[:password] = val
37
+ end
38
+
39
+ opts.on('-f', '--format [FORMAT]', "format of the returned data (json or properties, defaults to #{self[:format]}") do |val|
40
+ self[:format] = val
41
+ end
42
+
43
+ opts.on('-m', '--mount [PATH]', "path where the Rumx app is mounted") do |val|
44
+ self[:format] = val
45
+ end
46
+ end
47
+
48
+ opts.parse!(argv)
49
+ end
50
+ end
51
+
52
+ options = MyOptions.new(ARGV)
53
+
54
+ # Args can be of the form Myfolder/Subfolder/Foo?reset=true which will expand to <mount>/attributes.<format>?query0=Myfolder/Subfolder/Foo/attributes?reset=true&query1=etc
55
+ path = "/attributes.#{options[:format]}?"
56
+ path = options[:mount] + path if options[:mount]
57
+ ARGV.each_with_index do |query, index|
58
+ path += '&' if index > 0
59
+ path += "query_#{index}=#{CGI.escape(query)}"
60
+ end
61
+
62
+ req = Net::HTTP::Get.new(path)
63
+ req.basic_auth(options[:username], options[:password]) if options[:username]
64
+ res = Net::HTTP.start(options[:host], options[:port]) { |http| http.request(req) }
65
+ if res.kind_of?(Net::HTTPSuccess)
66
+ puts res.body
67
+ end
@@ -3,9 +3,11 @@ $LOAD_PATH.unshift File.dirname(__FILE__) + '/../../lib'
3
3
 
4
4
  require 'rubygems'
5
5
  require 'rumx'
6
- require 'my_bean'
6
+ require './my_bean'
7
+ require './my_other_bean'
7
8
 
8
9
  my_folder = Rumx::Beans::Folder.new
9
10
  Rumx::Bean.root.bean_add_child(:MyFolder, my_folder)
10
11
  my_folder.bean_add_child(:MyBean, MyBean.new)
12
+ my_folder.bean_add_child(:MyOtherBean, MyOtherBean.new)
11
13
  run Rumx::Server
@@ -0,0 +1,11 @@
1
+ require 'rumx'
2
+
3
+ class MyOtherBean
4
+ include Rumx::Bean
5
+
6
+ bean_attr_accessor :message, :string, 'A message'
7
+
8
+ def initialize
9
+ @message = "I'm just here to put another bean in the mix"
10
+ end
11
+ end
@@ -1,7 +1,7 @@
1
1
  1) Execute 'rackup -p 4567'
2
2
  2) Browse to http://localhost:4567, expand the tree and view/update the attributes and operations
3
3
  3) Browse to http://localhost:4567/MyBean/timer/attributes.json and refresh the screen every so often.
4
- 4) Browse to http://localhost:4567/MyBean/timer/attributes.json?reset=true and refresh the screen every so often.
4
+ 4) Browse to http://localhost:4567/MyBean/timer/attributes.properties?reset=true and refresh the screen every so often.
5
5
  Note that a tool like munin, nagios, or hyperic could poll this url to monitor the timer and graph the results
6
6
  or create alerts based on exceeding some threshold.
7
7
 
@@ -3,13 +3,14 @@ class MyBean
3
3
 
4
4
  bean_attr_accessor :sleep_time, :float, 'Amount of time in seconds my measured block sleeps'
5
5
  bean_attr_accessor :percent_failure, :integer, 'Percentage of time the measured block will fail'
6
- bean_attr_embed :timer, 'Timer for our sleep action'
7
6
 
8
7
  def initialize
9
8
  @sleep_time = 0.5
10
9
  @percent_failure = 10
11
10
  @timer = Rumx::Beans::TimerAndError.new(:max_errors => 5)
12
11
 
12
+ bean_add_child(:timer, @timer)
13
+
13
14
  Thread.new do
14
15
  while true
15
16
  begin
@@ -0,0 +1,2 @@
1
+ 1) Execute 'rackup -p 4567'
2
+ 2) Browse to http://localhost:4567, expand the tree and view/update the attributes and operations
@@ -0,0 +1,9 @@
1
+ # Allow examples to be run in-place without requiring a gem install
2
+ $LOAD_PATH.unshift File.dirname(__FILE__) + '/../../lib'
3
+
4
+ require 'rubygems'
5
+ require 'rumx'
6
+ require 'my_bean'
7
+
8
+ Rumx::Bean.root.bean_add_child(:MyBean, MyBean.new)
9
+ run Rumx::Server
@@ -0,0 +1,29 @@
1
+ require 'rumx'
2
+
3
+ class MyBean
4
+ include Rumx::Bean
5
+
6
+ bean_attr_accessor :sleep1, :float, 'Amount of time sleep1 sleeps'
7
+ bean_attr_accessor :sleep2, :float, 'Amount of time sleep2 sleeps'
8
+ bean_attr_accessor :sleep3, :float, 'Amount of time sleep3 sleeps'
9
+
10
+ def initialize
11
+ @sleep1 = 1
12
+ @sleep2 = 2
13
+ @sleep3 = 3
14
+ @timers = Rumx::Beans::TimerHash.new
15
+ bean_add_child(:timers, @timers)
16
+ 100.times do
17
+ Thread.new do
18
+ while true
19
+ @timers[:overall].measure do
20
+ @timers[:sleep1].measure { sleep @sleep1 }
21
+ @timers[:sleep2].measure { sleep @sleep2 }
22
+ @timers[:sleep3].measure { sleep @sleep3 }
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
29
+
data/lib/rumx.rb CHANGED
@@ -1,7 +1,12 @@
1
1
  require 'rumx/argument'
2
2
  require 'rumx/attribute'
3
+ require 'rumx/attribute_info'
4
+ require 'rumx/list_attribute'
5
+ require 'rumx/hash_attribute'
3
6
  require 'rumx/operation'
4
7
  require 'rumx/bean'
8
+ require 'rumx/list_bean'
9
+ require 'rumx/hash_bean'
5
10
  require 'rumx/type'
6
11
  require 'rumx/server'
7
12
  require 'rumx/beans'
@@ -2,37 +2,46 @@ module Rumx
2
2
  class Attribute
3
3
  attr_reader :name, :type, :description, :allow_read, :allow_write
4
4
 
5
- def initialize(name, type_name, description, allow_read, allow_write, options)
5
+ def initialize(name, type, description, allow_read, allow_write, options)
6
6
  @name = name.to_sym
7
- @type = Type.find(type_name)
7
+ @type = type
8
8
  @description = description
9
- @allow_read = allow_read
10
- @allow_write = allow_write
9
+ # List and hash attributes might set up the object for reading but the individual elements for writing
10
+ @allow_read = options[:allow_read] || allow_read
11
+ @allow_write = options[:allow_write] || allow_write
11
12
  @options = options
12
13
  end
13
14
 
14
15
  def get_value(bean)
15
- return nil unless @allow_read
16
- bean.send(self.name)
16
+ @allow_read ? bean.send(@name) : nil
17
17
  end
18
18
 
19
- def set_value(bean, value)
20
- raise 'Illegal set_value' unless @allow_write
21
- bean.send(self.name.to_s+'=', type.string_to_value(value))
19
+ def each_attribute_info(bean, ancestry, &block)
20
+ yield AttributeInfo.new(self, bean, ancestry+[@name], get_value(bean))
22
21
  end
23
22
 
24
- def get_index_value(obj, index)
25
- return nil unless @allow_read
26
- return obj[index]
27
- end
28
-
29
- def set_index_value(obj, index, value)
30
- raise 'Illegal set_index_value' unless @allow_write
31
- obj[index] = type.string_to_value(value)
23
+ def write?(bean, params)
24
+ if @allow_write
25
+ param_value(params) do |value|
26
+ bean.send(@name.to_s+'=', @type.string_to_value(value))
27
+ return true
28
+ end
29
+ end
30
+ return false
32
31
  end
33
32
 
34
33
  def [](key)
35
34
  @options[key]
36
35
  end
36
+
37
+ protected
38
+
39
+ def param_value(params, &block)
40
+ if params.has_key?(@name)
41
+ yield params[@name]
42
+ elsif params.has_key?(@name.to_s)
43
+ yield params[@name.to_s]
44
+ end
45
+ end
37
46
  end
38
47
  end