cloud-crowd 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 (66) hide show
  1. data/EPIGRAPHS +17 -0
  2. data/LICENSE +22 -0
  3. data/README +93 -0
  4. data/actions/graphics_magick.rb +43 -0
  5. data/actions/process_pdfs.rb +92 -0
  6. data/actions/word_count.rb +14 -0
  7. data/bin/crowd +5 -0
  8. data/cloud-crowd.gemspec +111 -0
  9. data/config/config.example.ru +17 -0
  10. data/config/config.example.yml +48 -0
  11. data/config/database.example.yml +9 -0
  12. data/examples/graphics_magick_example.rb +44 -0
  13. data/examples/process_pdfs_example.rb +40 -0
  14. data/examples/word_count_example.rb +41 -0
  15. data/lib/cloud-crowd.rb +130 -0
  16. data/lib/cloud_crowd/action.rb +101 -0
  17. data/lib/cloud_crowd/app.rb +117 -0
  18. data/lib/cloud_crowd/asset_store.rb +41 -0
  19. data/lib/cloud_crowd/asset_store/filesystem_store.rb +28 -0
  20. data/lib/cloud_crowd/asset_store/s3_store.rb +40 -0
  21. data/lib/cloud_crowd/command_line.rb +209 -0
  22. data/lib/cloud_crowd/daemon.rb +95 -0
  23. data/lib/cloud_crowd/exceptions.rb +28 -0
  24. data/lib/cloud_crowd/helpers.rb +8 -0
  25. data/lib/cloud_crowd/helpers/authorization.rb +50 -0
  26. data/lib/cloud_crowd/helpers/resources.rb +45 -0
  27. data/lib/cloud_crowd/inflector.rb +19 -0
  28. data/lib/cloud_crowd/models.rb +40 -0
  29. data/lib/cloud_crowd/models/job.rb +176 -0
  30. data/lib/cloud_crowd/models/work_unit.rb +89 -0
  31. data/lib/cloud_crowd/models/worker_record.rb +61 -0
  32. data/lib/cloud_crowd/runner.rb +15 -0
  33. data/lib/cloud_crowd/schema.rb +45 -0
  34. data/lib/cloud_crowd/worker.rb +186 -0
  35. data/public/css/admin_console.css +221 -0
  36. data/public/css/reset.css +42 -0
  37. data/public/images/bullet_green.png +0 -0
  38. data/public/images/bullet_white.png +0 -0
  39. data/public/images/cloud_hand.png +0 -0
  40. data/public/images/header_back.png +0 -0
  41. data/public/images/logo.png +0 -0
  42. data/public/images/queue_fill.png +0 -0
  43. data/public/images/server_error.png +0 -0
  44. data/public/images/sidebar_bottom.png +0 -0
  45. data/public/images/sidebar_top.png +0 -0
  46. data/public/images/worker_info.png +0 -0
  47. data/public/images/worker_info_loading.gif +0 -0
  48. data/public/js/admin_console.js +168 -0
  49. data/public/js/excanvas.js +1 -0
  50. data/public/js/flot.js +1 -0
  51. data/public/js/jquery.js +19 -0
  52. data/test/acceptance/test_app.rb +72 -0
  53. data/test/acceptance/test_failing_work_units.rb +32 -0
  54. data/test/acceptance/test_word_count.rb +49 -0
  55. data/test/blueprints.rb +17 -0
  56. data/test/config/actions/failure_testing.rb +13 -0
  57. data/test/config/config.ru +17 -0
  58. data/test/config/config.yml +7 -0
  59. data/test/config/database.yml +6 -0
  60. data/test/test_helper.rb +19 -0
  61. data/test/unit/test_action.rb +49 -0
  62. data/test/unit/test_configuration.rb +28 -0
  63. data/test/unit/test_job.rb +78 -0
  64. data/test/unit/test_work_unit.rb +55 -0
  65. data/views/index.erb +77 -0
  66. metadata +233 -0
