cuboid 0.0.0 → 0.0.1alpha

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 (221) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +0 -0
  3. data/Gemfile +20 -5
  4. data/LICENSE.md +22 -0
  5. data/README.md +158 -19
  6. data/Rakefile +56 -3
  7. data/config/paths.yml +15 -0
  8. data/cuboid.gemspec +61 -23
  9. data/lib/cuboid.rb +96 -4
  10. data/lib/cuboid/application.rb +326 -0
  11. data/lib/cuboid/application/parts/data.rb +18 -0
  12. data/lib/cuboid/application/parts/report.rb +29 -0
  13. data/lib/cuboid/application/parts/state.rb +274 -0
  14. data/lib/cuboid/application/runtime.rb +25 -0
  15. data/lib/cuboid/banner.rb +13 -0
  16. data/lib/cuboid/data.rb +86 -0
  17. data/lib/cuboid/data/application.rb +52 -0
  18. data/lib/cuboid/error.rb +9 -0
  19. data/lib/cuboid/option_group.rb +129 -0
  20. data/lib/cuboid/option_groups.rb +8 -0
  21. data/lib/cuboid/option_groups/datastore.rb +23 -0
  22. data/lib/cuboid/option_groups/dispatcher.rb +38 -0
  23. data/lib/cuboid/option_groups/output.rb +14 -0
  24. data/lib/cuboid/option_groups/paths.rb +184 -0
  25. data/lib/cuboid/option_groups/report.rb +39 -0
  26. data/lib/cuboid/option_groups/rpc.rb +105 -0
  27. data/lib/cuboid/option_groups/scheduler.rb +27 -0
  28. data/lib/cuboid/option_groups/snapshot.rb +13 -0
  29. data/lib/cuboid/option_groups/system.rb +10 -0
  30. data/lib/cuboid/options.rb +254 -0
  31. data/lib/cuboid/processes.rb +13 -0
  32. data/lib/cuboid/processes/dispatchers.rb +140 -0
  33. data/lib/cuboid/processes/executables/base.rb +54 -0
  34. data/lib/cuboid/processes/executables/dispatcher.rb +5 -0
  35. data/lib/cuboid/processes/executables/instance.rb +12 -0
  36. data/lib/cuboid/processes/executables/rest_service.rb +13 -0
  37. data/lib/cuboid/processes/executables/scheduler.rb +5 -0
  38. data/lib/cuboid/processes/helpers.rb +4 -0
  39. data/lib/cuboid/processes/helpers/dispatchers.rb +23 -0
  40. data/lib/cuboid/processes/helpers/instances.rb +39 -0
  41. data/lib/cuboid/processes/helpers/processes.rb +23 -0
  42. data/lib/cuboid/processes/helpers/schedulers.rb +23 -0
  43. data/lib/cuboid/processes/instances.rb +203 -0
  44. data/lib/cuboid/processes/manager.rb +262 -0
  45. data/lib/cuboid/processes/schedulers.rb +128 -0
  46. data/lib/cuboid/report.rb +220 -0
  47. data/lib/cuboid/rest/server.rb +165 -0
  48. data/lib/cuboid/rest/server/instance_helpers.rb +99 -0
  49. data/lib/cuboid/rest/server/routes/dispatcher.rb +41 -0
  50. data/lib/cuboid/rest/server/routes/grid.rb +41 -0
  51. data/lib/cuboid/rest/server/routes/instances.rb +131 -0
  52. data/lib/cuboid/rest/server/routes/scheduler.rb +140 -0
  53. data/lib/cuboid/rpc/client.rb +3 -0
  54. data/lib/cuboid/rpc/client/base.rb +58 -0
  55. data/lib/cuboid/rpc/client/dispatcher.rb +58 -0
  56. data/lib/cuboid/rpc/client/instance.rb +100 -0
  57. data/lib/cuboid/rpc/client/instance/service.rb +37 -0
  58. data/lib/cuboid/rpc/client/scheduler.rb +46 -0
  59. data/lib/cuboid/rpc/serializer.rb +92 -0
  60. data/lib/cuboid/rpc/server/active_options.rb +38 -0
  61. data/lib/cuboid/rpc/server/application_wrapper.rb +138 -0
  62. data/lib/cuboid/rpc/server/base.rb +63 -0
  63. data/lib/cuboid/rpc/server/dispatcher.rb +317 -0
  64. data/lib/cuboid/rpc/server/dispatcher/node.rb +247 -0
  65. data/lib/cuboid/rpc/server/dispatcher/service.rb +145 -0
  66. data/lib/cuboid/rpc/server/instance.rb +338 -0
  67. data/lib/cuboid/rpc/server/output.rb +92 -0
  68. data/lib/cuboid/rpc/server/scheduler.rb +482 -0
  69. data/lib/cuboid/ruby.rb +4 -0
  70. data/lib/cuboid/ruby/array.rb +17 -0
  71. data/lib/cuboid/ruby/hash.rb +41 -0
  72. data/lib/cuboid/ruby/object.rb +32 -0
  73. data/lib/cuboid/snapshot.rb +186 -0
  74. data/lib/cuboid/state.rb +94 -0
  75. data/lib/cuboid/state/application.rb +309 -0
  76. data/lib/cuboid/state/options.rb +27 -0
  77. data/lib/cuboid/support.rb +11 -0
  78. data/lib/cuboid/support/buffer.rb +3 -0
  79. data/lib/cuboid/support/buffer/autoflush.rb +61 -0
  80. data/lib/cuboid/support/buffer/base.rb +91 -0
  81. data/lib/cuboid/support/cache.rb +7 -0
  82. data/lib/cuboid/support/cache/base.rb +226 -0
  83. data/lib/cuboid/support/cache/least_cost_replacement.rb +77 -0
  84. data/lib/cuboid/support/cache/least_recently_pushed.rb +21 -0
  85. data/lib/cuboid/support/cache/least_recently_used.rb +31 -0
  86. data/lib/cuboid/support/cache/preference.rb +31 -0
  87. data/lib/cuboid/support/cache/random_replacement.rb +20 -0
  88. data/lib/cuboid/support/crypto.rb +2 -0
  89. data/lib/cuboid/support/crypto/rsa_aes_cbc.rb +86 -0
  90. data/lib/cuboid/support/database.rb +5 -0
  91. data/lib/cuboid/support/database/base.rb +177 -0
  92. data/lib/cuboid/support/database/categorized_queue.rb +195 -0
  93. data/lib/cuboid/support/database/hash.rb +300 -0
  94. data/lib/cuboid/support/database/queue.rb +149 -0
  95. data/lib/cuboid/support/filter.rb +3 -0
  96. data/lib/cuboid/support/filter/base.rb +110 -0
  97. data/lib/cuboid/support/filter/set.rb +29 -0
  98. data/lib/cuboid/support/glob.rb +27 -0
  99. data/lib/cuboid/support/mixins.rb +8 -0
  100. data/lib/cuboid/support/mixins/observable.rb +99 -0
  101. data/lib/cuboid/support/mixins/parts.rb +20 -0
  102. data/lib/cuboid/support/mixins/profiler.rb +93 -0
  103. data/lib/cuboid/support/mixins/spec_instances.rb +65 -0
  104. data/lib/cuboid/support/mixins/terminal.rb +57 -0
  105. data/lib/cuboid/system.rb +119 -0
  106. data/lib/cuboid/system/platforms.rb +84 -0
  107. data/lib/cuboid/system/platforms/linux.rb +26 -0
  108. data/lib/cuboid/system/platforms/mixins/unix.rb +46 -0
  109. data/lib/cuboid/system/platforms/osx.rb +25 -0
  110. data/lib/cuboid/system/platforms/windows.rb +81 -0
  111. data/lib/cuboid/system/slots.rb +143 -0
  112. data/lib/cuboid/ui/output.rb +52 -0
  113. data/lib/cuboid/ui/output_interface.rb +43 -0
  114. data/lib/cuboid/ui/output_interface/abstract.rb +68 -0
  115. data/lib/cuboid/ui/output_interface/controls.rb +84 -0
  116. data/lib/cuboid/ui/output_interface/error_logging.rb +119 -0
  117. data/lib/cuboid/ui/output_interface/implemented.rb +58 -0
  118. data/lib/cuboid/ui/output_interface/personalization.rb +62 -0
  119. data/lib/cuboid/utilities.rb +155 -0
  120. data/lib/cuboid/version.rb +4 -3
  121. data/lib/version +1 -0
  122. data/logs/placeholder +0 -0
  123. data/spec/cuboid/application/parts/data_spec.rb +12 -0
  124. data/spec/cuboid/application/parts/report_spec.rb +6 -0
  125. data/spec/cuboid/application/parts/state_spec.rb +192 -0
  126. data/spec/cuboid/application/runtime_spec.rb +21 -0
  127. data/spec/cuboid/application_spec.rb +37 -0
  128. data/spec/cuboid/data/application_spec.rb +22 -0
  129. data/spec/cuboid/data_spec.rb +47 -0
  130. data/spec/cuboid/error_spec.rb +23 -0
  131. data/spec/cuboid/option_groups/datastore_spec.rb +54 -0
  132. data/spec/cuboid/option_groups/dispatcher_spec.rb +12 -0
  133. data/spec/cuboid/option_groups/output_spec.rb +11 -0
  134. data/spec/cuboid/option_groups/paths_spec.rb +184 -0
  135. data/spec/cuboid/option_groups/report_spec.rb +26 -0
  136. data/spec/cuboid/option_groups/rpc_spec.rb +53 -0
  137. data/spec/cuboid/option_groups/snapshot_spec.rb +26 -0
  138. data/spec/cuboid/option_groups/system.rb +12 -0
  139. data/spec/cuboid/options_spec.rb +218 -0
  140. data/spec/cuboid/report_spec.rb +221 -0
  141. data/spec/cuboid/rest/server_spec.rb +1205 -0
  142. data/spec/cuboid/rpc/client/base_spec.rb +151 -0
  143. data/spec/cuboid/rpc/client/dispatcher_spec.rb +13 -0
  144. data/spec/cuboid/rpc/client/instance_spec.rb +38 -0
  145. data/spec/cuboid/rpc/server/active_options_spec.rb +21 -0
  146. data/spec/cuboid/rpc/server/base_spec.rb +60 -0
  147. data/spec/cuboid/rpc/server/dispatcher/node_spec.rb +222 -0
  148. data/spec/cuboid/rpc/server/dispatcher/service_spec.rb +112 -0
  149. data/spec/cuboid/rpc/server/dispatcher_spec.rb +317 -0
  150. data/spec/cuboid/rpc/server/instance_spec.rb +307 -0
  151. data/spec/cuboid/rpc/server/output_spec.rb +32 -0
  152. data/spec/cuboid/rpc/server/scheduler_spec.rb +400 -0
  153. data/spec/cuboid/ruby/array_spec.rb +77 -0
  154. data/spec/cuboid/ruby/hash_spec.rb +63 -0
  155. data/spec/cuboid/ruby/object_spec.rb +22 -0
  156. data/spec/cuboid/snapshot_spec.rb +123 -0
  157. data/spec/cuboid/state/application_spec.rb +538 -0
  158. data/spec/cuboid/state/options_spec.rb +37 -0
  159. data/spec/cuboid/state_spec.rb +53 -0
  160. data/spec/cuboid/support/buffer/autoflush_spec.rb +78 -0
  161. data/spec/cuboid/support/buffer/base_spec.rb +193 -0
  162. data/spec/cuboid/support/cache/least_cost_replacement_spec.rb +61 -0
  163. data/spec/cuboid/support/cache/least_recently_pushed_spec.rb +90 -0
  164. data/spec/cuboid/support/cache/least_recently_used_spec.rb +80 -0
  165. data/spec/cuboid/support/cache/preference_spec.rb +37 -0
  166. data/spec/cuboid/support/cache/random_replacement_spec.rb +42 -0
  167. data/spec/cuboid/support/crypto/rsa_aes_cbc_spec.rb +28 -0
  168. data/spec/cuboid/support/database/categorized_queue_spec.rb +327 -0
  169. data/spec/cuboid/support/database/hash_spec.rb +204 -0
  170. data/spec/cuboid/support/database/scheduler_spec.rb +325 -0
  171. data/spec/cuboid/support/filter/set_spec.rb +19 -0
  172. data/spec/cuboid/support/glob_spec.rb +75 -0
  173. data/spec/cuboid/support/mixins/observable_spec.rb +95 -0
  174. data/spec/cuboid/system/platforms/linux_spec.rb +31 -0
  175. data/spec/cuboid/system/platforms/osx_spec.rb +32 -0
  176. data/spec/cuboid/system/platforms/windows_spec.rb +41 -0
  177. data/spec/cuboid/system/slots_spec.rb +202 -0
  178. data/spec/cuboid/system_spec.rb +105 -0
  179. data/spec/cuboid/utilities_spec.rb +131 -0
  180. data/spec/spec_helper.rb +46 -0
  181. data/spec/support/factories/placeholder +0 -0
  182. data/spec/support/factories/scan_report.rb +18 -0
  183. data/spec/support/fixtures/empty/placeholder +0 -0
  184. data/spec/support/fixtures/executables/node.rb +50 -0
  185. data/spec/support/fixtures/mock_app.rb +61 -0
  186. data/spec/support/fixtures/mock_app/test_service.rb +64 -0
  187. data/spec/support/fixtures/services/echo.rb +64 -0
  188. data/spec/support/helpers/framework.rb +3 -0
  189. data/spec/support/helpers/matchers.rb +5 -0
  190. data/spec/support/helpers/misc.rb +3 -0
  191. data/spec/support/helpers/paths.rb +15 -0
  192. data/spec/support/helpers/request_helpers.rb +38 -0
  193. data/spec/support/helpers/requires.rb +8 -0
  194. data/spec/support/helpers/resets.rb +52 -0
  195. data/spec/support/helpers/web_server.rb +15 -0
  196. data/spec/support/lib/factory.rb +107 -0
  197. data/spec/support/lib/web_server_client.rb +41 -0
  198. data/spec/support/lib/web_server_dispatcher.rb +25 -0
  199. data/spec/support/lib/web_server_manager.rb +118 -0
  200. data/spec/support/logs/placeholder +0 -0
  201. data/spec/support/pems/cacert.pem +37 -0
  202. data/spec/support/pems/client/cert.pem +37 -0
  203. data/spec/support/pems/client/foo-cert.pem +39 -0
  204. data/spec/support/pems/client/foo-key.pem +51 -0
  205. data/spec/support/pems/client/key.pem +51 -0
  206. data/spec/support/pems/server/cert.pem +37 -0
  207. data/spec/support/pems/server/key.pem +51 -0
  208. data/spec/support/reports/placeholder +0 -0
  209. data/spec/support/shared/application.rb +10 -0
  210. data/spec/support/shared/component.rb +31 -0
  211. data/spec/support/shared/component/options/base.rb +187 -0
  212. data/spec/support/shared/option_group.rb +98 -0
  213. data/spec/support/shared/support/cache.rb +419 -0
  214. data/spec/support/shared/support/filter.rb +143 -0
  215. data/spec/support/shared/system/platforms/base.rb +25 -0
  216. data/spec/support/shared/system/platforms/mixins/unix.rb +37 -0
  217. data/spec/support/snapshots/placeholder +0 -0
  218. metadata +566 -21
  219. data/.gitignore +0 -8
  220. data/bin/console +0 -15
  221. data/bin/setup +0 -8
