rrrspec-web 0.2.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.
- checksums.yaml +7 -0
- data/.rspec +2 -0
- data/Gemfile +5 -0
- data/Guardfile +4 -0
- data/Rakefile +2 -0
- data/app/css/application.sass +124 -0
- data/app/css/vendor/bootstrap-theme.css +384 -0
- data/app/css/vendor/bootstrap-theme.min.css +1 -0
- data/app/css/vendor/bootstrap.css +6805 -0
- data/app/css/vendor/bootstrap.min.css +9 -0
- data/app/js/index.coffee +51 -0
- data/app/js/models.coffee +177 -0
- data/app/js/tasksets.coffee +305 -0
- data/app/js/vendor/backbone-min.js +2 -0
- data/app/js/vendor/backbone-min.map +1 -0
- data/app/js/vendor/backbone.js +1581 -0
- data/app/js/vendor/bootstrap.js +1999 -0
- data/app/js/vendor/bootstrap.min.js +6 -0
- data/app/js/vendor/jquery-1.10.2.js +9789 -0
- data/app/js/vendor/jquery-1.10.2.min.js +6 -0
- data/app/js/vendor/jquery-1.10.2.min.map +1 -0
- data/app/js/vendor/moment.min.js +6 -0
- data/app/js/vendor/mustache.js +551 -0
- data/app/js/vendor/underscore-min.js +6 -0
- data/app/js/vendor/underscore-min.map +1 -0
- data/app/js/vendor/underscore.js +1276 -0
- data/compass.config +2 -0
- data/lib/rrrspec/web.rb +22 -0
- data/lib/rrrspec/web/api.rb +55 -0
- data/lib/rrrspec/web/app.rb +48 -0
- data/lib/rrrspec/web/configuration.rb +12 -0
- data/lib/rrrspec/web/persistent_models.rb +16 -0
- data/lib/rrrspec/web/version.rb +5 -0
- data/rrrspec-web.gemspec +47 -0
- data/spec/rrrspec/web/api_spec.rb +118 -0
- data/spec/spec_helper.rb +77 -0
- data/tasks/assets.rake +6 -0
- data/views/index.haml +46 -0
- data/views/taskset.haml +161 -0
- data/views/user.haml +33 -0
- metadata +379 -0
data/compass.config
ADDED
data/lib/rrrspec/web.rb
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
require 'active_record'
|
2
|
+
require 'kaminari/grape'
|
3
|
+
|
4
|
+
require 'rrrspec'
|
5
|
+
require 'rrrspec/server'
|
6
|
+
require 'rrrspec/web/persistent_models'
|
7
|
+
require 'rrrspec/web/api'
|
8
|
+
require 'rrrspec/web/app'
|
9
|
+
require 'rrrspec/web/configuration'
|
10
|
+
|
11
|
+
RRRSpec.configuration = RRRSpec::Web::WebConfiguration.new
|
12
|
+
|
13
|
+
module RRRSpec
|
14
|
+
module Web
|
15
|
+
def self.setup
|
16
|
+
ActiveRecord::Base.establish_connection(
|
17
|
+
**RRRSpec.configuration.persistence_db
|
18
|
+
)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
@@ -0,0 +1,55 @@
|
|
1
|
+
require 'grape'
|
2
|
+
require 'api-pagination'
|
3
|
+
|
4
|
+
module RRRSpec
|
5
|
+
module Web
|
6
|
+
class API < Grape::API
|
7
|
+
version 'v1', using: :path
|
8
|
+
format :json
|
9
|
+
|
10
|
+
resource :tasksets do
|
11
|
+
desc "Return active tasksets"
|
12
|
+
get :actives do
|
13
|
+
ActiveTaskset.list
|
14
|
+
end
|
15
|
+
|
16
|
+
desc "Return recently finished tasksets"
|
17
|
+
get :recents do
|
18
|
+
paginate(RRRSpec::Server::Persistence::Taskset.recent).map(&:as_json_with_no_relation)
|
19
|
+
end
|
20
|
+
|
21
|
+
desc "Return tasksets that contains failure_exit slave"
|
22
|
+
get :failure_slaves do
|
23
|
+
paginate(RRRSpec::Server::Persistence::Taskset.has_failed_slaves.recent).map(&:as_json_with_no_relation)
|
24
|
+
end
|
25
|
+
|
26
|
+
desc "Return a taskset."
|
27
|
+
params { requires :key, type: String, desc: "Taskset key." }
|
28
|
+
route_param :key do
|
29
|
+
get do
|
30
|
+
p_obj = RRRSpec::Server::Persistence::Taskset.where(key: params[:key]).full.first
|
31
|
+
if p_obj
|
32
|
+
p_obj.as_full_json.update('is_full' => true)
|
33
|
+
else
|
34
|
+
error!('Not Found', 404)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
namespace :batch do
|
41
|
+
resource :tasks do
|
42
|
+
desc "Return all tasks in the taskset"
|
43
|
+
params { requires :key, type: String, desc: "Taskset key." }
|
44
|
+
route_param :key do
|
45
|
+
get do
|
46
|
+
r_taskset = Taskset.new(params[:key])
|
47
|
+
error!('Not Found', 404) unless r_taskset.exist?
|
48
|
+
r_taskset.tasks.map(&:to_h)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
require 'sinatra/base'
|
2
|
+
require 'sinatra/assetpack'
|
3
|
+
require 'haml'
|
4
|
+
require 'sass'
|
5
|
+
require 'coffee-script'
|
6
|
+
|
7
|
+
module RRRSpec
|
8
|
+
module Web
|
9
|
+
class App < Sinatra::Base
|
10
|
+
configure do
|
11
|
+
set :root, File.expand_path(File.join(__FILE__, '..', '..', '..', '..'))
|
12
|
+
set :haml, :format => :html5
|
13
|
+
end
|
14
|
+
|
15
|
+
register Sinatra::AssetPack
|
16
|
+
|
17
|
+
assets do
|
18
|
+
JSLIBS = [
|
19
|
+
'/js/vendor/jquery-1.10.2.min.js',
|
20
|
+
'/js/vendor/underscore-min.js',
|
21
|
+
'/js/vendor/backbone-min.js',
|
22
|
+
'/js/vendor/mustache.js',
|
23
|
+
'/js/vendor/bootstrap.min.js',
|
24
|
+
'/js/vendor/moment.min.js',
|
25
|
+
'/js/models.js',
|
26
|
+
]
|
27
|
+
|
28
|
+
CSSLIBS = [
|
29
|
+
'/css/vendor/bootstrap.min.css',
|
30
|
+
'/css/vendor/bootstrap-theme.min.css',
|
31
|
+
]
|
32
|
+
|
33
|
+
js :tasksets, JSLIBS + ["/js/tasksets.js"]
|
34
|
+
js :index, JSLIBS + ["/js/index.js"]
|
35
|
+
css :application, CSSLIBS + ["/css/application.css"]
|
36
|
+
|
37
|
+
js_compression :jsmin
|
38
|
+
css_compression :simple
|
39
|
+
|
40
|
+
prebuild true
|
41
|
+
cache_dynamic_assets true
|
42
|
+
end
|
43
|
+
|
44
|
+
get('/') { haml :index }
|
45
|
+
get('/tasksets/*') { haml :taskset }
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
# Extensions to RRRSpec::Server::Persistence
|
2
|
+
|
3
|
+
module RRRSpec
|
4
|
+
module Server
|
5
|
+
module Persistence
|
6
|
+
class Taskset
|
7
|
+
scope :recent, order('finished_at DESC')
|
8
|
+
scope :has_failed_slaves, includes(:slaves).where(slaves: {status: 'failure_exit'})
|
9
|
+
|
10
|
+
def as_json_with_no_relation
|
11
|
+
as_json(except: :id)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
data/rrrspec-web.gemspec
ADDED
@@ -0,0 +1,47 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'rrrspec/web/version'
|
5
|
+
require 'pathname'
|
6
|
+
|
7
|
+
Gem::Specification.new do |spec|
|
8
|
+
spec.name = "rrrspec-web"
|
9
|
+
spec.version = RRRSpec::Web::VERSION
|
10
|
+
spec.authors = ["Masaya Suzuki"]
|
11
|
+
spec.email = ["draftcode@gmail.com"]
|
12
|
+
spec.description = "Execute RSpec in a distributed manner"
|
13
|
+
spec.summary = "Execute RSpec in a distributed manner"
|
14
|
+
spec.homepage = ""
|
15
|
+
spec.license = "MIT"
|
16
|
+
|
17
|
+
gemspec_dir = File.expand_path('..', __FILE__)
|
18
|
+
spec.files = `git ls-files`.split($/).
|
19
|
+
map { |f| File.absolute_path(f) }.
|
20
|
+
select { |f| f.start_with?(gemspec_dir) }.
|
21
|
+
map { |f| Pathname(f).relative_path_from(Pathname(gemspec_dir)).to_s }
|
22
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
23
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
24
|
+
spec.require_paths = ["lib"]
|
25
|
+
|
26
|
+
spec.add_development_dependency "bundler", "~> 1.4"
|
27
|
+
spec.add_development_dependency "rake"
|
28
|
+
spec.add_development_dependency "rspec"
|
29
|
+
spec.add_development_dependency "rack-test"
|
30
|
+
spec.add_development_dependency "database_cleaner", "~> 1.2.0"
|
31
|
+
spec.add_development_dependency "sqlite3"
|
32
|
+
spec.add_development_dependency "mysql2"
|
33
|
+
spec.add_development_dependency "guard-livereload"
|
34
|
+
spec.add_development_dependency "rack-livereload"
|
35
|
+
spec.add_dependency "activerecord", "~> 3.0"
|
36
|
+
spec.add_dependency "activesupport"
|
37
|
+
spec.add_dependency "api-pagination"
|
38
|
+
spec.add_dependency "coffee-script", "~> 2.2.0"
|
39
|
+
spec.add_dependency "grape"
|
40
|
+
spec.add_dependency "haml", "~> 4.0.3"
|
41
|
+
spec.add_dependency "kaminari", "~> 0.15.0"
|
42
|
+
spec.add_dependency "rrrspec-client"
|
43
|
+
spec.add_dependency "rrrspec-server"
|
44
|
+
spec.add_dependency "sass"
|
45
|
+
spec.add_dependency "sinatra", "~> 1.4.3"
|
46
|
+
spec.add_dependency "sinatra-assetpack"
|
47
|
+
end
|
@@ -0,0 +1,118 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module RRRSpec
|
4
|
+
describe Web::API do
|
5
|
+
include Rack::Test::Methods
|
6
|
+
|
7
|
+
def app
|
8
|
+
Web::API
|
9
|
+
end
|
10
|
+
|
11
|
+
before do
|
12
|
+
RRRSpec.configuration = Configuration.new
|
13
|
+
RRRSpec.configuration.redis = @redis
|
14
|
+
end
|
15
|
+
|
16
|
+
let(:taskset) do
|
17
|
+
Taskset.create(
|
18
|
+
'testuser', 'echo 1', 'echo 2', 'default', 'default', 3, 3, 5, 5
|
19
|
+
)
|
20
|
+
end
|
21
|
+
|
22
|
+
let(:task) do
|
23
|
+
Task.create(taskset, 10, 'spec/test_spec.rb')
|
24
|
+
end
|
25
|
+
|
26
|
+
let(:worker) do
|
27
|
+
Worker.create('default')
|
28
|
+
end
|
29
|
+
|
30
|
+
let(:worker_log) do
|
31
|
+
WorkerLog.create(worker, taskset)
|
32
|
+
end
|
33
|
+
|
34
|
+
let(:slave) do
|
35
|
+
Slave.create
|
36
|
+
end
|
37
|
+
|
38
|
+
before do
|
39
|
+
worker # Create worker
|
40
|
+
taskset.add_task(task)
|
41
|
+
taskset.enqueue_task(task)
|
42
|
+
ActiveTaskset.add(taskset)
|
43
|
+
worker_log # Create worker_log
|
44
|
+
worker_log.set_rsync_finished_time
|
45
|
+
worker_log.append_log('worker_log log body')
|
46
|
+
worker_log.set_setup_finished_time
|
47
|
+
slave # Create slave
|
48
|
+
taskset.add_slave(slave)
|
49
|
+
slave.append_log('slave log body')
|
50
|
+
trial = Trial.create(task, slave)
|
51
|
+
trial.start
|
52
|
+
trial.finish('pending', 'stdout body', 'stderr body', 10, 2, 0)
|
53
|
+
task.update_status('pending')
|
54
|
+
taskset.incr_succeeded_count
|
55
|
+
taskset.finish_task(task)
|
56
|
+
taskset.update_status('succeeded')
|
57
|
+
taskset.set_finished_time
|
58
|
+
ActiveTaskset.remove(taskset)
|
59
|
+
slave.update_status('normal_exit')
|
60
|
+
worker_log.set_finished_time
|
61
|
+
end
|
62
|
+
|
63
|
+
describe "GET /v1/tasksets/actives" do
|
64
|
+
before { ActiveTaskset.add(taskset) }
|
65
|
+
|
66
|
+
it 'returns the active tasksets' do
|
67
|
+
get "/v1/tasksets/actives"
|
68
|
+
expect(last_response.status).to eq(200)
|
69
|
+
expect(JSON.parse(last_response.body)).to eq(JSON.parse(ActiveTaskset.list.to_json))
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
describe "GET /v1/tasksets/recents" do
|
74
|
+
context 'there are 11 tasksets' do
|
75
|
+
before do
|
76
|
+
11.times { Server::Persistence::Taskset.create() }
|
77
|
+
end
|
78
|
+
|
79
|
+
it 'returns the recent 10 tasksets' do
|
80
|
+
get "/v1/tasksets/recents"
|
81
|
+
expect(last_response.status).to eq(200)
|
82
|
+
expect(JSON.parse(last_response.body).size).to eq(10)
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
describe "GET /v1/tasksets/:key" do
|
88
|
+
context 'with the taskset persisted' do
|
89
|
+
before do
|
90
|
+
Server::Persister.persist(taskset)
|
91
|
+
end
|
92
|
+
|
93
|
+
it 'returns the taskset' do
|
94
|
+
get "/v1/tasksets/#{taskset.key}"
|
95
|
+
expect(last_response.status).to eq(200)
|
96
|
+
expect(JSON.parse(last_response.body)).to eq(
|
97
|
+
JSON.parse(JSON.generate(Server::Persistence::Taskset.first.as_full_json)).update("is_full" => true)
|
98
|
+
)
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
context 'with the taskset not persisted' do
|
103
|
+
it 'returns 404' do
|
104
|
+
get "/v1/tasksets/#{taskset.key}"
|
105
|
+
expect(last_response.status).to eq(404)
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
describe "GET /v1/batch/tasks/:key" do
|
111
|
+
it 'returns all tasks in the taskset' do
|
112
|
+
get "/v1/batch/tasks/#{taskset.key}"
|
113
|
+
expect(last_response.status).to eq(200)
|
114
|
+
expect(JSON.parse(last_response.body)).to eq([JSON.parse(task.to_json)])
|
115
|
+
end
|
116
|
+
end
|
117
|
+
end
|
118
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,77 @@
|
|
1
|
+
# This file was generated by the `rspec --init` command. Conventionally, all
|
2
|
+
# specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`.
|
3
|
+
# Require this file using `require "spec_helper"` to ensure that it is only
|
4
|
+
# loaded once.
|
5
|
+
#
|
6
|
+
# See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
|
7
|
+
require 'rrrspec/web'
|
8
|
+
require 'rack/test'
|
9
|
+
require 'database_cleaner'
|
10
|
+
|
11
|
+
RSpec.configure do |config|
|
12
|
+
config.treat_symbols_as_metadata_keys_with_true_values = true
|
13
|
+
config.run_all_when_everything_filtered = true
|
14
|
+
config.filter_run :focus
|
15
|
+
|
16
|
+
# Run specs in random order to surface order dependencies. If you find an
|
17
|
+
# order dependency and want to debug it, you can fix the order by providing
|
18
|
+
# the seed, which is printed after each run.
|
19
|
+
# --seed 1234
|
20
|
+
config.order = 'random'
|
21
|
+
|
22
|
+
pid = nil
|
23
|
+
config.before(:suite) do
|
24
|
+
pid = Kernel.spawn("redis-server --port 9999 --save ''",
|
25
|
+
in: '/dev/null', out: '/dev/null', err: '/dev/null')
|
26
|
+
redis = Redis.new(port: 9999)
|
27
|
+
retry_count = 1
|
28
|
+
loop do
|
29
|
+
begin
|
30
|
+
redis.client.connect
|
31
|
+
break
|
32
|
+
rescue Redis::CannotConnectError
|
33
|
+
if retry_count < 10
|
34
|
+
retry_count += 1
|
35
|
+
sleep 0.01
|
36
|
+
retry
|
37
|
+
end
|
38
|
+
raise
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
config.before(:each) do
|
44
|
+
@redis = Redis.new(port: 9999)
|
45
|
+
@redis.flushall
|
46
|
+
|
47
|
+
RRRSpec.configuration = nil
|
48
|
+
RRRSpec.flushredis
|
49
|
+
RRRSpec.hostname = 'testhostname'
|
50
|
+
end
|
51
|
+
|
52
|
+
config.after(:suite) do
|
53
|
+
Process.kill('KILL', pid) if pid
|
54
|
+
end
|
55
|
+
|
56
|
+
def key(*args)
|
57
|
+
args.join(':')
|
58
|
+
end
|
59
|
+
|
60
|
+
config.before(:suite) do
|
61
|
+
ActiveRecord::Base.establish_connection(
|
62
|
+
adapter: "sqlite3", database: ":memory:"
|
63
|
+
)
|
64
|
+
ActiveRecord::Migration.verbose = false
|
65
|
+
ActiveRecord::Migrator.up "#{Gem::Specification.find_by_name('rrrspec-server').gem_dir}/db/migrate"
|
66
|
+
DatabaseCleaner.strategy = :transaction
|
67
|
+
DatabaseCleaner.clean_with(:truncation)
|
68
|
+
end
|
69
|
+
|
70
|
+
config.before(:each) do
|
71
|
+
DatabaseCleaner.start
|
72
|
+
end
|
73
|
+
|
74
|
+
config.after(:each) do
|
75
|
+
DatabaseCleaner.clean
|
76
|
+
end
|
77
|
+
end
|
data/tasks/assets.rake
ADDED
data/views/index.haml
ADDED
@@ -0,0 +1,46 @@
|
|
1
|
+
!!!
|
2
|
+
%html
|
3
|
+
%head
|
4
|
+
%meta{charset: 'utf-8', 'http-equiv' => 'Content-Type', content: 'text/html'}
|
5
|
+
%title RRRSpec
|
6
|
+
!= css :application
|
7
|
+
!= js :index
|
8
|
+
%body
|
9
|
+
.index.container
|
10
|
+
.panel.panel-default.active-tasksets
|
11
|
+
.panel-heading
|
12
|
+
.panel-title Active Tasksets
|
13
|
+
%ul.list-group.tasksets
|
14
|
+
|
15
|
+
.index.container
|
16
|
+
.panel.panel-default.recent-tasksets
|
17
|
+
.panel-heading
|
18
|
+
.panel-title Recent Tasksets
|
19
|
+
%ul.list-group.tasksets
|
20
|
+
%ul.pager
|
21
|
+
%li.previous
|
22
|
+
%a{href: "#"} ← Newer
|
23
|
+
%li.next
|
24
|
+
%a{href: "#"}Older →
|
25
|
+
|
26
|
+
.index.container
|
27
|
+
.panel.panel-default.slave-failed-tasksets
|
28
|
+
.panel-heading
|
29
|
+
.panel-title Slave Failed Tasksets
|
30
|
+
%ul.list-group.tasksets
|
31
|
+
%ul.pager
|
32
|
+
%li.previous
|
33
|
+
%a{href: "#"} ← Newer
|
34
|
+
%li.next
|
35
|
+
%a{href: "#"}Older →
|
36
|
+
|
37
|
+
%script#taskset-template{type: 'text/template'}
|
38
|
+
%ul
|
39
|
+
%li.taskset-status
|
40
|
+
{{status}}
|
41
|
+
%li
|
42
|
+
%a{href: "/tasksets/{{key}}"} {{key}}
|
43
|
+
%li.pull-right
|
44
|
+
{{#created_at}}{{created_at}} ({{created_at_humanized}}){{/created_at}}
|
45
|
+
%li.username.pull-right
|
46
|
+
{{rsync_name}}
|