@@ -0,0 +1,17 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ # This rackup script can be used to start the central CloudCrowd server
4
+ # using any Rack-compliant server handler. For example, start up three servers
5
+ # with a specified port number, using Thin:
6
+ #
7
+ # thin start -R config.ru -p 9173 --servers 3
8
+
9
+ require 'rubygems'
10
+ require 'cloud-crowd'
11
+
12
+ CloudCrowd.configure(File.dirname(__FILE__) + '/config.yml')
13
+ CloudCrowd.configure_database(File.dirname(__FILE__) + '/database.yml')
14
+
15
+ map '/' do
16
+ run CloudCrowd::App
17
+ end
@@ -0,0 +1,7 @@
1
+ :num_workers: 4
2
+ :min_worker_wait: 1
3
+ :max_worker_wait: 20
4
+ :work_unit_retries: 3
5
+
6
+ :central_server: http://localhost:9173
7
+ :storage: filesystem
@@ -0,0 +1,6 @@
1
+ :adapter: mysql
2
+ :encoding: utf8
3
+ :username: root
4
+ :password:
5
+ :socket: /tmp/mysql.sock
6
+ :database: cloud_crowd_test
@@ -0,0 +1,19 @@
1
+ ENV['RACK_ENV'] = 'test'
2
+ require 'rubygems'
3
+
4
+ here = File.dirname(__FILE__)
5
+ require File.expand_path(here + "/../lib/cloud-crowd")
6
+ CloudCrowd.configure(here + '/config/config.yml')
7
+ CloudCrowd.configure_database(here + '/config/database.yml')
8
+
9
+ require 'faker'
10
+ require 'sham'
11
+ require 'rack/test'
12
+ require 'shoulda/active_record'
13
+ require 'machinist/active_record'
14
+ require 'mocha'
15
+ require "#{CloudCrowd::ROOT}/test/blueprints.rb"
16
+
17
+ class Test::Unit::TestCase
18
+ include CloudCrowd
19
+ end
@@ -0,0 +1,49 @@
1
+ require 'test_helper'
2
+
3
+ class CloudCrowd::Action
4
+ public :safe_filename
5
+ end
6
+
7
+ class EmptyAction < CloudCrowd::Action
8
+ end
9
+
10
+ class ActionTest < Test::Unit::TestCase
11
+
12
+ context "A CloudCrowd Job" do
13
+
14
+ setup do
15
+ @store = CloudCrowd::AssetStore.new
16
+ @args = [CloudCrowd::PROCESSING, 'file://' + File.expand_path(__FILE__), {'job_id' => 1, 'work_unit_id' => 1}, @store]
17
+ @action = CloudCrowd.actions['word_count'].new(*@args)
18
+ end
19
+
20
+ should "throw an exception if the 'process' method isn't implemented" do
21
+ assert_raise(NotImplementedError) { EmptyAction.new(*@args).process }
22
+ end
23
+
24
+ should "have downloaded the input URL to local storage" do
25
+ assert @action.input_path
26
+ assert File.read(@action.input_path) == File.read(File.expand_path(__FILE__))
27
+ end
28
+
29
+ should "be able to save (to the filesystem while testing)" do
30
+ assert @action.save(@action.input_path) == "file://#{CloudCrowd::AssetStore::LOCAL_STORAGE_PATH}/word_count/job_1/unit_1/test_action.rb"
31
+ end
32
+
33
+ should "be able to clean up after itself" do
34
+ @action.cleanup_work_directory
35
+ assert !File.exists?(@action.work_directory)
36
+ end
37
+
38
+ should "be able to generate a safe filename for a URL to write to disk" do
39
+ name = @action.safe_filename("http://example.com/Some%20(Crazy'Kinda%7E)'Filename.txt")
40
+ assert name == 'Some-Crazy-Kinda-Filename.txt'
41
+ end
42
+
43
+ should "be able to count the number of words in this file" do
44
+ assert @action.process == 149
45
+ end
46
+
47
+ end
48
+
49
+ end
@@ -0,0 +1,28 @@
1
+ require 'test_helper'
2
+
3
+ class ConfigurationTest < Test::Unit::TestCase
4
+
5
+ context "CloudCrowd Configuration" do
6
+
7
+ should "have read in config.yml" do
8
+ assert CloudCrowd.config[:num_workers] == 4
9
+ assert CloudCrowd.config[:storage] == 'filesystem'
10
+ end
11
+
12
+ should "allow config.yml to configure the implementation of AssetStore" do
13
+ assert CloudCrowd::AssetStore.ancestors.include?(CloudCrowd::AssetStore::FilesystemStore)
14
+ end
15
+
16
+ should "have properly configured the ActiveRecord database" do
17
+ assert ActiveRecord::Base.connection.active?
18
+ end
19
+
20
+ should "have loaded in the default set of actions" do
21
+ assert CloudCrowd.actions['word_count'] == WordCount
22
+ assert CloudCrowd.actions['process_pdfs'] == ProcessPdfs
23
+ assert CloudCrowd.actions['graphics_magick'] == GraphicsMagick
24
+ end
25
+
26
+ end
27
+
28
+ end
@@ -0,0 +1,78 @@
1
+ require 'test_helper'
2
+
3
+ class JobTest < Test::Unit::TestCase
4
+
5
+ context "A CloudCrowd Job" do
6
+
7
+ setup do
8
+ @job = CloudCrowd::Job.make
9
+ @unit = @job.work_units.first
10
+ end
11
+
12
+ subject { @job }
13
+
14
+ should_have_many :work_units
15
+
16
+ should_validate_presence_of :status, :inputs, :action, :options
17
+
18
+ should "create all of its work units as soon as the job is created" do
19
+ assert @job.work_units.count >= 1
20
+ assert @job.percent_complete == 0
21
+ assert @job.processing?
22
+ assert @unit.processing?
23
+ assert !@job.all_work_units_complete?
24
+ end
25
+
26
+ should "know its completion status" do
27
+ assert !@job.all_work_units_complete?
28
+ @unit.update_attributes(:status => CloudCrowd::SUCCEEDED, :output => '{"output":"hello"}')
29
+ assert @job.reload.all_work_units_complete?
30
+ assert @job.percent_complete == 100
31
+ assert @job.outputs == "[\"hello\"]"
32
+ end
33
+
34
+ should "be able to create a job from a JSON request" do
35
+ job = CloudCrowd::Job.create_from_request(JSON.parse(<<-EOS
36
+ { "inputs" : ["one", "two", "three"],
37
+ "action" : "graphics_magick",
38
+ "email" : "bob@example.com",
39
+ "callback_url" : "http://example.com/callback" }
40
+ EOS
41
+ ))
42
+ assert job.work_units.count == 3
43
+ assert job.action == 'graphics_magick'
44
+ assert job.action_class == GraphicsMagick
45
+ assert job.callback_url == "http://example.com/callback"
46
+ end
47
+
48
+ should "be able to return a comprehensive JSON representation" do
49
+ json = JSON.parse(@job.to_json)
50
+ assert json['email'] == 'noone@example.com'
51
+ assert json['percent_complete'] == 0
52
+ assert json['work_units'] == 1
53
+ assert json['time_taken'] > 0
54
+ end
55
+
56
+ should "create jobs with a SPLITTING status for actions that have a split method defined" do
57
+ job = CloudCrowd::Job.create_from_request({'inputs' => ['1'], 'action' => 'process_pdfs'})
58
+ assert job.splittable?
59
+ assert job.splitting?
60
+ end
61
+
62
+ should "fire a callback when a job has finished, successfully or not" do
63
+ CloudCrowd::Job.any_instance.expects(:fire_callback)
64
+ @job.work_units.first.finish('{"output":"output"}', 10)
65
+ assert @job.all_work_units_complete?
66
+ end
67
+
68
+ should "have a 'pretty' display of the Job's status" do
69
+ assert @job.display_status == 'processing'
70
+ @job.update_attribute(:status, CloudCrowd::FAILED)
71
+ assert @job.display_status == 'failed'
72
+ @job.update_attribute(:status, CloudCrowd::MERGING)
73
+ assert @job.display_status == 'merging'
74
+ end
75
+
76
+ end
77
+
78
+ end
@@ -0,0 +1,55 @@
1
+ require 'test_helper'
2
+
3
+ class WorkUnitTest < Test::Unit::TestCase
4
+
5
+ context "A WorkUnit" do
6
+
7
+ setup do
8
+ @unit = CloudCrowd::WorkUnit.make
9
+ @job = @unit.job
10
+ end
11
+
12
+ subject { @unit }
13
+
14
+ should_belong_to :job
15
+
16
+ should_validate_presence_of :job_id, :status, :input, :action
17
+
18
+ should "know if its done" do
19
+ assert !@unit.complete?
20
+ @unit.status = CloudCrowd::SUCCEEDED
21
+ assert @unit.complete?
22
+ @unit.status = CloudCrowd::FAILED
23
+ assert @unit.complete?
24
+ @unit.expects :check_for_job_completion
25
+ @unit.save
26
+ end
27
+
28
+ should "have JSON that includes job attributes" do
29
+ job = CloudCrowd::Job.make
30
+ unit_data = JSON.parse(job.work_units.first.to_json)
31
+ assert unit_data['job_id'] == job.id
32
+ assert unit_data['action'] == job.action
33
+ assert JSON.parse(job.inputs).include? unit_data['input']
34
+ end
35
+
36
+ should "be able to retry, on failure" do
37
+ @unit.update_attribute :worker_record_id, 10
38
+ assert @unit.attempts == 0
39
+ @unit.fail('oops', 10)
40
+ assert @unit.worker_record == nil
41
+ assert @unit.attempts == 1
42
+ assert @unit.processing?
43
+ @unit.fail('oops again', 10)
44
+ assert @unit.attempts == 2
45
+ assert @unit.processing?
46
+ assert @unit.job.processing?
47
+ @unit.fail('oops one last time', 10)
48
+ assert @unit.attempts == 3
49
+ assert @unit.failed?
50
+ assert @unit.job.any_work_units_failed?
51
+ end
52
+
53
+ end
54
+
55
+ end
@@ -0,0 +1,77 @@
1
+ <!DOCTYPE html>
2
+ <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
3
+ <head>
4
+ <meta http-equiv="content-type" content="text/html; charset=UTF-8" />
5
+ <title>Operations Center | CloudCrowd</title>
6
+ <link href="/css/reset.css" media="screen" rel="stylesheet" type="text/css" />
7
+ <link href="/css/admin_console.css" media="screen" rel="stylesheet" type="text/css" />
8
+ <script src="/js/jquery.js" type="text/javascript"></script>
9
+ <!--[if IE]><script src="/js/excanvas.js" type="text/javascript"></script><![endif]-->
10
+ <script src="/js/flot.js" type="text/javascript"></script>
11
+ <script src="/js/admin_console.js" type="text/javascript"></script>
12
+ </head>
13
+
14
+ <body>
15
+ <div id="container">
16
+
17
+ <div id="header">
18
+ <div id="logo"></div>
19
+ </div>
20
+
21
+ <div id="disconnected" class="small_caps" style="display:none;">
22
+ <div class="server_error"></div>
23
+ Disconnected. Attempting to reconnect&hellip;
24
+ </div>
25
+
26
+ <div id="queue">
27
+ <div id="no_jobs" class="small_caps">no jobs running&hellip;</div>
28
+ <div id="jobs">
29
+ <%# Render target for jobs. %>
30
+ </div>
31
+ <div id="queue_fill"></div>
32
+ </div>
33
+
34
+ <div id="sidebar">
35
+ <div id="sidebar_top" class="sidebar_back"></div>
36
+ <div id="sidebar_background"></div>
37
+ <div id="sidebar_bottom" class="sidebar_back"></div>
38
+ <div id="sidebar_header" class="small_caps">
39
+ <span class="has_workers">Active Worker Daemons</span>
40
+ <span class="no_workers">No Workers Running&hellip;</span>
41
+ </div>
42
+ <div id="workers">
43
+ <%# Render target for workers. %>
44
+ </div>
45
+ </div>
46
+
47
+ <div id="graphs">
48
+ <div class="graph_container">
49
+ <div class="graph_title">Work Units in Queue:</div>
50
+ <div id="work_units_graph" class="graph"></div>
51
+ </div>
52
+ <div class="graph_container">
53
+ <div class="graph_title">Jobs in Queue:</div>
54
+ <div id="jobs_graph" class="graph"></div>
55
+ </div>
56
+ <div class="graph_container">
57
+ <div class="graph_title">Active Worker Daemons:</div>
58
+ <div id="workers_graph" class="graph"></div>
59
+ </div>
60
+ </div>
61
+
62
+ <div id="worker_info" style="display:none;">
63
+ <div id="worker_info_inner" class="small_caps">
64
+ <div id="worker_details">
65
+ <div id="worker_status">status: <span class="status"></span></div>
66
+ <div id="worker_action">action: <span class="action"></span></div>
67
+ <div id="worker_job_id">job #<span class="job_id"></span> / work unit #<span class="work_unit_id"></span></div>
68
+ </div>
69
+ <div id="worker_sleeping">
70
+ worker is sleeping&hellip;
71
+ </div>
72
+ </div>
73
+ </div>
74
+
75
+ </div>
76
+ </body>
77
+ </html>
metadata ADDED
@@ -0,0 +1,233 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: cloud-crowd
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Jeremy Ashkenas
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2009-09-14 00:00:00 -04:00
13
+ default_executable:
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: sinatra
17
+ type: :runtime
18
+ version_requirement:
19
+ version_requirements: !ruby/object:Gem::Requirement
20
+ requirements:
21
+ - - ">="
22
+ - !ruby/object:Gem::Version
23
+ version: 0.9.4
24
+ version:
25
+ - !ruby/object:Gem::Dependency
26
+ name: activerecord
27
+ type: :runtime
28
+ version_requirement:
29
+ version_requirements: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: 2.3.3
34
+ version:
35
+ - !ruby/object:Gem::Dependency
36
+ name: json
37
+ type: :runtime
38
+ version_requirement:
39
+ version_requirements: !ruby/object:Gem::Requirement
40
+ requirements:
41
+ - - ">="
42
+ - !ruby/object:Gem::Version
43
+ version: 1.1.7
44
+ version:
45
+ - !ruby/object:Gem::Dependency
46
+ name: rest-client
47
+ type: :runtime
48
+ version_requirement:
49
+ version_requirements: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - ">="
52
+ - !ruby/object:Gem::Version
53
+ version: 1.0.3
54
+ version:
55
+ - !ruby/object:Gem::Dependency
56
+ name: right_aws
57
+ type: :runtime
58
+ version_requirement:
59
+ version_requirements: !ruby/object:Gem::Requirement
60
+ requirements:
61
+ - - ">="
62
+ - !ruby/object:Gem::Version
63
+ version: 1.10.0
64
+ version:
65
+ - !ruby/object:Gem::Dependency
66
+ name: daemons
67
+ type: :runtime
68
+ version_requirement:
69
+ version_requirements: !ruby/object:Gem::Requirement
70
+ requirements:
71
+ - - ">="
72
+ - !ruby/object:Gem::Version
73
+ version: 1.0.10
74
+ version:
75
+ - !ruby/object:Gem::Dependency
76
+ name: faker
77
+ type: :development
78
+ version_requirement:
79
+ version_requirements: !ruby/object:Gem::Requirement
80
+ requirements:
81
+ - - ">="
82
+ - !ruby/object:Gem::Version
83
+ version: 0.3.1
84
+ version:
85
+ - !ruby/object:Gem::Dependency
86
+ name: thoughtbot-shoulda
87
+ type: :development
88
+ version_requirement:
89
+ version_requirements: !ruby/object:Gem::Requirement
90
+ requirements:
91
+ - - ">="
92
+ - !ruby/object:Gem::Version
93
+ version: 2.10.2
94
+ version:
95
+ - !ruby/object:Gem::Dependency
96
+ name: notahat-machinist
97
+ type: :development
98
+ version_requirement:
99
+ version_requirements: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ">="
102
+ - !ruby/object:Gem::Version
103
+ version: 1.0.3
104
+ version:
105
+ - !ruby/object:Gem::Dependency
106
+ name: rack-test
107
+ type: :development
108
+ version_requirement:
109
+ version_requirements: !ruby/object:Gem::Requirement
110
+ requirements:
111
+ - - ">="
112
+ - !ruby/object:Gem::Version
113
+ version: 0.4.1
114
+ version:
115
+ - !ruby/object:Gem::Dependency
116
+ name: mocha
117
+ type: :development
118
+ version_requirement:
119
+ version_requirements: !ruby/object:Gem::Requirement
120
+ requirements:
121
+ - - ">="
122
+ - !ruby/object:Gem::Version
123
+ version: 0.9.7
124
+ version:
125
+ description: " The crowd, suddenly there where there was nothing before, is a mysterious and\n universal phenomenon. A few people may have been standing together -- five, ten\n or twelve, nor more; nothing has been announced, nothing is expected. Suddenly\n everywhere is black with people and more come streaming from all sides as though\n streets had only one direction.\n"
126
+ email: jeremy@documentcloud.org
127
+ executables:
128
+ - crowd
129
+ extensions: []
130
+
131
+ extra_rdoc_files:
132
+ - README
133
+ files:
134
+ - actions/graphics_magick.rb
135
+ - actions/process_pdfs.rb
136
+ - actions/word_count.rb
137
+ - cloud-crowd.gemspec
138
+ - config/config.example.ru
139
+ - config/config.example.yml
140
+ - config/database.example.yml
141
+ - EPIGRAPHS
142
+ - examples/graphics_magick_example.rb
143
+ - examples/process_pdfs_example.rb
144
+ - examples/word_count_example.rb
145
+ - lib/cloud-crowd.rb
146
+ - lib/cloud_crowd/action.rb
147
+ - lib/cloud_crowd/app.rb
148
+ - lib/cloud_crowd/asset_store/filesystem_store.rb
149
+ - lib/cloud_crowd/asset_store/s3_store.rb
150
+ - lib/cloud_crowd/asset_store.rb
151
+ - lib/cloud_crowd/command_line.rb
152
+ - lib/cloud_crowd/daemon.rb
153
+ - lib/cloud_crowd/exceptions.rb
154
+ - lib/cloud_crowd/helpers/authorization.rb
155
+ - lib/cloud_crowd/helpers/resources.rb
156
+ - lib/cloud_crowd/helpers.rb
157
+ - lib/cloud_crowd/inflector.rb
158
+ - lib/cloud_crowd/models/job.rb
159
+ - lib/cloud_crowd/models/work_unit.rb
160
+ - lib/cloud_crowd/models/worker_record.rb
161
+ - lib/cloud_crowd/models.rb
162
+ - lib/cloud_crowd/runner.rb
163
+ - lib/cloud_crowd/schema.rb
164
+ - lib/cloud_crowd/worker.rb
165
+ - LICENSE
166
+ - public/css/admin_console.css
167
+ - public/css/reset.css
168
+ - public/images/bullet_green.png
169
+ - public/images/bullet_white.png
170
+ - public/images/cloud_hand.png
171
+ - public/images/header_back.png
172
+ - public/images/logo.png
173
+ - public/images/queue_fill.png
174
+ - public/images/server_error.png
175
+ - public/images/sidebar_bottom.png
176
+ - public/images/sidebar_top.png
177
+ - public/images/worker_info.png
178
+ - public/images/worker_info_loading.gif
179
+ - public/js/admin_console.js
180
+ - public/js/excanvas.js
181
+ - public/js/flot.js
182
+ - public/js/jquery.js
183
+ - README
184
+ - test/acceptance/test_app.rb
185
+ - test/acceptance/test_failing_work_units.rb
186
+ - test/acceptance/test_word_count.rb
187
+ - test/blueprints.rb
188
+ - test/config/config.ru
189
+ - test/config/config.yml
190
+ - test/config/database.yml
191
+ - test/config/actions/failure_testing.rb
192
+ - test/test_helper.rb
193
+ - test/unit/test_action.rb
194
+ - test/unit/test_configuration.rb
195
+ - test/unit/test_job.rb
196
+ - test/unit/test_work_unit.rb
197
+ - views/index.erb
198
+ has_rdoc: true
199
+ homepage: http://wiki.github.com/documentcloud/cloud-crowd
200
+ licenses: []
201
+
202
+ post_install_message:
203
+ rdoc_options:
204
+ - --title
205
+ - CloudCrowd | Parallel Processing for the Rest of Us
206
+ - --exclude
207
+ - test
208
+ - --main
209
+ - README
210
+ - --all
211
+ require_paths:
212
+ - lib
213
+ required_ruby_version: !ruby/object:Gem::Requirement
214
+ requirements:
215
+ - - ">="
216
+ - !ruby/object:Gem::Version
217
+ version: "0"
218
+ version:
219
+ required_rubygems_version: !ruby/object:Gem::Requirement
220
+ requirements:
221
+ - - ">="
222
+ - !ruby/object:Gem::Version
223
+ version: "0"
224
+ version:
225
+ requirements: []
226
+
227
+ rubyforge_project: cloud-crowd
228
+ rubygems_version: 1.3.5
229
+ signing_key:
230
+ specification_version: 3
231
+ summary: Parallel Processing for the Rest of Us
232
+ test_files: []
233
+