rboss 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (51) hide show
  1. data/.gitignore +9 -0
  2. data/Gemfile +4 -0
  3. data/Rakefile +1 -0
  4. data/bin/jboss-profile +90 -0
  5. data/bin/twiddle +230 -0
  6. data/examples/jboss_profile/jbb_profile_1.yaml +32 -0
  7. data/examples/jboss_profile/jbb_profile_2.yaml +32 -0
  8. data/examples/jboss_profile/jboss_profile.yaml +7 -0
  9. data/examples/monitor/simple_monitor.rb +61 -0
  10. data/lib/rboss.rb +25 -0
  11. data/lib/rboss/component_processor.rb +177 -0
  12. data/lib/rboss/components/component.rb +52 -0
  13. data/lib/rboss/components/datasource.rb +198 -0
  14. data/lib/rboss/components/deploy_folder.rb +104 -0
  15. data/lib/rboss/components/hypersonic_replacer.rb +58 -0
  16. data/lib/rboss/components/jbossweb.rb +117 -0
  17. data/lib/rboss/components/jmx.rb +88 -0
  18. data/lib/rboss/components/mod_cluster.rb +81 -0
  19. data/lib/rboss/components/org/6.0/deploy_folder.rb +33 -0
  20. data/lib/rboss/components/org/jmx.rb +59 -0
  21. data/lib/rboss/components/profile_folder.rb +44 -0
  22. data/lib/rboss/components/resource.rb +53 -0
  23. data/lib/rboss/components/run_conf.rb +90 -0
  24. data/lib/rboss/components/run_conf.yaml +22 -0
  25. data/lib/rboss/components/service_script.rb +55 -0
  26. data/lib/rboss/components/slimming.rb +124 -0
  27. data/lib/rboss/components/soa-p/hypersonic_replacer.rb +79 -0
  28. data/lib/rboss/components/soa-p/jmx.rb +47 -0
  29. data/lib/rboss/components/xadatasource.rb +67 -0
  30. data/lib/rboss/file_processor.rb +107 -0
  31. data/lib/rboss/jboss_path.rb +53 -0
  32. data/lib/rboss/jboss_profile.rb +344 -0
  33. data/lib/rboss/resources/jboss_init_redhat.sh.erb +140 -0
  34. data/lib/rboss/resources/mod_cluster.sar/META-INF/mod_cluster-jboss-beans.xml +282 -0
  35. data/lib/rboss/resources/mod_cluster.sar/mod_cluster-1.1.2.Final.jar +0 -0
  36. data/lib/rboss/resources/run.conf.erb +62 -0
  37. data/lib/rboss/twiddle.rb +25 -0
  38. data/lib/rboss/twiddle/base_monitor.rb +57 -0
  39. data/lib/rboss/twiddle/mbean.rb +82 -0
  40. data/lib/rboss/twiddle/monitor.rb +144 -0
  41. data/lib/rboss/twiddle/scanner.rb +92 -0
  42. data/lib/rboss/twiddle/twiddle.rb +71 -0
  43. data/lib/rboss/utils.rb +33 -0
  44. data/lib/rboss/version.rb +25 -0
  45. data/rboss.gemspec +20 -0
  46. data/test/datasource_test.rb +211 -0
  47. data/test/deploy_folder_test.rb +126 -0
  48. data/test/mbean_test.rb +53 -0
  49. data/test/test_helper.rb +124 -0
  50. data/test/test_suite.rb +35 -0
  51. metadata +109 -0
