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.
Files changed (41) hide show
  1. checksums.yaml +7 -0
  2. data/.rspec +2 -0
  3. data/Gemfile +5 -0
  4. data/Guardfile +4 -0
  5. data/Rakefile +2 -0
  6. data/app/css/application.sass +124 -0
  7. data/app/css/vendor/bootstrap-theme.css +384 -0
  8. data/app/css/vendor/bootstrap-theme.min.css +1 -0
  9. data/app/css/vendor/bootstrap.css +6805 -0
  10. data/app/css/vendor/bootstrap.min.css +9 -0
  11. data/app/js/index.coffee +51 -0
  12. data/app/js/models.coffee +177 -0
  13. data/app/js/tasksets.coffee +305 -0
  14. data/app/js/vendor/backbone-min.js +2 -0
  15. data/app/js/vendor/backbone-min.map +1 -0
  16. data/app/js/vendor/backbone.js +1581 -0
  17. data/app/js/vendor/bootstrap.js +1999 -0
  18. data/app/js/vendor/bootstrap.min.js +6 -0
  19. data/app/js/vendor/jquery-1.10.2.js +9789 -0
  20. data/app/js/vendor/jquery-1.10.2.min.js +6 -0
  21. data/app/js/vendor/jquery-1.10.2.min.map +1 -0
  22. data/app/js/vendor/moment.min.js +6 -0
  23. data/app/js/vendor/mustache.js +551 -0
  24. data/app/js/vendor/underscore-min.js +6 -0
  25. data/app/js/vendor/underscore-min.map +1 -0
  26. data/app/js/vendor/underscore.js +1276 -0
  27. data/compass.config +2 -0
  28. data/lib/rrrspec/web.rb +22 -0
  29. data/lib/rrrspec/web/api.rb +55 -0
  30. data/lib/rrrspec/web/app.rb +48 -0
  31. data/lib/rrrspec/web/configuration.rb +12 -0
  32. data/lib/rrrspec/web/persistent_models.rb +16 -0
  33. data/lib/rrrspec/web/version.rb +5 -0
  34. data/rrrspec-web.gemspec +47 -0
  35. data/spec/rrrspec/web/api_spec.rb +118 -0
  36. data/spec/spec_helper.rb +77 -0
  37. data/tasks/assets.rake +6 -0
  38. data/views/index.haml +46 -0
  39. data/views/taskset.haml +161 -0
  40. data/views/user.haml +33 -0
  41. metadata +379 -0
@@ -0,0 +1,2 @@
1
+ project_path = File.dirname(__FILE__)
2
+ sass_dir = File.join(project_path, 'views')
@@ -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,12 @@
1
+ module RRRSpec
2
+ module Web
3
+ class WebConfiguration < RRRSpec::Configuration
4
+ attr_accessor :persistence_db
5
+
6
+ def initialize
7
+ super()
8
+ @type = :web
9
+ end
10
+ end
11
+ end
12
+ 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
@@ -0,0 +1,5 @@
1
+ module RRRSpec
2
+ module Web
3
+ VERSION = "0.2.0"
4
+ end
5
+ end
@@ -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
@@ -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
@@ -0,0 +1,6 @@
1
+ APP_FILE = File.expand_path('../../lib/rrrspec/web/app.rb', __FILE__)
2
+ APP_CLASS = 'RRRSpec::Web::App'
3
+ require 'sinatra/assetpack/rake'
4
+
5
+ desc 'Build assets'
6
+ task 'assets:precompile' => 'assetpack:build'
@@ -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: "#"} &larr; Newer
23
+ %li.next
24
+ %a{href: "#"}Older &rarr;
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: "#"} &larr; Newer
34
+ %li.next
35
+ %a{href: "#"}Older &rarr;
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}}