mamiya 0.0.1.alpha21 → 0.0.1.alpha22
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 +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
|