mamiya 0.0.1.alpha21 → 0.0.1.alpha22
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/example/.gitignore +5 -0
- data/example/Procfile +1 -1
- data/example/README.md +83 -0
- data/example/config.agent.rb +40 -0
- data/example/config.rb +20 -6
- data/example/deploy.rb +27 -11
- data/example/source/README.md +1 -0
- data/lib/mamiya/agent/actions.rb +8 -3
- data/lib/mamiya/agent/task_queue.rb +9 -0
- data/lib/mamiya/agent/tasks/abstract.rb +13 -0
- data/lib/mamiya/agent/tasks/clean.rb +36 -4
- data/lib/mamiya/agent/tasks/fetch.rb +1 -0
- data/lib/mamiya/agent/tasks/notifyable.rb +0 -1
- data/lib/mamiya/agent/tasks/prepare.rb +103 -0
- data/lib/mamiya/agent.rb +46 -12
- data/lib/mamiya/cli/client.rb +35 -7
- data/lib/mamiya/cli.rb +44 -5
- data/lib/mamiya/configuration.rb +12 -0
- data/lib/mamiya/dsl.rb +6 -2
- data/lib/mamiya/helpers/git.rb +24 -0
- data/lib/mamiya/master/agent_monitor.rb +22 -2
- data/lib/mamiya/master/agent_monitor_handlers.rb +17 -0
- data/lib/mamiya/master/web.rb +42 -3
- data/lib/mamiya/master.rb +4 -0
- data/lib/mamiya/script.rb +28 -8
- data/lib/mamiya/steps/abstract.rb +1 -0
- data/lib/mamiya/steps/build.rb +107 -19
- data/lib/mamiya/steps/extract.rb +1 -0
- data/lib/mamiya/steps/prepare.rb +60 -0
- data/lib/mamiya/steps/switch.rb +76 -0
- data/lib/mamiya/storages/filesystem.rb +92 -0
- data/lib/mamiya/storages/mock.rb +1 -0
- data/lib/mamiya/util/label_matcher.rb +7 -3
- data/lib/mamiya/version.rb +1 -1
- data/mamiya.gemspec +1 -1
- data/spec/agent/actions_spec.rb +25 -0
- data/spec/agent/task_queue_spec.rb +42 -6
- data/spec/agent/tasks/abstract_spec.rb +35 -0
- data/spec/agent/tasks/clean_spec.rb +94 -45
- data/spec/agent/tasks/fetch_spec.rb +1 -0
- data/spec/agent/tasks/prepare_spec.rb +127 -0
- data/spec/agent_spec.rb +75 -27
- data/spec/dsl_spec.rb +6 -8
- data/spec/master/agent_monitor_spec.rb +142 -4
- data/spec/master/web_spec.rb +43 -1
- data/spec/steps/build_spec.rb +101 -0
- data/spec/steps/prepare_spec.rb +125 -0
- data/spec/steps/switch_spec.rb +146 -0
- data/spec/storages/filesystem_spec.rb +305 -0
- data/spec/util/label_matcher_spec.rb +32 -0
- metadata +20 -6
- data/config.example.yml +0 -11
- data/example.rb +0 -74
data/lib/mamiya/steps/build.rb
CHANGED
@@ -1,24 +1,73 @@
|
|
1
1
|
require 'mamiya/steps/abstract'
|
2
2
|
require 'mamiya/package'
|
3
3
|
|
4
|
+
require 'fileutils'
|
5
|
+
|
4
6
|
module Mamiya
|
5
7
|
module Steps
|
6
8
|
class Build < Abstract
|
9
|
+
class ScriptFileNotSpecified < Exception; end
|
10
|
+
class ApplicationNotSpecified < Exception; end
|
11
|
+
|
7
12
|
def run!
|
8
13
|
@exception = nil
|
9
14
|
|
15
|
+
unless script_file
|
16
|
+
raise ScriptFileNotSpecified, "Set script files to :script_file"
|
17
|
+
end
|
18
|
+
|
19
|
+
unless script.application
|
20
|
+
raise ApplicationNotSpecified, ":application should be specified in your script file"
|
21
|
+
end
|
22
|
+
|
10
23
|
logger.info "Initiating package build"
|
11
24
|
|
25
|
+
run_before_build
|
26
|
+
run_prepare_build
|
27
|
+
run_build
|
28
|
+
|
29
|
+
# XXX: Is this really suitable here? Package class should do?
|
30
|
+
copy_deploy_scripts
|
31
|
+
|
32
|
+
set_metadata
|
33
|
+
|
34
|
+
build_package
|
35
|
+
|
36
|
+
logger.info "Packed."
|
37
|
+
|
38
|
+
rescue Exception => e
|
39
|
+
@exception = e
|
40
|
+
raise
|
41
|
+
ensure
|
42
|
+
logger.warn "Exception occured, cleaning up..." if @exception
|
43
|
+
|
44
|
+
if script_dest.exist?
|
45
|
+
FileUtils.remove_entry_secure script_dest
|
46
|
+
end
|
47
|
+
|
48
|
+
logger.info "Running script.after_build"
|
49
|
+
script.after_build[@exception]
|
50
|
+
|
51
|
+
logger.info "DONE!" unless @exception
|
52
|
+
end
|
53
|
+
|
54
|
+
private
|
55
|
+
|
56
|
+
def run_before_build
|
12
57
|
logger.info "Running script.before_build"
|
13
58
|
script.before_build[]
|
59
|
+
end
|
14
60
|
|
61
|
+
def run_prepare_build
|
15
62
|
unless script.skip_prepare_build
|
16
63
|
logger.info "Running script.prepare_build"
|
17
64
|
script.prepare_build[File.exists?(script.build_from)]
|
18
65
|
else
|
19
66
|
logger.debug "prepare_build skipped due to script.skip_prepare_build"
|
20
67
|
end
|
68
|
+
end
|
21
69
|
|
70
|
+
def run_build
|
22
71
|
old_pwd = Dir.pwd
|
23
72
|
begin
|
24
73
|
# Using without block because chdir in block shows warning
|
@@ -29,24 +78,42 @@ module Mamiya
|
|
29
78
|
ensure
|
30
79
|
Dir.chdir old_pwd
|
31
80
|
end
|
81
|
+
end
|
32
82
|
|
83
|
+
def copy_deploy_scripts
|
84
|
+
# XXX: TODO: move to another class?
|
85
|
+
logger.info "Copying script files..."
|
33
86
|
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
}
|
40
|
-
logger.info "Package name determined: #{package_name}"
|
87
|
+
if script_dest.exist?
|
88
|
+
logger.warn "Removing existing .mamiya.script"
|
89
|
+
FileUtils.remove_entry_secure script_dest
|
90
|
+
end
|
91
|
+
script_dest.mkdir
|
41
92
|
|
42
|
-
|
43
|
-
|
44
|
-
|
93
|
+
logger.info "- #{script_file} -> #{script_dest}"
|
94
|
+
FileUtils.cp script_file, script_dest
|
95
|
+
|
96
|
+
if script.script_additionals
|
97
|
+
script_dir = Pathname.new(File.dirname(script_file))
|
98
|
+
script.script_additionals.each do |additional|
|
99
|
+
src = script_dir.join(additional)
|
100
|
+
dst = script_dest.join(additional)
|
101
|
+
logger.info "- #{src} -> #{dst}"
|
102
|
+
FileUtils.mkdir_p dst.dirname
|
103
|
+
FileUtils.cp_r src, dst
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
45
107
|
|
108
|
+
def set_metadata
|
109
|
+
package.meta[:application] = script.application
|
110
|
+
package.meta[:script] = File.basename(script_file)
|
46
111
|
Dir.chdir(script.build_from) do
|
47
112
|
package.meta.replace script.package_meta[package.meta]
|
48
113
|
end
|
114
|
+
end
|
49
115
|
|
116
|
+
def build_package
|
50
117
|
logger.info "Packaging to: #{package.path}"
|
51
118
|
logger.debug "meta=#{package.meta.inspect}"
|
52
119
|
package.build!(script.build_from,
|
@@ -54,18 +121,39 @@ module Mamiya
|
|
54
121
|
dereference_symlinks: script.dereference_symlinks || false,
|
55
122
|
package_under: script.package_under || nil,
|
56
123
|
logger: logger)
|
57
|
-
|
124
|
+
end
|
58
125
|
|
59
|
-
|
60
|
-
@
|
61
|
-
|
62
|
-
|
63
|
-
|
126
|
+
def package_name
|
127
|
+
@package_name ||= begin
|
128
|
+
logger.debug "Determining package name..."
|
129
|
+
name = Dir.chdir(script.build_from) {
|
130
|
+
script.package_name[
|
131
|
+
[Time.now.strftime("%Y-%m-%d_%H.%M.%S"), script.application]
|
132
|
+
].join('-')
|
133
|
+
}
|
134
|
+
logger.info "Package name determined: #{name}"
|
135
|
+
name
|
136
|
+
end
|
137
|
+
end
|
64
138
|
|
65
|
-
|
66
|
-
script.
|
139
|
+
def package_path
|
140
|
+
@package_path ||= File.join(script.build_to, package_name)
|
141
|
+
end
|
67
142
|
|
68
|
-
|
143
|
+
def package
|
144
|
+
@package ||= Mamiya::Package.new(package_path)
|
145
|
+
end
|
146
|
+
|
147
|
+
def script_file
|
148
|
+
@script_file ||= script.script_file || script._file
|
149
|
+
end
|
150
|
+
|
151
|
+
def script_dest
|
152
|
+
@script_dest ||= if script.package_under
|
153
|
+
Pathname.new File.join(script.build_from, script.package_under, '.mamiya.script')
|
154
|
+
else
|
155
|
+
Pathname.new File.join(script.build_from, '.mamiya.script')
|
156
|
+
end
|
69
157
|
end
|
70
158
|
end
|
71
159
|
end
|
data/lib/mamiya/steps/extract.rb
CHANGED
@@ -4,6 +4,7 @@ require 'mamiya/steps/abstract'
|
|
4
4
|
module Mamiya
|
5
5
|
module Steps
|
6
6
|
class Extract < Abstract
|
7
|
+
# XXX: extract step is really needed? doing this in prepare step for consistency with agent/tasks/prepare, is better, I guess.
|
7
8
|
def run!
|
8
9
|
package = case options[:package]
|
9
10
|
when Mamiya::Package
|
@@ -0,0 +1,60 @@
|
|
1
|
+
require 'mamiya/steps/abstract'
|
2
|
+
|
3
|
+
require 'pathname'
|
4
|
+
require 'json'
|
5
|
+
|
6
|
+
module Mamiya
|
7
|
+
module Steps
|
8
|
+
class Prepare < Abstract
|
9
|
+
def run!
|
10
|
+
@exception = nil
|
11
|
+
old_pwd = Dir.pwd
|
12
|
+
Dir.chdir(target)
|
13
|
+
|
14
|
+
logger.info "Preparing #{target}..."
|
15
|
+
|
16
|
+
script.before_prepare(labels)[]
|
17
|
+
script.prepare(labels)[]
|
18
|
+
|
19
|
+
File.write target.join('.mamiya.prepared'), "#{Time.now.to_i}\n"
|
20
|
+
rescue Exception => e
|
21
|
+
@exception = e
|
22
|
+
raise e
|
23
|
+
ensure
|
24
|
+
Dir.chdir old_pwd if old_pwd
|
25
|
+
logger.warn "Exception occured, cleaning up..." if @exception
|
26
|
+
|
27
|
+
script.after_prepare(labels)[@exception]
|
28
|
+
|
29
|
+
logger.info "DONE!" unless @exception
|
30
|
+
end
|
31
|
+
|
32
|
+
# This class see target_dir's script
|
33
|
+
alias given_script script
|
34
|
+
|
35
|
+
def script
|
36
|
+
@target_script ||= Mamiya::Script.new.load!(
|
37
|
+
target.join('.mamiya.script', target_meta['script'])).tap do |script|
|
38
|
+
# XXX: release_path is set by options[:target] but deploy_to is set by script?
|
39
|
+
script.set(:release_path, target)
|
40
|
+
script.set(:logger, logger)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
private
|
45
|
+
|
46
|
+
def target
|
47
|
+
@target ||= Pathname.new(options[:target]).realpath
|
48
|
+
end
|
49
|
+
|
50
|
+
def target_meta
|
51
|
+
@target_meta ||= JSON.parse target.join('.mamiya.meta.json').read
|
52
|
+
end
|
53
|
+
|
54
|
+
def labels
|
55
|
+
# XXX: TODO: is it sure that passing labels via options of step?
|
56
|
+
options[:labels]
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
@@ -0,0 +1,76 @@
|
|
1
|
+
require 'mamiya/steps/abstract'
|
2
|
+
|
3
|
+
module Mamiya
|
4
|
+
module Steps
|
5
|
+
class Switch < Abstract
|
6
|
+
def run!
|
7
|
+
@exception = nil
|
8
|
+
logger.info "Switching to #{target}"
|
9
|
+
|
10
|
+
script.before_switch(labels)[]
|
11
|
+
|
12
|
+
# TODO: link with relative if available?
|
13
|
+
File.unlink script.current_path if script.current_path.symlink?
|
14
|
+
script.current_path.make_symlink(target.realpath)
|
15
|
+
|
16
|
+
if do_release?
|
17
|
+
begin
|
18
|
+
old_pwd = Dir.pwd
|
19
|
+
Dir.chdir(target)
|
20
|
+
|
21
|
+
logger.info "Releasing..."
|
22
|
+
|
23
|
+
script.release(labels)[@exception]
|
24
|
+
ensure
|
25
|
+
Dir.chdir old_pwd if old_pwd
|
26
|
+
end
|
27
|
+
else
|
28
|
+
logger.warn "Skipping release (:no_release is set)"
|
29
|
+
end
|
30
|
+
|
31
|
+
rescue Exception => e
|
32
|
+
@exception = e
|
33
|
+
raise e
|
34
|
+
ensure
|
35
|
+
logger.warn "Exception occured, cleaning up..." if @exception
|
36
|
+
|
37
|
+
script.after_switch(labels)[@exception]
|
38
|
+
|
39
|
+
logger.info "DONE!" unless @exception
|
40
|
+
end
|
41
|
+
|
42
|
+
# XXX: dupe with prepare step. modulize?
|
43
|
+
|
44
|
+
# This class see target_dir's script
|
45
|
+
alias given_script script
|
46
|
+
|
47
|
+
def script
|
48
|
+
@target_script ||= Mamiya::Script.new.load!(
|
49
|
+
target.join('.mamiya.script', target_meta['script'])).tap do |script|
|
50
|
+
# XXX: release_path is set by options[:target] but deploy_to is set by script?
|
51
|
+
script.set(:release_path, target)
|
52
|
+
script.set(:logger, logger)
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
private
|
57
|
+
|
58
|
+
def do_release?
|
59
|
+
!options[:no_release]
|
60
|
+
end
|
61
|
+
|
62
|
+
def target
|
63
|
+
@target ||= Pathname.new(options[:target]).realpath
|
64
|
+
end
|
65
|
+
|
66
|
+
def target_meta
|
67
|
+
@target_meta ||= JSON.parse target.join('.mamiya.meta.json').read
|
68
|
+
end
|
69
|
+
|
70
|
+
def labels
|
71
|
+
# XXX: TODO: is it sure that passing labels via options of step?
|
72
|
+
options[:labels]
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
@@ -0,0 +1,92 @@
|
|
1
|
+
require 'mamiya/package'
|
2
|
+
require 'mamiya/storages/abstract'
|
3
|
+
require 'fileutils'
|
4
|
+
|
5
|
+
module Mamiya
|
6
|
+
module Storages
|
7
|
+
class Filesystem < Mamiya::Storages::Abstract
|
8
|
+
def self.find(config={})
|
9
|
+
Hash[Dir[File.join(config[:path], '*')].map do |app_path|
|
10
|
+
app = File.basename(app_path)
|
11
|
+
[app, self.new(config.merge(application: app))]
|
12
|
+
end]
|
13
|
+
end
|
14
|
+
|
15
|
+
def packages
|
16
|
+
storage_path.children(false).group_by { |child|
|
17
|
+
child.to_s.sub(Package::PATH_SUFFIXES,'')
|
18
|
+
}.select { |key, files|
|
19
|
+
files.find { |file| file.to_s.end_with?('.tar.gz') } &&
|
20
|
+
files.find { |file| file.to_s.end_with?('.json') }
|
21
|
+
}.keys.sort
|
22
|
+
end
|
23
|
+
|
24
|
+
def push(package)
|
25
|
+
raise TypeError, "package should be a kind of Mamiya::Package" unless package.kind_of?(Mamiya::Package)
|
26
|
+
raise NotBuilt, "package not built" unless package.exists?
|
27
|
+
|
28
|
+
if package_exist?(package.name)
|
29
|
+
raise AlreadyExists
|
30
|
+
end
|
31
|
+
|
32
|
+
storage_path.mkpath
|
33
|
+
|
34
|
+
FileUtils.cp package.path, storage_path.join("#{package.name}.tar.gz")
|
35
|
+
FileUtils.cp package.meta_path, storage_path.join("#{package.name}.json")
|
36
|
+
end
|
37
|
+
|
38
|
+
def fetch(package_name, destination)
|
39
|
+
package_name = normalize_package_name(package_name)
|
40
|
+
raise NotFound unless package_exist?(package_name)
|
41
|
+
|
42
|
+
package_path = File.join(destination, "#{package_name}.tar.gz")
|
43
|
+
meta_path = File.join(destination, "#{package_name}.json")
|
44
|
+
|
45
|
+
if File.exists?(package_path) || File.exists?(meta_path)
|
46
|
+
raise AlreadyFetched
|
47
|
+
end
|
48
|
+
|
49
|
+
FileUtils.cp storage_path.join("#{package_name}.tar.gz"), package_path
|
50
|
+
FileUtils.cp storage_path.join("#{package_name}.json"), meta_path
|
51
|
+
|
52
|
+
return Mamiya::Package.new(package_path)
|
53
|
+
end
|
54
|
+
|
55
|
+
def meta(package_name)
|
56
|
+
package_name = normalize_package_name(package_name)
|
57
|
+
return unless package_exist?(package_name)
|
58
|
+
|
59
|
+
JSON.parse storage_path.join("#{package_name}.json").read
|
60
|
+
end
|
61
|
+
|
62
|
+
def remove(package_name)
|
63
|
+
package_name = normalize_package_name(package_name)
|
64
|
+
|
65
|
+
package_path = storage_path.join("#{package_name}.tar.gz")
|
66
|
+
meta_path = storage_path.join("#{package_name}.json")
|
67
|
+
|
68
|
+
if [package_path, meta_path].all? { |_| !_.exist? }
|
69
|
+
raise Mamiya::Storages::Abstract::NotFound
|
70
|
+
end
|
71
|
+
|
72
|
+
package_path.delete if package_path.exist?
|
73
|
+
meta_path.delete if meta_path.exist?
|
74
|
+
end
|
75
|
+
|
76
|
+
private
|
77
|
+
|
78
|
+
def storage_path
|
79
|
+
@storage_path ||= Pathname.new(@config[:path]).join(@config[:application])
|
80
|
+
end
|
81
|
+
|
82
|
+
def package_exist?(name)
|
83
|
+
storage_path.join("#{name}.tar.gz").exist? &&
|
84
|
+
storage_path.join("#{name}.json").exist?
|
85
|
+
end
|
86
|
+
|
87
|
+
def normalize_package_name(name)
|
88
|
+
name.sub(/\.(?:tar\.gz|json)\z/, '')
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
data/lib/mamiya/storages/mock.rb
CHANGED
@@ -1,8 +1,12 @@
|
|
1
1
|
module Mamiya
|
2
2
|
module Util
|
3
3
|
module LabelMatcher
|
4
|
+
def self.parse_string_expr(str)
|
5
|
+
str.split(/\|/).map{ |_| _.split(/,/) }
|
6
|
+
end
|
7
|
+
|
4
8
|
def match?(*expressions)
|
5
|
-
labels = self.labels()
|
9
|
+
labels = self.labels().map(&:to_s)
|
6
10
|
|
7
11
|
if expressions.all? { |_| _.kind_of?(Symbol) || _.kind_of?(String) }
|
8
12
|
return self.match?(expressions)
|
@@ -11,12 +15,12 @@ module Mamiya
|
|
11
15
|
expressions.any? do |expression|
|
12
16
|
case expression
|
13
17
|
when Symbol, String
|
14
|
-
labels.include?(expression)
|
18
|
+
labels.include?(expression.to_s)
|
15
19
|
when Array
|
16
20
|
if expression.any? { |_| _.kind_of?(Array) }
|
17
21
|
self.match?(*expression)
|
18
22
|
else
|
19
|
-
expression.all? { |_| labels.include?(_) }
|
23
|
+
expression.all? { |_| labels.include?(_.to_s) }
|
20
24
|
end
|
21
25
|
end
|
22
26
|
end
|
data/lib/mamiya/version.rb
CHANGED
data/mamiya.gemspec
CHANGED
@@ -22,7 +22,7 @@ Gem::Specification.new do |spec|
|
|
22
22
|
spec.add_runtime_dependency "aws-sdk-core", "2.0.0.rc15"
|
23
23
|
spec.add_runtime_dependency "term-ansicolor", ">= 1.3.0"
|
24
24
|
unless ENV["MAMIYA_VILLEIN_PATH"]
|
25
|
-
spec.add_runtime_dependency "villein", ">= 0.
|
25
|
+
spec.add_runtime_dependency "villein", ">= 0.5.0"
|
26
26
|
end
|
27
27
|
|
28
28
|
spec.add_runtime_dependency "sinatra", ">= 1.4.5"
|
data/spec/agent/actions_spec.rb
CHANGED
@@ -28,5 +28,30 @@ describe Mamiya::Agent::Actions do
|
|
28
28
|
|
29
29
|
agent.distribute('myapp', 'mypkg')
|
30
30
|
end
|
31
|
+
|
32
|
+
context "with labels" do
|
33
|
+
it "adds _labels on task" do
|
34
|
+
expect(agent).to receive(:trigger).with('task', task: 'fetch', app: 'myapp', pkg: 'mypkg', _labels: ['foo'], coalesce: false)
|
35
|
+
|
36
|
+
agent.distribute('myapp', 'mypkg', labels: ['foo'])
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|
41
|
+
|
42
|
+
describe "#prepare" do
|
43
|
+
it "sends prepare request" do
|
44
|
+
expect(agent).to receive(:trigger).with('task', task: 'prepare', app: 'myapp', pkg: 'mypkg', coalesce: false)
|
45
|
+
|
46
|
+
agent.prepare('myapp', 'mypkg')
|
47
|
+
end
|
48
|
+
|
49
|
+
context "with labels" do
|
50
|
+
it "adds _labels on task" do
|
51
|
+
expect(agent).to receive(:trigger).with('task', task: 'prepare', app: 'myapp', pkg: 'mypkg', _labels: ['foo'], coalesce: false)
|
52
|
+
|
53
|
+
agent.prepare('myapp', 'mypkg', labels: ['foo'])
|
54
|
+
end
|
55
|
+
end
|
31
56
|
end
|
32
57
|
end
|
@@ -103,6 +103,42 @@ describe Mamiya::Agent::TaskQueue do
|
|
103
103
|
expect(task_class_a.runs[1]['foo']).to eq '2'
|
104
104
|
end
|
105
105
|
|
106
|
+
describe "(task with _labels)" do
|
107
|
+
it "runs on matched agent" do
|
108
|
+
queue.start!
|
109
|
+
expect(agent).to receive(:match?).with(['foo', 'bar']).and_return(true)
|
110
|
+
|
111
|
+
queue.enqueue(:a, 'foo' => '1', '_labels' => ['foo', 'bar'])
|
112
|
+
|
113
|
+
100.times { break if task_class_a.runs.size == 1; sleep 0.01 }
|
114
|
+
expect(task_class_a.runs.size).to eq 1
|
115
|
+
expect(task_class_a.runs[0]['foo']).to eq '1'
|
116
|
+
end
|
117
|
+
|
118
|
+
it "doesn't run on not matched agent" do
|
119
|
+
queue.start!
|
120
|
+
expect(agent).to receive(:match?).with(['foo', 'bar']).and_return(false)
|
121
|
+
|
122
|
+
queue.enqueue(:a, 'foo' => '1', '_labels' => ['foo', 'bar'])
|
123
|
+
queue.enqueue(:a, 'foo' => '2')
|
124
|
+
|
125
|
+
100.times { break if task_class_a.runs.size == 1; sleep 0.01 }
|
126
|
+
expect(task_class_a.runs.size).to eq 1
|
127
|
+
expect(task_class_a.runs[0]['foo']).to eq '2'
|
128
|
+
end
|
129
|
+
|
130
|
+
it "removes _labels from task on run" do
|
131
|
+
queue.start!
|
132
|
+
expect(agent).to receive(:match?).with(['foo', 'bar']).and_return(true)
|
133
|
+
|
134
|
+
queue.enqueue(:a, 'foo' => '1', '_labels' => ['foo', 'bar'])
|
135
|
+
|
136
|
+
100.times { break if task_class_a.runs.size == 1; sleep 0.01 }
|
137
|
+
expect(task_class_a.runs.size).to eq 1
|
138
|
+
expect(task_class_a.runs[0].key?('_labels')).to be_false
|
139
|
+
end
|
140
|
+
end
|
141
|
+
|
106
142
|
describe "#working?" do
|
107
143
|
it "returns true if there're any working tasks" do
|
108
144
|
queue.start!
|
@@ -134,12 +170,12 @@ describe Mamiya::Agent::TaskQueue do
|
|
134
170
|
|
135
171
|
100.times { break unless task_class_a.locks.empty?; sleep 0.01 }
|
136
172
|
expect(task_class_a.locks).not_to be_empty
|
137
|
-
expect(queue.status[:a][:working]).to eq('wait' => true, 'id' => 1)
|
173
|
+
expect(queue.status[:a][:working]).to eq('wait' => true, 'id' => 1, 'task' => :a)
|
138
174
|
|
139
175
|
queue.enqueue(:a, 'id' => 2)
|
140
176
|
100.times { break unless queue.status[:a][:queue].empty?; sleep 0.01 }
|
141
177
|
expect(queue.status[:a][:queue].size).to eq 1
|
142
|
-
expect(queue.status[:a][:queue].first).to eq('id' => 2)
|
178
|
+
expect(queue.status[:a][:queue].first).to eq('id' => 2, 'task' => :a)
|
143
179
|
|
144
180
|
task_class_a.locks.values.last << true
|
145
181
|
|
@@ -200,16 +236,16 @@ describe Mamiya::Agent::TaskQueue do
|
|
200
236
|
expect(task_class_a.locks).not_to be_empty
|
201
237
|
expect(task_class_b.locks).not_to be_empty
|
202
238
|
|
203
|
-
expect(queue.status[:a][:working]).to eq('wait' => true, 'id' => 1)
|
204
|
-
expect(queue.status[:b][:working]).to eq('wait' => true, 'id' => 2)
|
239
|
+
expect(queue.status[:a][:working]).to eq('wait' => true, 'id' => 1, 'task' => :a)
|
240
|
+
expect(queue.status[:b][:working]).to eq('wait' => true, 'id' => 2, 'task' => :b)
|
205
241
|
|
206
242
|
queue.enqueue(:a, 'id' => 3)
|
207
243
|
queue.enqueue(:b, 'id' => 4)
|
208
244
|
100.times { break if !queue.status[:a][:queue].empty? && !queue.status[:b][:queue].empty?; sleep 0.01 }
|
209
245
|
expect(queue.status[:a][:queue].size).to eq 1
|
210
|
-
expect(queue.status[:a][:queue].first).to eq('id' => 3)
|
246
|
+
expect(queue.status[:a][:queue].first).to eq('id' => 3, 'task' => :a)
|
211
247
|
expect(queue.status[:b][:queue].size).to eq 1
|
212
|
-
expect(queue.status[:b][:queue].first).to eq('id' => 4)
|
248
|
+
expect(queue.status[:b][:queue].first).to eq('id' => 4, 'task' => :b)
|
213
249
|
|
214
250
|
task_class_a.locks.values.last << true
|
215
251
|
task_class_b.locks.values.last << true
|
@@ -41,6 +41,41 @@ describe Mamiya::Agent::Tasks::Abstract do
|
|
41
41
|
|
42
42
|
expect(task.error).to eq err
|
43
43
|
end
|
44
|
+
|
45
|
+
context "with _chain" do
|
46
|
+
let(:job) { {'foo' => 'bar', '_chain' => ['another']} }
|
47
|
+
|
48
|
+
it "enqueues next _chain, keeping same task specification" do
|
49
|
+
expect(queue).to receive(:enqueue).with(:another,
|
50
|
+
'foo' => 'bar',
|
51
|
+
)
|
52
|
+
|
53
|
+
task.execute
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
context "with multiple _chain" do
|
58
|
+
let(:job) { {'foo' => 'bar', '_chain' => ['b', 'c']} }
|
59
|
+
|
60
|
+
it "enqueues next _chain, keeping same task specification" do
|
61
|
+
expect(queue).to receive(:enqueue).with(:b,
|
62
|
+
'foo' => 'bar',
|
63
|
+
'_chain' => ['c'],
|
64
|
+
)
|
65
|
+
|
66
|
+
task.execute
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
context "with empty _chain" do
|
71
|
+
let(:job) { {'foo' => 'bar', '_chain' => []} }
|
72
|
+
|
73
|
+
it "doesn't enqueue nothing" do
|
74
|
+
expect(queue).not_to receive(:enqueue)
|
75
|
+
task.execute
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
44
79
|
end
|
45
80
|
|
46
81
|
describe ".identifier" do
|