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.
- data/History.md +28 -0
- data/README.md +8 -6
- data/examples/bean_hash/README +2 -0
- data/examples/bean_hash/config.ru +9 -0
- data/examples/bean_hash/my_bean.rb +44 -0
- data/examples/bean_list/my_bean.rb +3 -3
- data/examples/embedded/my_bean.rb +3 -2
- data/examples/hash/README +2 -0
- data/examples/hash/config.ru +9 -0
- data/examples/hash/my_bean.rb +30 -0
- data/examples/list/my_bean.rb +5 -2
- data/examples/monitor_script/README +8 -0
- data/examples/monitor_script/rumx_attributes +67 -0
- data/examples/simple/config.ru +3 -1
- data/examples/simple/my_other_bean.rb +11 -0
- data/examples/timer/README +1 -1
- data/examples/timer/my_bean.rb +2 -1
- data/examples/timer_hash/README +2 -0
- data/examples/timer_hash/config.ru +9 -0
- data/examples/timer_hash/my_bean.rb +29 -0
- data/lib/rumx.rb +5 -0
- data/lib/rumx/attribute.rb +26 -17
- data/lib/rumx/attribute_info.rb +12 -0
- data/lib/rumx/bean.rb +146 -248
- data/lib/rumx/beans.rb +2 -0
- data/lib/rumx/beans/error.rb +1 -1
- data/lib/rumx/beans/hash.rb +34 -0
- data/lib/rumx/beans/timer.rb +2 -2
- data/lib/rumx/beans/timer_and_error.rb +1 -1
- data/lib/rumx/beans/timer_hash.rb +9 -0
- data/lib/rumx/hash_attribute.rb +39 -0
- data/lib/rumx/hash_bean.rb +55 -0
- data/lib/rumx/list_attribute.rb +65 -0
- data/lib/rumx/list_bean.rb +52 -0
- data/lib/rumx/server.rb +65 -69
- data/lib/rumx/server/views/attribute_value_tag.haml +3 -3
- data/lib/rumx/server/views/content_attributes.haml +4 -4
- data/lib/rumx/server/views/content_operations.haml +2 -2
- data/lib/rumx/server/views/tree_bean_attributes.haml +0 -4
- data/lib/rumx/server/views/tree_bean_operations.haml +2 -2
- data/lib/rumx/type.rb +15 -7
- metadata +21 -3
- 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(:
|
55
|
-
my_folder.bean_add_child(:
|
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,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
|
18
|
-
|
19
|
-
|
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,
|
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,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
|
+
|
data/examples/list/my_bean.rb
CHANGED
@@ -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
|
-
|
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
|
data/examples/simple/config.ru
CHANGED
@@ -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
|
data/examples/timer/README
CHANGED
@@ -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.
|
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
|
|
data/examples/timer/my_bean.rb
CHANGED
@@ -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,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'
|
data/lib/rumx/attribute.rb
CHANGED
@@ -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,
|
5
|
+
def initialize(name, type, description, allow_read, allow_write, options)
|
6
6
|
@name = name.to_sym
|
7
|
-
@type =
|
7
|
+
@type = type
|
8
8
|
@description = description
|
9
|
-
|
10
|
-
@
|
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
|
-
|
16
|
-
bean.send(self.name)
|
16
|
+
@allow_read ? bean.send(@name) : nil
|
17
17
|
end
|
18
18
|
|
19
|
-
def
|
20
|
-
|
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
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
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
|