cloud-crowd 0.7.5 → 0.7.6
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/config/database.example.yml +4 -5
- data/lib/cloud-crowd.rb +15 -13
- data/lib/cloud_crowd/models.rb +5 -0
- data/lib/cloud_crowd/models/black_listed_action.rb +27 -0
- data/lib/cloud_crowd/models/node_record.rb +4 -0
- data/lib/cloud_crowd/models/work_unit.rb +2 -1
- data/lib/cloud_crowd/schema.rb +5 -0
- data/lib/cloud_crowd/server.rb +25 -0
- data/lib/cloud_crowd/version.rb +2 -2
- data/public/css/admin_console.css +19 -1
- data/public/js/admin_console.js +23 -0
- data/test/test_helper.rb +1 -0
- data/test/unit/test_black_listed_action.rb +33 -0
- data/views/operations_center.erb +16 -0
- metadata +6 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 1d33763aebe17845688903d5e4c15f7c9be07833
|
4
|
+
data.tar.gz: 95c586ec36d78a80c4e648017ad3e8c245b73206
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f04bca0a15c63970099d8595323237962764a6050d0a433ac4c1b8cb6c00f2881578cd24a769adaf20952ba852f3cb21b2cec667456dcce670442acd05ff0a89
|
7
|
+
data.tar.gz: 4a26778718399824ffbc749c099808b38433d3b6864fb1439336b5bf4d8b1a4c1b50db29c2dc11263c1d11d8c3a5ce105c0dac93bb0134ef76b2626aecdbaf74
|
data/config/database.example.yml
CHANGED
@@ -2,12 +2,11 @@
|
|
2
2
|
# to use any database that ActiveRecord supports. Only the central server needs
|
3
3
|
# this file to be configured -- nodes never connect directly to the database.
|
4
4
|
|
5
|
-
:adapter:
|
6
|
-
:encoding:
|
7
|
-
:
|
8
|
-
:password:
|
9
|
-
:socket: /tmp/mysql.sock
|
5
|
+
:adapter: postgresql
|
6
|
+
:encoding: unicode
|
7
|
+
:host: localhost
|
10
8
|
:database: cloud_crowd
|
9
|
+
allow_concurrency: true
|
11
10
|
|
12
11
|
# If you'd prefer to use an SQLite database instead, the following configuration
|
13
12
|
# will do nicely:
|
data/lib/cloud-crowd.rb
CHANGED
@@ -35,21 +35,23 @@ ActiveModel::Serializer.root = false
|
|
35
35
|
module CloudCrowd
|
36
36
|
|
37
37
|
# Autoload all the CloudCrowd internals.
|
38
|
-
autoload :Action,
|
39
|
-
autoload :AssetStore,
|
40
|
-
autoload :CommandLine,
|
41
|
-
autoload :Helpers,
|
42
|
-
autoload :Inflector,
|
43
|
-
autoload :
|
44
|
-
autoload :
|
45
|
-
autoload :
|
46
|
-
autoload :
|
47
|
-
autoload :
|
48
|
-
autoload :
|
49
|
-
autoload :
|
38
|
+
autoload :Action, 'cloud_crowd/action'
|
39
|
+
autoload :AssetStore, 'cloud_crowd/asset_store'
|
40
|
+
autoload :CommandLine, 'cloud_crowd/command_line'
|
41
|
+
autoload :Helpers, 'cloud_crowd/helpers'
|
42
|
+
autoload :Inflector, 'cloud_crowd/inflector'
|
43
|
+
autoload :MODELS, 'cloud_crowd/models'
|
44
|
+
autoload :Job, 'cloud_crowd/models'
|
45
|
+
autoload :BlackListedAction, 'cloud_crowd/models'
|
46
|
+
autoload :Node, 'cloud_crowd/node'
|
47
|
+
autoload :NodeRecord, 'cloud_crowd/models'
|
48
|
+
autoload :Server, 'cloud_crowd/server'
|
49
|
+
autoload :Worker, 'cloud_crowd/worker'
|
50
|
+
autoload :WorkUnit, 'cloud_crowd/models'
|
51
|
+
autoload :Dispatcher, 'cloud_crowd/dispatcher'
|
50
52
|
|
51
53
|
# Increment the schema version when there's a backwards incompatible change.
|
52
|
-
SCHEMA_VERSION =
|
54
|
+
SCHEMA_VERSION = 5
|
53
55
|
|
54
56
|
# Root directory of the CloudCrowd gem.
|
55
57
|
ROOT = File.expand_path(File.dirname(__FILE__) + '/..')
|
data/lib/cloud_crowd/models.rb
CHANGED
@@ -38,3 +38,8 @@ end
|
|
38
38
|
require 'cloud_crowd/models/job'
|
39
39
|
require 'cloud_crowd/models/node_record'
|
40
40
|
require 'cloud_crowd/models/work_unit'
|
41
|
+
require 'cloud_crowd/models/black_listed_action'
|
42
|
+
|
43
|
+
module CloudCrowd
|
44
|
+
MODELS = [Job, NodeRecord, WorkUnit, BlackListedAction]
|
45
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module CloudCrowd
|
2
|
+
|
3
|
+
# A Black Listed Action is an action that has been disabled from running. For example, we may
|
4
|
+
# want to disable calls to a particular API once we have reached a rate limit.
|
5
|
+
# When a Node exits, it destroys this record.
|
6
|
+
class BlackListedAction < ActiveRecord::Base
|
7
|
+
|
8
|
+
validates_presence_of :action
|
9
|
+
validates :action, uniqueness: true
|
10
|
+
validates :action, format: { with: /\A[a-z_]+\z/, message: "action names must be alphabetic snakecase" }
|
11
|
+
|
12
|
+
# Update items on our blacklist that have expired and can now be run
|
13
|
+
# def self.update_black_list
|
14
|
+
# black_list = BlackListedAction.where.not(:duration_in_seconds => [nil,'',0])
|
15
|
+
# black_list.each do |item|
|
16
|
+
# target_time = item.created_at.to_i + item.duration_in_seconds
|
17
|
+
# item.delete if target_time < Time.now.to_i
|
18
|
+
# end
|
19
|
+
# end
|
20
|
+
|
21
|
+
# Returns the time the blacklisting will be removed
|
22
|
+
# def finish_time
|
23
|
+
# return nil if self.duration_in_seconds.nil?
|
24
|
+
# Time.at(self.created_at.to_i + self.duration_in_seconds)
|
25
|
+
# end
|
26
|
+
end
|
27
|
+
end
|
@@ -40,6 +40,10 @@ module CloudCrowd
|
|
40
40
|
create!(attrs.merge(host_attr))
|
41
41
|
end
|
42
42
|
end
|
43
|
+
|
44
|
+
def self.available_actions
|
45
|
+
available.map(&:actions).flatten.uniq - BlackListedAction.all.pluck(:action)
|
46
|
+
end
|
43
47
|
|
44
48
|
# Dispatch a WorkUnit to this node. Places the node at back at the end of
|
45
49
|
# the rotation. If we fail to send the WorkUnit, we consider the node to be
|
@@ -42,7 +42,8 @@ module CloudCrowd
|
|
42
42
|
# Find the available nodes, and determine what actions we're capable
|
43
43
|
# of running at the moment.
|
44
44
|
available_nodes = NodeRecord.available.to_a
|
45
|
-
available_actions =
|
45
|
+
available_actions = NodeRecord.available_actions
|
46
|
+
|
46
47
|
filter = "action in (#{available_actions.map{|a| "'#{a}'"}.join(',')})"
|
47
48
|
|
48
49
|
# If there aren't any available nodes or actions don't bother doing anything.
|
data/lib/cloud_crowd/schema.rb
CHANGED
@@ -26,6 +26,11 @@ ActiveRecord::Schema.define(:version => CloudCrowd::SCHEMA_VERSION) do
|
|
26
26
|
t.datetime "updated_at"
|
27
27
|
end
|
28
28
|
|
29
|
+
create_table "black_listed_actions", :force => true do |t|
|
30
|
+
t.string "action", :null => false
|
31
|
+
t.datetime "created_at"
|
32
|
+
end
|
33
|
+
|
29
34
|
create_table "work_units", :force => true do |t|
|
30
35
|
t.integer "status", :null => false
|
31
36
|
t.integer "job_id", :null => false
|
data/lib/cloud_crowd/server.rb
CHANGED
@@ -81,6 +81,31 @@ module CloudCrowd
|
|
81
81
|
json current_job
|
82
82
|
end
|
83
83
|
|
84
|
+
# Create a new blacklist item.
|
85
|
+
post '/blacklist' do
|
86
|
+
banned_action = BlackListedAction.new({:action=> params[:action]})
|
87
|
+
CloudCrowd.log("Blacklist ##{banned_action.id} (#{banned_action.action}) created.") unless ENV['RACK_ENV'] == 'test'
|
88
|
+
if banned_action.save
|
89
|
+
json banned_action
|
90
|
+
else
|
91
|
+
json banned_action.errors
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
# Delete a blacklist by action name
|
96
|
+
delete '/blacklist/:action' do
|
97
|
+
if action_ban = BlackListedAction.where(:action => params[:action]).first
|
98
|
+
json action_ban.destroy
|
99
|
+
else
|
100
|
+
raise not_found
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
# Retrieve a list of blacklisted actions and information about them.
|
105
|
+
get '/blacklist' do
|
106
|
+
json BlackListedAction.all
|
107
|
+
end
|
108
|
+
|
84
109
|
# Cleans up a Job's saved S3 files. Delete a Job after you're done
|
85
110
|
# downloading the results.
|
86
111
|
delete '/jobs/:job_id' do
|
data/lib/cloud_crowd/version.rb
CHANGED
@@ -204,4 +204,22 @@ body {
|
|
204
204
|
}
|
205
205
|
.graph {
|
206
206
|
height: 150px;
|
207
|
-
}
|
207
|
+
}
|
208
|
+
.info_table {
|
209
|
+
width: 300px;
|
210
|
+
outline: #555555 solid 2px;
|
211
|
+
text-align: center;
|
212
|
+
margin-left: 15px;
|
213
|
+
}
|
214
|
+
.info_table thead tr {
|
215
|
+
font-size: 16px;
|
216
|
+
color: #454545;
|
217
|
+
height: 50px;
|
218
|
+
background-color: white;
|
219
|
+
}
|
220
|
+
.info_table tbody tr {
|
221
|
+
height: 30px;
|
222
|
+
background-color: white;
|
223
|
+
}
|
224
|
+
|
225
|
+
|
data/public/js/admin_console.js
CHANGED
@@ -44,6 +44,7 @@ window.Console = {
|
|
44
44
|
this._workUnitCountEl = $('#work_unit_count');
|
45
45
|
this._nodeCountEl = $('#node_count');
|
46
46
|
this._workerCountEl = $('#worker_count');
|
47
|
+
this._blacklistEl = $('#blacklist');
|
47
48
|
this._disconnected = $('#disconnected');
|
48
49
|
$(window).bind('resize', Console.renderGraphs);
|
49
50
|
$('#nodes .worker').live('click', Console.getWorkerInfo);
|
@@ -51,6 +52,7 @@ window.Console = {
|
|
51
52
|
$('#workers_legend').css({background : this.WORKERS_COLOR});
|
52
53
|
$('#nodes_legend').css({background : this.NODES_COLOR});
|
53
54
|
this.getStatus();
|
55
|
+
this.getBlacklist();
|
54
56
|
$.each(this.PRELOAD_IMAGES, function(){ var i = new Image(); i.src = this; });
|
55
57
|
},
|
56
58
|
|
@@ -74,6 +76,27 @@ window.Console = {
|
|
74
76
|
}});
|
75
77
|
},
|
76
78
|
|
79
|
+
// Request the blacklisted actions from our server
|
80
|
+
getBlacklist : function () {
|
81
|
+
$.ajax({url : 'blacklist', dataType: 'json', success : function(resp) {
|
82
|
+
Console._blacklist = resp;
|
83
|
+
if (Console._disconnected.is(':visible')) Console._disconnected.fadeOut(Console.ANIMATION_SPEED);
|
84
|
+
Console.renderBlacklist();
|
85
|
+
setTimeout(Console.getBlacklist, Console.POLL_INTERVAL);
|
86
|
+
}, error : function(request, status, errorThrown) {
|
87
|
+
if (!Console._disconnected.is(':visible')) Console._disconnected.fadeIn(Console.ANIMATION_SPEED);
|
88
|
+
setTimeout(Console.getBlacklist, Console.POLL_INTERVAL);
|
89
|
+
}});
|
90
|
+
},
|
91
|
+
|
92
|
+
// Render the blacklisted actions
|
93
|
+
renderBlacklist : function() {
|
94
|
+
Console._blacklistEl.empty()
|
95
|
+
this._blacklist.forEach(function(d){
|
96
|
+
Console._blacklistEl.append("<tr><td>" + d.action + "</td><td>" + d.created_at + "</td></tr>")
|
97
|
+
});
|
98
|
+
},
|
99
|
+
|
77
100
|
// Fetch the last 100 lines of log from the server.
|
78
101
|
tailLog : function() {
|
79
102
|
$.ajax({url : 'log', success : function(resp) {
|
data/test/test_helper.rb
CHANGED
@@ -0,0 +1,33 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
class BlackListedActionTest < Minitest::Test
|
4
|
+
|
5
|
+
context "A CloudCrowd::BlackListedAction" do
|
6
|
+
|
7
|
+
setup do
|
8
|
+
BlackListedAction.destroy_all
|
9
|
+
@black_listed_action = BlackListedAction.create(action: 'word_count')
|
10
|
+
@node = NodeRecord.make!
|
11
|
+
end
|
12
|
+
|
13
|
+
teardown do
|
14
|
+
BlackListedAction.destroy_all
|
15
|
+
end
|
16
|
+
|
17
|
+
should "fail if trying to create a duplicate blacklist entry" do
|
18
|
+
duplicate = BlackListedAction.create(action: 'word_count')
|
19
|
+
assert duplicate.errors.first[1] == "has already been taken"
|
20
|
+
end
|
21
|
+
|
22
|
+
should "create valid black listed action object" do
|
23
|
+
assert @black_listed_action.present?
|
24
|
+
end
|
25
|
+
|
26
|
+
should "not execute job because it is blacklisted" do
|
27
|
+
assert NodeRecord.all.map(&:actions).flatten.uniq.include? @black_listed_action.action
|
28
|
+
refute NodeRecord.available_actions.include? @black_listed_action.action
|
29
|
+
end
|
30
|
+
|
31
|
+
end
|
32
|
+
|
33
|
+
end
|
data/views/operations_center.erb
CHANGED
@@ -75,6 +75,22 @@
|
|
75
75
|
</div>
|
76
76
|
<div id="workers_graph" class="graph"></div>
|
77
77
|
</div>
|
78
|
+
<div class="graph_container">
|
79
|
+
<div class="graph_title">
|
80
|
+
Blacklisted Actions
|
81
|
+
</div>
|
82
|
+
<table class="info_table">
|
83
|
+
<thead>
|
84
|
+
<tr class="heading">
|
85
|
+
<th>Name</th>
|
86
|
+
<th>Disabled Time</th>
|
87
|
+
</tr>
|
88
|
+
</thead>
|
89
|
+
<tbody id="blacklist">
|
90
|
+
</tbody>
|
91
|
+
</table>
|
92
|
+
<div id="actions_table" class="table"></div>
|
93
|
+
</div>
|
78
94
|
</div>
|
79
95
|
|
80
96
|
<div id="worker_info" style="display:none;">
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: cloud-crowd
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.7.
|
4
|
+
version: 0.7.6
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jeremy Ashkenas
|
@@ -10,7 +10,7 @@ authors:
|
|
10
10
|
autorequire:
|
11
11
|
bindir: bin
|
12
12
|
cert_chain: []
|
13
|
-
date: 2015-
|
13
|
+
date: 2015-10-28 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: activerecord
|
@@ -221,6 +221,7 @@ files:
|
|
221
221
|
- lib/cloud_crowd/helpers/resources.rb
|
222
222
|
- lib/cloud_crowd/inflector.rb
|
223
223
|
- lib/cloud_crowd/models.rb
|
224
|
+
- lib/cloud_crowd/models/black_listed_action.rb
|
224
225
|
- lib/cloud_crowd/models/job.rb
|
225
226
|
- lib/cloud_crowd/models/node_record.rb
|
226
227
|
- lib/cloud_crowd/models/work_unit.rb
|
@@ -261,6 +262,7 @@ files:
|
|
261
262
|
- test/config/database.yml
|
262
263
|
- test/test_helper.rb
|
263
264
|
- test/unit/test_action.rb
|
265
|
+
- test/unit/test_black_listed_action.rb
|
264
266
|
- test/unit/test_command_line.rb
|
265
267
|
- test/unit/test_configuration.rb
|
266
268
|
- test/unit/test_job.rb
|
@@ -296,8 +298,9 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
296
298
|
version: '0'
|
297
299
|
requirements: []
|
298
300
|
rubyforge_project: cloud-crowd
|
299
|
-
rubygems_version: 2.
|
301
|
+
rubygems_version: 2.4.5
|
300
302
|
signing_key:
|
301
303
|
specification_version: 4
|
302
304
|
summary: Parallel Processing for the Rest of Us
|
303
305
|
test_files: []
|
306
|
+
has_rdoc:
|