@@ -0,0 +1,64 @@
1
+ class Cuboid::RPC::Server::Dispatcher
2
+ class Service::Echo < Service
3
+
4
+ private :instances
5
+ public :instances
6
+
7
+ def test_dispatcher
8
+ dispatcher.class == Cuboid::RPC::Server::Dispatcher
9
+ end
10
+
11
+ def test_opts
12
+ dispatcher.instance_eval{ @options } == options
13
+ end
14
+
15
+ def test_node
16
+ node.class == Node
17
+ end
18
+
19
+ def test_map_instances( &block )
20
+ each = proc do |instance, iterator|
21
+ iterator.return [instance.url, instance.token]
22
+ end
23
+ after = proc { |i| block.call Hash[i] }
24
+
25
+ map_instances( each, after )
26
+ end
27
+
28
+ def test_each_instance
29
+ i = 0
30
+ each_instance do |instance, iterator|
31
+ i += 1
32
+ instance.options.set( authorized_by: "test#{i}@test.test") { |p| iterator.next }
33
+ end
34
+ true
35
+ end
36
+
37
+ def test_iterator_for
38
+ iterator_for( instances ).class == Arachni::Reactor::Iterator
39
+ end
40
+
41
+ def test_connect_to_dispatcher( url, &block )
42
+ connect_to_dispatcher( url ).alive? { |b| block.call b }
43
+ end
44
+
45
+ def test_connect_to_instance( *args, &block )
46
+ connect_to_instance( *args ).busy?{ |b| block.call !!b }
47
+ end
48
+
49
+ def test_defer( *args, &block )
50
+ defer do
51
+ block.call args
52
+ end
53
+ end
54
+
55
+ def test_run_asap( *args, &block )
56
+ run_asap { block.call args }
57
+ end
58
+
59
+ def echo( *args )
60
+ args
61
+ end
62
+
63
+ end
64
+ end
@@ -0,0 +1,3 @@
1
+ def issues
2
+ Cuboid::Data.issues.all
3
+ end
@@ -0,0 +1,5 @@
1
+ RSpec::Matchers.define :be_same_array_as do |expected_array|
2
+ match do |actual_array|
3
+ Set.new(actual_array) == Set.new(expected_array)
4
+ end
5
+ end
@@ -0,0 +1,3 @@
1
+ def available_port
2
+ Cuboid::Utilities.available_port
3
+ end
@@ -0,0 +1,15 @@
1
+ def name_from_filename
2
+ File.basename( caller.first.split( ':' ).first, '_spec.rb' )
3
+ end
4
+
5
+ def spec_path
6
+ File.expand_path( File.dirname( File.absolute_path( __FILE__ ) ) + '/../../' ) + '/'
7
+ end
8
+
9
+ def support_path
10
+ "#{spec_path}support/"
11
+ end
12
+
13
+ def fixtures_path
14
+ "#{support_path}fixtures/"
15
+ end
@@ -0,0 +1,38 @@
1
+ module RequestHelpers
2
+ include Rack::Test::Methods
3
+
4
+ def app
5
+ Cuboid::Rest::Server
6
+ end
7
+
8
+ def response_data
9
+ JSON.load response.body
10
+ rescue => e
11
+ ap response
12
+ raise
13
+ end
14
+
15
+ def pretty_response_body
16
+ JSON.pretty_generate( response_data )
17
+ end
18
+
19
+ def response_body
20
+ response.body
21
+ end
22
+
23
+ def response_code
24
+ response.status
25
+ end
26
+
27
+ def response
28
+ last_response
29
+ end
30
+
31
+ %w(get post put delete).each do |m|
32
+ define_method m do |path, parameters = nil, headers = {}|
33
+ super( path, (parameters.to_json if parameters), headers )
34
+ end
35
+ end
36
+
37
+ extend self
38
+ end
@@ -0,0 +1,8 @@
1
+ def require_lib( path )
2
+ require Cuboid::Options.paths.lib + path
3
+ end
4
+
5
+ def require_testee
6
+ require Kernel.caller.first.split( ':' ).first.
7
+ gsub( '/spec/cuboid', '/lib/cuboid' ).gsub( '_spec', '' )
8
+ end
@@ -0,0 +1,52 @@
1
+ # Order is important.
2
+ INSTANCES = [
3
+ Cuboid::Application
4
+ ]
5
+ INSTANCES.each(&:_spec_instances_collect!)
6
+
7
+ def reset_options
8
+ options = Cuboid::Options
9
+ options.reset
10
+
11
+ options.paths.logs = spec_path + 'support/logs/'
12
+ options.paths.reports = spec_path + 'support/reports/'
13
+ options.paths.snapshots = spec_path + 'support/snapshots/'
14
+ options.snapshot.path = options.paths.snapshots
15
+
16
+ options.rpc.server_address = '127.0.0.1'
17
+
18
+ options
19
+ end
20
+
21
+ def cleanup_instances
22
+ INSTANCES.each do |i|
23
+ i._spec_instances_cleanup
24
+ end
25
+ end
26
+
27
+ def reset_framework
28
+ Cuboid::UI::OutputInterface.initialize
29
+ # Cuboid::UI::Output.debug_on( 999999 )
30
+ # Cuboid::UI::Output.verbose_on
31
+ # Cuboid::UI::Output.mute
32
+
33
+ Cuboid::Application.reset
34
+ end
35
+
36
+ def reset_all
37
+ reset_options
38
+ reset_framework
39
+ end
40
+
41
+ def processes_killall
42
+ instance_killall
43
+ dispatcher_killall
44
+ scheduler_killall
45
+ process_killall
46
+ process_kill_reactor
47
+ end
48
+
49
+ def killall
50
+ processes_killall
51
+ web_server_killall
52
+ end
@@ -0,0 +1,15 @@
1
+ def web_server_manager
2
+ ENV['WEB_SERVER_DISPATCHER'] ? WebServerClient.instance : WebServerManager
3
+ end
4
+
5
+ def web_server_url_for( *args )
6
+ web_server_manager.url_for( *args )
7
+ end
8
+
9
+ def web_server_spawn( *args )
10
+ web_server_manager.spawn( *args )
11
+ end
12
+
13
+ def web_server_killall
14
+ web_server_manager.killall
15
+ end
@@ -0,0 +1,107 @@
1
+ class Factory
2
+ class <<self
3
+
4
+ # Clears all instructions and aliases.
5
+ def reset
6
+ @instructions = {}
7
+ @aliases = {}
8
+ end
9
+
10
+ # Defines instruction on how to create a given object.
11
+ #
12
+ # There are 2 ways to define a factory instruction:
13
+ #
14
+ # * Using a `generator` block to return an object.
15
+ # * Using the `options` to generate an object.
16
+ #
17
+ # @param [Symbol] object_name Name of the object.
18
+ # @param [Hash] options Generation options.
19
+ # @option options [Class] :class
20
+ # Class to instantiate.
21
+ # @option options [Hash] :options
22
+ # Options to use to instantiate the `:class`.
23
+ def define( object_name, options = {}, &generator )
24
+ @instructions[object_name] = {
25
+ options: options.dup,
26
+ generator: generator
27
+ }
28
+ end
29
+
30
+ # @param [Symbol] object_name Name of the object.
31
+ # @param [] args
32
+ # If a `generator` block has been provided via {#define}, those arguments
33
+ # will be passed to it.
34
+ #
35
+ # If `:options` have been passed to {#define}, the `args` will be merged
36
+ # with them before instantiating the object.
37
+ def create( object_name, *args )
38
+ ensure_defined( object_name )
39
+
40
+ instructions = instructions_for( object_name )
41
+
42
+ if instructions[:generator]
43
+ instructions[:generator].call( *args )
44
+ elsif (options = instructions[:options]).include? :class
45
+ options[:class].new( options[:options].merge( args.first || {} ) )
46
+ end
47
+ end
48
+
49
+ # @param [Symbol] object_name Name of the object.
50
+ # @return [Hash] Instantiation options passed to {#define}.
51
+ def options_for( object_name )
52
+ instructions_for( object_name )[:options][:options].freeze
53
+ end
54
+
55
+ # @note {#create} helper.
56
+ #
57
+ # @param [Symbol] object_name Name of the object.
58
+ # @return [Object] Instantiated object.
59
+ def []( object_name )
60
+ create object_name
61
+ end
62
+
63
+ # @param [Symbol] object_name
64
+ # Name of the new object.
65
+ # @param [Symbol] existing_object_name
66
+ # Name of the existing object.
67
+ def alias( object_name, existing_object_name )
68
+ ensure_defined( existing_object_name )
69
+ @aliases[object_name] = existing_object_name
70
+ end
71
+
72
+ # @param [Symbol] object_name Object to delete.
73
+ def delete( object_name )
74
+ @instructions.delete object_name
75
+ end
76
+
77
+ # @param [Symbol] object_name Alias to delete.
78
+ def unalias( object_name )
79
+ @aliases.delete object_name
80
+ nil
81
+ end
82
+
83
+ # @param [Symbol] object_name
84
+ # Name of the new object.
85
+ # @return [Bool]
86
+ # `true` if instructions have been {#defined} for the `object_name`,
87
+ # `false` otherwise.
88
+ def defined?( object_name )
89
+ !!instructions_for( object_name ) rescue false
90
+ end
91
+
92
+ private
93
+
94
+ def instructions_for( object_name )
95
+ instructions = @instructions[object_name] || @instructions[@aliases[object_name]]
96
+ return instructions if instructions
97
+
98
+ fail ArgumentError, "Factory '#{object_name}' not defined."
99
+ end
100
+
101
+ def ensure_defined( object_name )
102
+ !!instructions_for( object_name )
103
+ end
104
+ end
105
+ reset
106
+
107
+ end
@@ -0,0 +1,41 @@
1
+ require 'arachni/rpc'
2
+
3
+ # @note Needs `ENV['WEB_SERVER_DISPATCHER']` in the format of `host:port`.
4
+ #
5
+ # {WebServerManager}-API-compatible client for the {WebServerDispatcher}.
6
+ #
7
+ # Delegates test webserver creation to the machine running {WebServerDispatcher},
8
+ # for hosts that lack support for fast servers (like Windows, which can't run
9
+ # Thin, Puma etc.).
10
+ #
11
+ # @author Tasos "Zapotek" Laskos <tasos.laskos@gmail.com>
12
+ class WebServerClient < Arachni::RPC::Proxy
13
+ include Singleton
14
+
15
+ def initialize( options = {} )
16
+ @host, port = ENV['WEB_SERVER_DISPATCHER'].split( ':' )
17
+
18
+ Arachni::Reactor.global.run_in_thread if !Arachni::Reactor.global.running?
19
+
20
+ client = Arachni::RPC::Client.new( host: @host, port: port )
21
+ super client, 'server'
22
+ end
23
+
24
+ def protocol_for( name )
25
+ name.to_s.include?( 'https' ) ? 'https' : 'http'
26
+ end
27
+
28
+ def address_for( name )
29
+ @host
30
+ end
31
+
32
+ def up?( name )
33
+ Typhoeus.get(
34
+ url_for( name, false ),
35
+ ssl_verifypeer: false,
36
+ ssl_verifyhost: 0,
37
+ forbid_reuse: true
38
+ ).code != 0
39
+ end
40
+
41
+ end
@@ -0,0 +1,25 @@
1
+ require_relative '../../../lib/cuboid/processes/manager'
2
+ require_relative '../../../lib/cuboid/processes/helpers'
3
+ require_relative '../../support/helpers/paths'
4
+ require_relative 'web_server_manager'
5
+ require 'arachni/rpc'
6
+
7
+ # @note Needs `ENV['WEB_SERVER_DISPATCHER']` in the format of `host:port`.
8
+ #
9
+ # Exposes the {WebServerManager} over RPC.
10
+ #
11
+ # @author Tasos "Zapotek" Laskos <tasos.laskos@gmail.com>
12
+ class WebServerDispatcher
13
+
14
+ def initialize( options = {} )
15
+ host, port = ENV['WEB_SERVER_DISPATCHER'].split( ':' )
16
+
17
+ manager = WebServerManager.instance
18
+ manager.address = host
19
+
20
+ rpc = Cuboid::RPC::Server.new( host: host, port: port.to_i )
21
+ rpc.add_handler( 'server', manager )
22
+ rpc.run
23
+ end
24
+
25
+ end
@@ -0,0 +1,118 @@
1
+ class WebServerManager
2
+ include Singleton
3
+ include Cuboid::Utilities
4
+
5
+ attr_reader :lib
6
+ attr_accessor :address
7
+
8
+ def initialize
9
+ @lib = "#{support_path}/servers/"
10
+ @servers = {}
11
+ @address = Socket.gethostname
12
+
13
+ Dir.glob( File.join( @lib + '**', '*.rb' ) ) do |path|
14
+ @servers[normalize_name( File.basename( path, '.rb' ) )] = {
15
+ path: path
16
+ }
17
+ end
18
+ end
19
+
20
+ def spawn( name )
21
+ server_info = data_for( name )
22
+
23
+ 10.times do
24
+ server_info[:port] = Cuboid::Utilities.available_port
25
+ server_info[:pid] = Process.spawn(
26
+ RbConfig.ruby, server_info[:path],
27
+ '-p', server_info[:port].to_s,
28
+ '-o', address_for( name )
29
+ )
30
+ Process.detach server_info[:pid]
31
+
32
+ begin
33
+ Timeout.timeout( 10 ) { sleep 0.1 while !up?( name ) }
34
+
35
+ return url_for( name, false )
36
+ rescue Timeout::Error
37
+ kill name
38
+ end
39
+ end
40
+
41
+ abort "Server '#{name}' never started!"
42
+ end
43
+
44
+ def url_for( name, lazy_start = true )
45
+ spawn( name ) if lazy_start && !up?( name )
46
+
47
+ "#{protocol_for( name )}://#{address_for( name )}:#{port_for( name )}"
48
+ end
49
+
50
+ def address_for( name )
51
+ @address
52
+ end
53
+
54
+ def port_for( name )
55
+ data_for( name )[:port]
56
+ end
57
+
58
+ def protocol_for( name )
59
+ name.to_s.include?( 'https' ) ? 'https' : 'http'
60
+ end
61
+
62
+ def kill( name )
63
+ server_info = data_for( name )
64
+ return if !server_info[:pid]
65
+
66
+ r = process_kill( server_info[:pid] )
67
+
68
+ if r
69
+ server_info.delete( :pid )
70
+ server_info.delete( :port )
71
+ end
72
+
73
+ r
74
+ end
75
+
76
+ def killall
77
+ @servers.keys.each { |name| kill name }
78
+ nil
79
+ end
80
+
81
+ def up?( name )
82
+ return false if !data_for(name)[:port]
83
+
84
+ Typhoeus.get(
85
+ url_for( name, false ),
86
+ ssl_verifypeer: false,
87
+ ssl_verifyhost: 0,
88
+ forbid_reuse: true
89
+ ).code != 0
90
+ end
91
+
92
+ def self.method_missing( sym, *args, &block )
93
+ if instance.respond_to?( sym )
94
+ instance.send( sym, *args, &block )
95
+ else
96
+ super( sym, *args, &block )
97
+ end
98
+ end
99
+
100
+ def self.respond_to?( m )
101
+ super( m ) || instance.respond_to?( m )
102
+ end
103
+
104
+ private
105
+
106
+ def normalize_name( name )
107
+ name.to_s.to_sym
108
+ end
109
+
110
+ def data_for( name )
111
+ @servers[normalize_name( name )]
112
+ end
113
+
114
+ def set_data_for(name, data)
115
+ @servers[normalize_name(name)] = data
116
+ end
117
+
118
+ end