data/lib/rboss.rb ADDED
@@ -0,0 +1,25 @@
1
+ # The MIT License
2
+ #
3
+ # Copyright (c) 2011 Marcelo Guimarães <ataxexe@gmail.com>
4
+ #
5
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ # of this software and associated documentation files (the "Software"), to deal
7
+ # in the Software without restriction, including without limitation the rights
8
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ # copies of the Software, and to permit persons to whom the Software is
10
+ # furnished to do so, subject to the following conditions:
11
+ #
12
+ # The above copyright notice and this permission notice shall be included in
13
+ # all copies or substantial portions of the Software.
14
+ #
15
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ # THE SOFTWARE.
22
+
23
+ require_relative "rboss/version"
24
+ require_relative "rboss/jboss_profile"
25
+ require_relative "rboss/twiddle"
@@ -0,0 +1,177 @@
1
+ # The MIT License
2
+ #
3
+ # Copyright (c) 2011 Marcelo Guimarães <ataxexe@gmail.com>
4
+ #
5
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ # of this software and associated documentation files (the "Software"), to deal
7
+ # in the Software without restriction, including without limitation the rights
8
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ # copies of the Software, and to permit persons to whom the Software is
10
+ # furnished to do so, subject to the following conditions:
11
+ #
12
+ # The above copyright notice and this permission notice shall be included in
13
+ # all copies or substantial portions of the Software.
14
+ #
15
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ # THE SOFTWARE.
22
+
23
+ # A main class to process components based on a highly customizable set of parameters.
24
+ #
25
+ # 1. Creating a ComponentProcessor
26
+ # A ComponentProcessor needs a block that defines how to process a component. The block
27
+ # will receive the component type and the configuration.
28
+ #
29
+ # Example: ComponentProcessor::new do |component_type, configuration|
30
+ # component_type.new(configuration).process
31
+ # end
32
+ #
33
+ # 2. Registering a component
34
+ # Components need to be registered in the processor. The registration uses an id and a hash
35
+ # of parameters described bellow:
36
+ #
37
+ # :type => the type of the component. Only components with a defined type will be passed to the processor block
38
+ #
39
+ # :multiple_instances => a flag to indicate if this component can be added more than once
40
+ # :priority => a number defining a priority for this component to be processed
41
+ #
42
+ # :enabled => a flag to indicate if this component is enabled for processing by default
43
+ #
44
+ # :defaults => a hash containing the default config parameters for this component (only if the configuration is a Hash)
45
+ #
46
+ # :send_config => a hash for sending the configurations at process time to another component (only if the configuration
47
+ # is a Hash).
48
+ #
49
+ # The configuration keys are sending using the pattern :to_$COMPONENT_ID and supports key overriding
50
+ # Example:
51
+ # :send_config => {
52
+ # :to_bar_service => {
53
+ # :foo => :bar
54
+ # }
55
+ # :to_foo_service => [:foo]
56
+ # }
57
+ # The :foo config will be moved to the component :bar_service using :bar as the configuration key and to the component
58
+ # :foo_service using the same name as the key.
59
+ #
60
+ # :move_config => the same as for :send_config, but the configurations moved will not be passed to the block for this
61
+ # component.
62
+ #
63
+ # 3. Adding a component
64
+ #
65
+ # A component should be added by add method. You only need to specify the component id and the configuration (if needed).
66
+ # When a component is added, it will be processed for sending or moving configurations and, if the component has a type,
67
+ # it will be passed to the block for processing.
68
+ #
69
+ # author: Marcelo Guimarães <ataxexe@gmail.com>
70
+ class ComponentProcessor
71
+
72
+ def initialize &block
73
+ @process = block
74
+ @process ||= lambda { |type, config| type.new(config).process }
75
+ end
76
+
77
+ # Register a component using the given id (which must be used for adding it to process) and parameters
78
+ def register component_id, params
79
+ params = {
80
+ :type => nil,
81
+ :multiple_instances => false,
82
+ :priority => 0,
83
+ :enabled => false,
84
+ :defaults => {}
85
+ }.merge! params
86
+ @components ||= {}
87
+ params[:configs] ||= [] if params[:multiple_instances]
88
+ @components[component_id] = params unless @components.has_key? component_id
89
+ end
90
+
91
+ def add component_id, config = {}
92
+ registered_component = @components[component_id]
93
+ return unless registered_component
94
+ defaults = registered_component[:defaults]
95
+ registered_component[:enabled] = true
96
+ config = defaults.merge config if config.is_a? Hash
97
+ if registered_component[:multiple_instances]
98
+ registered_component[:configs] << config
99
+ else
100
+ registered_component[:config] = config
101
+ end
102
+ propagate_configs registered_component
103
+ end
104
+
105
+ def defaults component_id, defaults
106
+ registered_component = @components[component_id]
107
+ registered_component[:defaults] = defaults if registered_component
108
+ end
109
+
110
+ def process_components
111
+ enabled_components = @components.find_all {|component_id, params| params[:enabled]}
112
+ (enabled_components.sort_by { |key, value| value[:priority] }).each do |key, component|
113
+ process_component component
114
+ end
115
+ end
116
+
117
+ private
118
+
119
+ def process_component component
120
+ return unless component[:type]
121
+ if component[:multiple_instances]
122
+ component[:configs].each do |config|
123
+ @process.call component[:type], config
124
+ end
125
+ else
126
+ config = component[:config]
127
+ config ||= component[:defaults]
128
+ @process.call component[:type], config
129
+ end
130
+ end
131
+
132
+ def propagate_configs component
133
+ #TODO refactor this -----------------------------------
134
+ if component[:send_config] and component[:config].is_a? Hash
135
+ component[:send_config].each do |to, keys|
136
+ destination = to.to_s.gsub(/^to_/, '').to_sym
137
+ config = {}
138
+ if keys.is_a? Array
139
+ keys.each do |key|
140
+ config[key] = component[:config][key] if component[:config].has_key? key
141
+ end
142
+ elsif keys.is_a? Hash
143
+ keys.each do |k, v|
144
+ config[v] = component[:config][k] if component[:config].has_key? k
145
+ end
146
+ end
147
+ send_config destination, config
148
+ end
149
+ end
150
+ if component[:move_config] and component[:config].is_a? Hash
151
+ component[:move_config].each do |to, keys|
152
+ destination = to.to_s.gsub(/^to_/, '').to_sym
153
+ config = {}
154
+ if keys.is_a? Array
155
+ keys.each do |key|
156
+ config[key] = component[:config].delete key if component[:config].has_key? key
157
+ end
158
+ elsif keys.is_a? Hash
159
+ keys.each do |k, v|
160
+ config[v] = component[:config].delete k if component[:config].has_key? k
161
+ end
162
+ end
163
+ send_config destination, config, :enable_component => true
164
+ end
165
+ end
166
+ #------------------------------------------------------
167
+ end
168
+
169
+ def send_config component_id, config, opts = {}
170
+ component = @components[component_id]
171
+ component[:defaults] ||= {}
172
+ component_config = @components[component_id][:defaults]
173
+ component_config.merge! config
174
+ component[:enabled] = true if opts[:enable_component]
175
+ end
176
+
177
+ end
@@ -0,0 +1,52 @@
1
+ # The MIT License
2
+ #
3
+ # Copyright (c) 2011 Marcelo Guimarães <ataxexe@gmail.com>
4
+ #
5
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ # of this software and associated documentation files (the "Software"), to deal
7
+ # in the Software without restriction, including without limitation the rights
8
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ # copies of the Software, and to permit persons to whom the Software is
10
+ # furnished to do so, subject to the following conditions:
11
+ #
12
+ # The above copyright notice and this permission notice shall be included in
13
+ # all copies or substantial portions of the Software.
14
+ #
15
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ # THE SOFTWARE.
22
+
23
+ require_relative "../file_processor"
24
+ require_relative "../jboss_path"
25
+ require_relative "../utils"
26
+
27
+ module JBoss
28
+
29
+ # A base helper module for JBoss Components
30
+ #
31
+ # author: Marcelo Guimarães <ataxexe@gmail.com>
32
+ module Component
33
+
34
+ def initialize jboss, logger, config
35
+ @jboss = jboss
36
+ @logger = logger
37
+ config = defaults.merge! config if self.respond_to? :defaults
38
+ configure(config)
39
+ end
40
+
41
+ def configure config
42
+ @config = config
43
+ end
44
+
45
+ # Creates a FileProcessor using the same logger and
46
+ # jboss path as the variable
47
+ def new_file_processor
48
+ FileProcessor::new :logger => @logger, :var => @jboss
49
+ end
50
+
51
+ end
52
+ end
@@ -0,0 +1,198 @@
1
+ # The MIT License
2
+ #
3
+ # Copyright (c) 2011 Marcelo Guimarães <ataxexe@gmail.com>
4
+ #
5
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ # of this software and associated documentation files (the "Software"), to deal
7
+ # in the Software without restriction, including without limitation the rights
8
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ # copies of the Software, and to permit persons to whom the Software is
10
+ # furnished to do so, subject to the following conditions:
11
+ #
12
+ # The above copyright notice and this permission notice shall be included in
13
+ # all copies or substantial portions of the Software.
14
+ #
15
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ # THE SOFTWARE.
22
+
23
+ require_relative "component"
24
+
25
+ require "logger"
26
+ require "rexml/document"
27
+
28
+ include REXML
29
+
30
+ module JBoss
31
+
32
+ # A class to configure a JBoss Datasource.
33
+ #
34
+ # For converting the property (if it is a Symbol), the above rules are used taking by example a
35
+ # value ":database_url":
36
+ # a. The value "database_url"
37
+ # b. The value "database-url"
38
+ # c. The value "DatabaseUrl"
39
+ # d. The value "DATABASE_URL"
40
+ #
41
+ # The key for finding the correct datasource is the configuration attribute :type, which is used
42
+ # to search in $JBOSS_HOME/docs/examples/jca for the file.
43
+ #
44
+ # Any key that is not found in the datasource template will be added. If it is a Symbol, the underlines will be
45
+ # converted to hyphens.
46
+ #
47
+ # For saving the file, the configuration :name will be used in the form "${name}-ds.xml".
48
+ #
49
+ # Configuration:
50
+ #
51
+ # :folder => a folder where this datasource will be saved (default: $JBOSS_HOME/server/$CONFIG/deploy)
52
+ # if a relative path is given, it will be appended to default value
53
+ # :encrypt => a flag to indicate if the password should be encrypted (default: false)
54
+ # :type => the type of the datasource
55
+ # :name => a name for saving the file (default: :type)
56
+ # :attributes => a Hash with the attributes that will be changed in template (the only required is :jndi_name)
57
+ # Any attribute that is not present in datasource xml will be created using this template: <key>value</key>.
58
+ #
59
+ # author: Marcelo Guimarães <ataxexe@gmail.com>
60
+ class Datasource
61
+ include Component
62
+
63
+ attr_accessor :jndi_name, :attributes, :type, :name
64
+
65
+ def defaults
66
+ {
67
+ :folder => "#{@jboss.profile}/deploy",
68
+ :encrypt => false,
69
+ :attributes => {}
70
+ }
71
+ end
72
+
73
+ def configure config
74
+ config[:type] = :mssql if config[:type].to_s == "sqlserver"
75
+ @type = config[:type].to_s.gsub /_/, '-'
76
+ @name = config[:name]
77
+ @name ||= @type.to_s
78
+ @folder = config[:folder].to_s
79
+ @folder = "#{@jboss.profile}/#{@folder}" unless @folder.start_with? '/'
80
+ @attributes = config[:attributes]
81
+ @encrypt = config[:encrypt]
82
+ @jndi_name = @attributes.delete :jndi_name
83
+ end
84
+
85
+ def process
86
+ if @encrypt
87
+ @user = @attributes.delete :user
88
+ @user = @attributes.delete :user_name unless @user
89
+ @password = encrypt @attributes.delete :password
90
+ end
91
+ processor = new_file_processor
92
+ processor.with "#{@jboss.home}/docs/examples/jca/#{@type}-ds.xml", :xml do |action|
93
+ action.to_process do |xml, jboss|
94
+ element = XPath.first xml, "//jndi-name"
95
+ element.text = @jndi_name
96
+ configure_datasource xml
97
+
98
+ if @encrypt
99
+ security_domain = Element::new "security-domain"
100
+ security_domain.text = @name
101
+
102
+ xml.root.elements[1] << security_domain
103
+ end
104
+ action.copy_to "#{@folder}/#{@name}-ds.xml"
105
+ xml
106
+ end
107
+ end
108
+ @logger.info "Creating datasource #{@name}"
109
+ processor.process
110
+ if @encrypt
111
+ create_login_module
112
+ create_login_config
113
+ end
114
+ end
115
+
116
+ def find xml, key
117
+ if key.is_a? Symbol
118
+ key = key.to_s
119
+ [key, key.gsub(/_/, '-'), key.camelize, key.upcase].each do |k|
120
+ element = XPath.first xml, yield(k)
121
+ return element if element
122
+ end
123
+ else
124
+ XPath.first xml, yield(key)
125
+ end
126
+ nil
127
+ end
128
+
129
+ def configure_datasource xml
130
+ if @encrypt
131
+ xml.root.delete_element "//user-name"
132
+ xml.root.delete_element "//password"
133
+ @service = "LocalTxCM"
134
+ end
135
+ @attributes.each do |key, value|
136
+ element = find(xml, key) { |k| "//#{k}" }
137
+
138
+ if element
139
+ element.text = value
140
+ else
141
+ insert_attribute xml, key, value
142
+ end
143
+ end
144
+ end
145
+
146
+ def insert_attribute xml, key, value
147
+ if key.is_a? Symbol
148
+ element = Element::new key.to_s.gsub /_/, '-'
149
+ else
150
+ element = Element::new key
151
+ end
152
+ element.text = value
153
+ xml.root.elements[1] << element
154
+ end
155
+
156
+ def create_login_config
157
+ File.open("#{@folder}/#{@name}.login-module.xml", 'w+') { |f| f.write @login_module }
158
+ end
159
+
160
+ def create_login_module
161
+ @login_module = Document::new <<XML
162
+ <policy>
163
+ <application-policy name='#{@name}'>
164
+ <authentication>
165
+ <login-module code='org.jboss.resource.security.SecureIdentityLoginModule' flag='required'>
166
+ <module-option name='username'>#{@user}</module-option>
167
+ <module-option name='password'>#{@password}</module-option>
168
+ <module-option name='managedConnectionFactoryName'>jboss.jca:name=#{@jndi_name},service=#{@service}</module-option>
169
+ </login-module>
170
+ </authentication>
171
+ </application-policy>
172
+ </policy>
173
+ XML
174
+ end
175
+
176
+ def jboss_logging_lib_path
177
+ %W{#{@jboss.home}/client/jboss-logging-spi.jar #{@jboss.home}/client/jboss-logging.jar}.each do |path|
178
+ return path if File.exist? path
179
+ end
180
+ end
181
+
182
+ def jbosssx_lib_path
183
+ %W{#{@jboss.home}/lib/jbosssx.jar #{@jboss.home}/common/lib/jbosssx.jar}.each do |path|
184
+ return path if File.exist? path
185
+ end
186
+ end
187
+
188
+ # Encrypts the given password using the SecureIdentityLoginModule
189
+ def encrypt password
190
+ cmd = "java -cp #{jboss_logging_lib_path}:#{jbosssx_lib_path} org.jboss.resource.security.SecureIdentityLoginModule #{password}"
191
+ @logger.debug cmd
192
+ encrypted = `#{cmd}`
193
+ encrypted.chomp.split(/:/)[1].strip
194
+ end
195
+
196
+ end
197
+
198
+ end