singularity_dsl 1.2.5
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 +15 -0
- data/.gitignore +17 -0
- data/.rspec +2 -0
- data/.rubocop.yml +10 -0
- data/.singularityrc +12 -0
- data/Gemfile +6 -0
- data/Gemfile.lock +52 -0
- data/LICENSE.txt +22 -0
- data/README.md +38 -0
- data/Rakefile +24 -0
- data/bin/singularity_runner +5 -0
- data/lib/singularity_dsl/application.rb +76 -0
- data/lib/singularity_dsl/cli/cli.rb +125 -0
- data/lib/singularity_dsl/cli/table.rb +32 -0
- data/lib/singularity_dsl/dsl/batch.rb +23 -0
- data/lib/singularity_dsl/dsl/changeset.rb +39 -0
- data/lib/singularity_dsl/dsl/components.rb +7 -0
- data/lib/singularity_dsl/dsl/dsl.rb +71 -0
- data/lib/singularity_dsl/dsl/event_store.rb +34 -0
- data/lib/singularity_dsl/dsl/registry.rb +60 -0
- data/lib/singularity_dsl/dsl/runner.rb +67 -0
- data/lib/singularity_dsl/dsl/utils.rb +28 -0
- data/lib/singularity_dsl/errors.rb +35 -0
- data/lib/singularity_dsl/files.rb +20 -0
- data/lib/singularity_dsl/git_helper.rb +94 -0
- data/lib/singularity_dsl/runstate.rb +30 -0
- data/lib/singularity_dsl/stdout.rb +16 -0
- data/lib/singularity_dsl/task.rb +30 -0
- data/lib/singularity_dsl/tasks/rake.rb +31 -0
- data/lib/singularity_dsl/tasks/rspec.rb +32 -0
- data/lib/singularity_dsl/tasks/rubocop.rb +54 -0
- data/lib/singularity_dsl/tasks/shell_task.rb +90 -0
- data/lib/singularity_dsl/version.rb +6 -0
- data/lib/singularity_dsl.rb +9 -0
- data/singularity_dsl.gemspec +31 -0
- data/spec/singularity_dsl/application_spec.rb +92 -0
- data/spec/singularity_dsl/dsl/batch_spec.rb +30 -0
- data/spec/singularity_dsl/dsl/changeset_spec.rb +54 -0
- data/spec/singularity_dsl/dsl/dsl_spec.rb +45 -0
- data/spec/singularity_dsl/dsl/event_store_spec.rb +44 -0
- data/spec/singularity_dsl/dsl/registry_spec.rb +39 -0
- data/spec/singularity_dsl/dsl/runner_spec.rb +39 -0
- data/spec/singularity_dsl/dsl/stubs/tasks/dummy_task.rb +4 -0
- data/spec/singularity_dsl/dsl/utils_spec.rb +33 -0
- data/spec/singularity_dsl/git_helper_spec.rb +72 -0
- data/spec/singularity_dsl/runstate_spec.rb +73 -0
- data/spec/singularity_dsl/task_spec.rb +54 -0
- data/spec/singularity_dsl/tasks/shell_task_spec.rb +119 -0
- metadata +231 -0
@@ -0,0 +1,67 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'singularity_dsl/dsl/batch'
|
4
|
+
require 'singularity_dsl/dsl/dsl'
|
5
|
+
require 'singularity_dsl/errors'
|
6
|
+
require 'singularity_dsl/runstate'
|
7
|
+
|
8
|
+
module SingularityDsl
|
9
|
+
# DSL classes & fxs
|
10
|
+
module Dsl
|
11
|
+
# class that runs Singularity::Dsl
|
12
|
+
class Runner
|
13
|
+
include SingularityDsl::Errors
|
14
|
+
|
15
|
+
attr_reader :state, :dsl
|
16
|
+
|
17
|
+
def initialize
|
18
|
+
@dsl = Dsl.new
|
19
|
+
@state = Runstate.new
|
20
|
+
end
|
21
|
+
|
22
|
+
def execute(batch = false, pass_errors = false)
|
23
|
+
@dsl.registry.run_list(batch).each do |task|
|
24
|
+
task.execute.tap do |status|
|
25
|
+
failed = task.failed_status status
|
26
|
+
record_failure task if failed
|
27
|
+
resource_fail task if failed && !pass_errors
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def load_ex_script(path)
|
33
|
+
@dsl.instance_eval(::File.read path)
|
34
|
+
end
|
35
|
+
|
36
|
+
def post_actions
|
37
|
+
@dsl.error_proc.call if @state.error
|
38
|
+
@dsl.fail_proc.call if @state.failed
|
39
|
+
@dsl.success_proc.call unless @state.failed || @state.error
|
40
|
+
@dsl.always_proc.call
|
41
|
+
end
|
42
|
+
|
43
|
+
private
|
44
|
+
|
45
|
+
def record_failure(task)
|
46
|
+
failure = klass_failed(task)
|
47
|
+
failure += " #{task.task_name}" if task.task_name
|
48
|
+
@state.add_failure failure
|
49
|
+
end
|
50
|
+
|
51
|
+
def raise_dsl_set_err(dsl)
|
52
|
+
fail "Invalid object given #{dsl}"
|
53
|
+
end
|
54
|
+
|
55
|
+
def execute_task(task)
|
56
|
+
failed = false
|
57
|
+
begin
|
58
|
+
failed = task.execute
|
59
|
+
rescue ::StandardError => err
|
60
|
+
@state.add_error "#{err.message}\n#{err.backtrace}"
|
61
|
+
resource_err task
|
62
|
+
end
|
63
|
+
failed
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
module SingularityDsl
|
4
|
+
# DSL classes & fxs
|
5
|
+
module Dsl
|
6
|
+
# Utility functions mixin module
|
7
|
+
module Utils
|
8
|
+
def task_name(klass)
|
9
|
+
klass.to_s.split(':').last
|
10
|
+
end
|
11
|
+
|
12
|
+
def task(klass)
|
13
|
+
task_name(klass).downcase.to_sym
|
14
|
+
end
|
15
|
+
|
16
|
+
def task_list
|
17
|
+
klasses = []
|
18
|
+
SingularityDsl.constants.each do |klass|
|
19
|
+
klass = SingularityDsl.const_get(klass)
|
20
|
+
next unless klass.is_a? Class
|
21
|
+
next unless klass < Task
|
22
|
+
klasses.push klass
|
23
|
+
end
|
24
|
+
klasses
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
module SingularityDsl
|
4
|
+
# error & failure classes / methods
|
5
|
+
module Errors
|
6
|
+
class ResourceFail < RuntimeError
|
7
|
+
end
|
8
|
+
|
9
|
+
class ResourceError < RuntimeError
|
10
|
+
end
|
11
|
+
|
12
|
+
def klass_name(obj)
|
13
|
+
return obj.class if obj.class < Object
|
14
|
+
obj
|
15
|
+
end
|
16
|
+
|
17
|
+
def klass_error(klass)
|
18
|
+
klass = klass_name klass
|
19
|
+
"#{klass} threw an exception while executing"
|
20
|
+
end
|
21
|
+
|
22
|
+
def klass_failed(klass)
|
23
|
+
klass = klass_name klass
|
24
|
+
"#{klass} failed."
|
25
|
+
end
|
26
|
+
|
27
|
+
def resource_fail(klass)
|
28
|
+
fail ResourceFail, klass_failed(klass)
|
29
|
+
end
|
30
|
+
|
31
|
+
def resource_err(klass)
|
32
|
+
fail ResourceError, klass_error(klass)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
module SingularityDsl
|
4
|
+
# File helper fx mixin
|
5
|
+
module Files
|
6
|
+
private
|
7
|
+
|
8
|
+
def files_in_path(path)
|
9
|
+
paths = [path] if ::File.file? path
|
10
|
+
paths = dir_glob path if ::File.directory? path
|
11
|
+
paths ||= []
|
12
|
+
paths
|
13
|
+
end
|
14
|
+
|
15
|
+
def dir_glob(dir)
|
16
|
+
dir = ::File.join dir, '**'
|
17
|
+
::Dir.glob dir
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,94 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'mixlib/shellout'
|
4
|
+
|
5
|
+
module SingularityDsl
|
6
|
+
# wrapper class for rugged
|
7
|
+
class GitHelper
|
8
|
+
attr_reader :dir
|
9
|
+
|
10
|
+
def initialize
|
11
|
+
throw 'git not installed' unless git_installed
|
12
|
+
end
|
13
|
+
|
14
|
+
def clean_reset
|
15
|
+
fail 'failed to clean' unless (reset | clean) == 0
|
16
|
+
end
|
17
|
+
|
18
|
+
def checkout_remote(branch, remote)
|
19
|
+
remote_action branch, remote, 'checkout'
|
20
|
+
end
|
21
|
+
|
22
|
+
def merge_remote(branch, url)
|
23
|
+
remote_action branch, url, 'merge'
|
24
|
+
end
|
25
|
+
|
26
|
+
def diff_remote(branch, url, flags = '')
|
27
|
+
flags = flags.join ' ' if flags.kind_of? Array
|
28
|
+
cmd = remote_cmd branch, url, "diff #{flags}"
|
29
|
+
task = Mixlib::ShellOut.new cmd
|
30
|
+
task.run_command
|
31
|
+
task.stdout
|
32
|
+
end
|
33
|
+
|
34
|
+
def add_remote(url)
|
35
|
+
remote = remote_from_url url
|
36
|
+
exec("git remote add #{remote} #{url}")
|
37
|
+
fetch_all
|
38
|
+
end
|
39
|
+
|
40
|
+
def remove_remote(url)
|
41
|
+
remote = remote_from_url url
|
42
|
+
return 0 if remote.eql? 'origin'
|
43
|
+
exec("git remote rm #{remote}")
|
44
|
+
end
|
45
|
+
|
46
|
+
private
|
47
|
+
|
48
|
+
def remote_cmd(branch, url, action)
|
49
|
+
remote = remote_from_url url
|
50
|
+
"git #{action} #{remote}/#{branch}"
|
51
|
+
end
|
52
|
+
|
53
|
+
def remote_action(branch, url, action)
|
54
|
+
status = exec(remote_cmd branch, url, action)
|
55
|
+
fail "failed to #{action}" unless status == 0
|
56
|
+
status
|
57
|
+
end
|
58
|
+
|
59
|
+
def remote_from_url(url)
|
60
|
+
return 'origin' if url.nil? || !url
|
61
|
+
url.split(':').last.gsub('/', '_')
|
62
|
+
end
|
63
|
+
|
64
|
+
def fetch_all
|
65
|
+
exec 'git fetch --all'
|
66
|
+
end
|
67
|
+
|
68
|
+
def remotes
|
69
|
+
(`git remote`.split "\n") - ['origin']
|
70
|
+
end
|
71
|
+
|
72
|
+
def index_path
|
73
|
+
::File.join(@repo.path, 'index')
|
74
|
+
end
|
75
|
+
|
76
|
+
def git_installed
|
77
|
+
!`which git`.empty?
|
78
|
+
end
|
79
|
+
|
80
|
+
def reset
|
81
|
+
exec 'git add . && git reset --hard'
|
82
|
+
end
|
83
|
+
|
84
|
+
def clean
|
85
|
+
exec 'git clean -fdx'
|
86
|
+
end
|
87
|
+
|
88
|
+
def exec(cmd)
|
89
|
+
task = Mixlib::ShellOut.new cmd
|
90
|
+
task.run_command
|
91
|
+
task.exitstatus
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
module SingularityDsl
|
4
|
+
# abstraction class for the overall runtime state
|
5
|
+
class Runstate
|
6
|
+
attr_reader :errors, :failures, :error, :failed
|
7
|
+
|
8
|
+
def initialize
|
9
|
+
@error = false
|
10
|
+
@errors = []
|
11
|
+
@failed = false
|
12
|
+
@failures = []
|
13
|
+
end
|
14
|
+
|
15
|
+
def add_failure(fail_msg)
|
16
|
+
@failed = true
|
17
|
+
@failures.push fail_msg
|
18
|
+
end
|
19
|
+
|
20
|
+
def add_error(err_msg)
|
21
|
+
@error = true
|
22
|
+
@errors.push err_msg
|
23
|
+
end
|
24
|
+
|
25
|
+
def exit_code
|
26
|
+
return 1 if @error || @failed
|
27
|
+
0
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
module SingularityDsl
|
4
|
+
# Task abstraction class
|
5
|
+
class Task
|
6
|
+
def initialize(&block)
|
7
|
+
instance_eval(&block) unless block.nil?
|
8
|
+
end
|
9
|
+
|
10
|
+
def validate_file(file)
|
11
|
+
throw "Cannot find #{file}" unless File.exist? file
|
12
|
+
end
|
13
|
+
|
14
|
+
def execute
|
15
|
+
fail 'SingularityDsl::Task::execute not implemented'
|
16
|
+
end
|
17
|
+
|
18
|
+
def failed_status(status)
|
19
|
+
![nil, 0, false].include? status
|
20
|
+
end
|
21
|
+
|
22
|
+
def description
|
23
|
+
"Runs #{self.class} task"
|
24
|
+
end
|
25
|
+
|
26
|
+
def task_name
|
27
|
+
false
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'rake'
|
4
|
+
|
5
|
+
# Rake Task
|
6
|
+
class Rake < Task
|
7
|
+
attr_accessor :target, :rake
|
8
|
+
|
9
|
+
def initialize(&block)
|
10
|
+
::Rake.application.init
|
11
|
+
@rake = ::Rake.application
|
12
|
+
super(&block)
|
13
|
+
end
|
14
|
+
|
15
|
+
def target(target)
|
16
|
+
@target = target
|
17
|
+
@target.strip!
|
18
|
+
end
|
19
|
+
|
20
|
+
def execute
|
21
|
+
throw 'target is required' if @target.nil?
|
22
|
+
@rake.load_rakefile
|
23
|
+
ret = @rake[@target].invoke
|
24
|
+
return ret.count if ret.kind_of? Array
|
25
|
+
ret
|
26
|
+
end
|
27
|
+
|
28
|
+
def description
|
29
|
+
'Simple resource to just wrap the Rake CLI'
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'rspec'
|
4
|
+
|
5
|
+
# RSpec Task
|
6
|
+
class RSpec < Task
|
7
|
+
attr_accessor :spec_dir, :config_file
|
8
|
+
|
9
|
+
def initialize(&block)
|
10
|
+
@spec_dir ||= './spec'
|
11
|
+
@config_file ||= './.rspec'
|
12
|
+
super(&block)
|
13
|
+
end
|
14
|
+
|
15
|
+
def config_file(file)
|
16
|
+
validate_file file
|
17
|
+
@config_file = file
|
18
|
+
end
|
19
|
+
|
20
|
+
def spec_dir(dir)
|
21
|
+
validate_file dir
|
22
|
+
@spec_dir = dir
|
23
|
+
end
|
24
|
+
|
25
|
+
def execute
|
26
|
+
::RSpec::Core::Runner.run([@spec_dir])
|
27
|
+
end
|
28
|
+
|
29
|
+
def description
|
30
|
+
'Run RSpec tests. Uses RSpec::Core'
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'rubocop'
|
4
|
+
|
5
|
+
# Rubocop task
|
6
|
+
# Intentionally NOT a rake task - for some reason the syck YAML parser
|
7
|
+
# that Rubocop uses internally freaks out when a
|
8
|
+
# ::Rake::Application[:task].invoke is called from a task
|
9
|
+
class Rubocop < Task
|
10
|
+
# :files => specific files to run against
|
11
|
+
# :cfg_file => separate config file
|
12
|
+
def initialize(&block)
|
13
|
+
@default_config = './.rubocop.yml'
|
14
|
+
@files = []
|
15
|
+
@cfg_files = [@default_config]
|
16
|
+
@cfg_store = ::RuboCop::ConfigStore.new
|
17
|
+
super(&block)
|
18
|
+
end
|
19
|
+
|
20
|
+
def config_file(file)
|
21
|
+
validate_file file
|
22
|
+
|
23
|
+
return if @cfg_files.include? file
|
24
|
+
warn 'Loading multiple configs' if File.exist? @default_config
|
25
|
+
|
26
|
+
@cfg_files.push file
|
27
|
+
|
28
|
+
# this does a merge of options...
|
29
|
+
@cfg_store.options_config = file
|
30
|
+
end
|
31
|
+
|
32
|
+
def file(file)
|
33
|
+
validate_file file
|
34
|
+
@files.push file
|
35
|
+
end
|
36
|
+
|
37
|
+
def execute
|
38
|
+
inspector = ::RuboCop::FileInspector.new({})
|
39
|
+
# yes, have to pass in a block
|
40
|
+
inspector.process_files files, @cfg_store do
|
41
|
+
false
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def description
|
46
|
+
'Runs rubocop, loads .rubocop.yml from ./'
|
47
|
+
end
|
48
|
+
|
49
|
+
private
|
50
|
+
|
51
|
+
def files
|
52
|
+
::RuboCop::TargetFinder.new(@cfg_store).find @files
|
53
|
+
end
|
54
|
+
end
|
@@ -0,0 +1,90 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'mixlib/shellout'
|
4
|
+
require 'singularity_dsl/stdout'
|
5
|
+
|
6
|
+
# shell-out resource for any ol commands
|
7
|
+
class ShellTask < SingularityDsl::Task
|
8
|
+
include SingularityDsl::Stdout
|
9
|
+
|
10
|
+
attr_reader :shell, :conditionals, :alternative, :no_fail
|
11
|
+
attr_writer :live_stream
|
12
|
+
|
13
|
+
def initialize(&block)
|
14
|
+
@live_stream = STDOUT
|
15
|
+
@conditionals = []
|
16
|
+
@no_fail = false
|
17
|
+
@alternative = 'echo "no alternative shell cmd defined"'
|
18
|
+
super(&block)
|
19
|
+
end
|
20
|
+
|
21
|
+
def condition(cmd)
|
22
|
+
invalid_cmd 'condition' unless cmd.is_a? String
|
23
|
+
@conditionals.push cmd
|
24
|
+
end
|
25
|
+
|
26
|
+
def no_fail(switch)
|
27
|
+
fail 'no_fail must be bool' unless bool? switch
|
28
|
+
@no_fail = switch
|
29
|
+
end
|
30
|
+
|
31
|
+
def alt(cmd)
|
32
|
+
invalid_cmd 'alt' unless cmd.is_a? String
|
33
|
+
@alternative = cmd
|
34
|
+
end
|
35
|
+
|
36
|
+
def command(cmd)
|
37
|
+
@task_name = cmd
|
38
|
+
@shell = setup_shell cmd
|
39
|
+
end
|
40
|
+
|
41
|
+
def task_name
|
42
|
+
return @task_name if @task_name
|
43
|
+
super
|
44
|
+
end
|
45
|
+
|
46
|
+
def execute
|
47
|
+
throw 'command never defined' if @shell.nil?
|
48
|
+
command @alternative unless evaluate_conditionals
|
49
|
+
@live_stream << log_shell if @live_stream
|
50
|
+
@shell.run_command
|
51
|
+
return 0 if @no_fail
|
52
|
+
@shell.exitstatus
|
53
|
+
end
|
54
|
+
|
55
|
+
def description
|
56
|
+
'Runs a SH command using Mixlib::ShellOut'
|
57
|
+
end
|
58
|
+
|
59
|
+
private
|
60
|
+
|
61
|
+
def log_shell(pre = '', shell = false)
|
62
|
+
shell ||= @shell
|
63
|
+
pre ||= ''
|
64
|
+
log = "[ShellTask]:#{pre}:#{shell.command}"
|
65
|
+
data(log)
|
66
|
+
end
|
67
|
+
|
68
|
+
def bool?(val)
|
69
|
+
val.is_a?(TrueClass) || val.is_a?(FalseClass)
|
70
|
+
end
|
71
|
+
|
72
|
+
def setup_shell(cmd)
|
73
|
+
shell = ::Mixlib::ShellOut.new cmd
|
74
|
+
shell.live_stream = @live_stream if @live_stream
|
75
|
+
shell
|
76
|
+
end
|
77
|
+
|
78
|
+
def invalid_cmd(type)
|
79
|
+
throw "#{type} must be string"
|
80
|
+
end
|
81
|
+
|
82
|
+
def evaluate_conditionals
|
83
|
+
@conditionals.all? do |cmd|
|
84
|
+
shell = setup_shell cmd
|
85
|
+
log_shell '[conditional]', shell
|
86
|
+
shell.run_command
|
87
|
+
!failed_status(shell.exitstatus)
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'singularity_dsl/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = 'singularity_dsl'
|
8
|
+
spec.version = SingularityDsl::VERSION
|
9
|
+
spec.authors = ['chr0n1x']
|
10
|
+
spec.email = ['heilong24@gmail.com']
|
11
|
+
spec.description = %q{DSL for your SingularityCI instance.}
|
12
|
+
spec.summary = %q{}
|
13
|
+
spec.homepage = ''
|
14
|
+
spec.license = 'MIT'
|
15
|
+
|
16
|
+
spec.files = `git ls-files`.split($/)
|
17
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
|
+
spec.require_paths = ['lib']
|
20
|
+
|
21
|
+
spec.add_dependency 'mixlib-shellout', '~> 1.4'
|
22
|
+
spec.add_dependency 'rainbow', '~> 2.0.0'
|
23
|
+
spec.add_dependency 'rake', '~> 10.3'
|
24
|
+
spec.add_dependency 'rspec', '~> 2.6'
|
25
|
+
spec.add_dependency 'rubocop', '~> 0.23.0'
|
26
|
+
spec.add_dependency 'terminal-table', '~> 1.4'
|
27
|
+
spec.add_dependency 'thor', '~> 0.19'
|
28
|
+
|
29
|
+
spec.add_development_dependency 'bundler', '~> 1.3'
|
30
|
+
spec.add_development_dependency 'gem-release'
|
31
|
+
end
|
@@ -0,0 +1,92 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'singularity_dsl/application'
|
4
|
+
|
5
|
+
describe 'Application' do
|
6
|
+
let(:app) { SingularityDsl::Application.new }
|
7
|
+
|
8
|
+
context '#initialize' do
|
9
|
+
it 'creates base runner' do
|
10
|
+
expect(app.runner).to be_kind_of SingularityDsl::Dsl::Runner
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
context '#load_script' do
|
15
|
+
it 'just calls runner.load_ex_script' do
|
16
|
+
stub_res = 'spooooooky ghooooost'
|
17
|
+
expect(app.runner).to(receive(:load_ex_script).and_return stub_res)
|
18
|
+
expect(app.load_script 'dummy').to eql stub_res
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
context '#run' do
|
23
|
+
it 'logs resource failures' do
|
24
|
+
# don't want the entire thing to exit...
|
25
|
+
app.stub(:post_task_runner_actions)
|
26
|
+
app.runner.stub(:execute).and_raise(SingularityDsl::Errors::ResourceFail)
|
27
|
+
expect(app).to receive(:log_resource_fail)
|
28
|
+
app.run
|
29
|
+
end
|
30
|
+
|
31
|
+
it 'runner post-script actions are evaulated on failure' do
|
32
|
+
app.stub(:post_task_runner_actions)
|
33
|
+
app.stub(:log_resource_fail)
|
34
|
+
app.runner.stub(:execute).and_raise(SingularityDsl::Errors::ResourceFail)
|
35
|
+
expect(app).to receive(:post_task_runner_actions)
|
36
|
+
app.run
|
37
|
+
end
|
38
|
+
|
39
|
+
it 'logs resource errors' do
|
40
|
+
app.stub(:post_task_runner_actions)
|
41
|
+
app.runner.stub(:execute).and_raise(SingularityDsl::Errors::ResourceError)
|
42
|
+
expect(app).to receive(:log_resource_error)
|
43
|
+
app.run
|
44
|
+
end
|
45
|
+
|
46
|
+
it 'runner post-script actions are evaulated on error' do
|
47
|
+
app.stub(:post_task_runner_actions)
|
48
|
+
app.stub(:log_resource_error)
|
49
|
+
app.runner.stub(:execute).and_raise(SingularityDsl::Errors::ResourceError)
|
50
|
+
expect(app).to receive(:post_task_runner_actions)
|
51
|
+
app.run
|
52
|
+
end
|
53
|
+
|
54
|
+
it 'runner post-script actions are evaulated on error' do
|
55
|
+
app.stub(:post_task_runner_actions)
|
56
|
+
app.stub(:execute)
|
57
|
+
expect(app.runner.state).to receive :exit_code
|
58
|
+
app.run
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
context '#post_task_runner_actions' do
|
63
|
+
it 'outputs warning when script fails' do
|
64
|
+
app.stub :script_warn
|
65
|
+
app.runner.stub :post_actions
|
66
|
+
app.stub :exit_run
|
67
|
+
app.runner.state.stub(:failed).and_return true
|
68
|
+
expect(app).to receive(:script_warn)
|
69
|
+
app.post_task_runner_actions
|
70
|
+
end
|
71
|
+
|
72
|
+
it 'outputs warning when script errors' do
|
73
|
+
app.stub :script_error
|
74
|
+
app.runner.stub :post_actions
|
75
|
+
app.stub :exit_run
|
76
|
+
app.runner.state.stub(:error).and_return true
|
77
|
+
expect(app).to receive(:script_error)
|
78
|
+
app.post_task_runner_actions
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
context '#change_list' do
|
83
|
+
it 'returns a sorted list' do
|
84
|
+
expect(app.change_list(%w(b c e a d)))
|
85
|
+
.to eql %w(a b c d e)
|
86
|
+
end
|
87
|
+
|
88
|
+
it 'handles empty lists' do
|
89
|
+
expect(app.change_list([])).to eql []
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|