mamiya 0.0.1.alpha2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +17 -0
- data/.rspec +2 -0
- data/.travis.yml +16 -0
- data/Gemfile +8 -0
- data/LICENSE.txt +22 -0
- data/README.md +43 -0
- data/Rakefile +6 -0
- data/bin/mamiya +17 -0
- data/config.example.yml +11 -0
- data/docs/sequences/deploy.png +0 -0
- data/docs/sequences/deploy.uml +58 -0
- data/example.rb +74 -0
- data/lib/mamiya.rb +5 -0
- data/lib/mamiya/agent.rb +181 -0
- data/lib/mamiya/agent/actions.rb +12 -0
- data/lib/mamiya/agent/fetcher.rb +137 -0
- data/lib/mamiya/agent/handlers/abstract.rb +20 -0
- data/lib/mamiya/agent/handlers/fetch.rb +68 -0
- data/lib/mamiya/cli.rb +322 -0
- data/lib/mamiya/cli/client.rb +172 -0
- data/lib/mamiya/config.rb +57 -0
- data/lib/mamiya/dsl.rb +192 -0
- data/lib/mamiya/helpers/git.rb +75 -0
- data/lib/mamiya/logger.rb +190 -0
- data/lib/mamiya/master.rb +118 -0
- data/lib/mamiya/master/agent_monitor.rb +146 -0
- data/lib/mamiya/master/agent_monitor_handlers.rb +44 -0
- data/lib/mamiya/master/web.rb +148 -0
- data/lib/mamiya/package.rb +122 -0
- data/lib/mamiya/script.rb +117 -0
- data/lib/mamiya/steps/abstract.rb +19 -0
- data/lib/mamiya/steps/build.rb +72 -0
- data/lib/mamiya/steps/extract.rb +26 -0
- data/lib/mamiya/steps/fetch.rb +24 -0
- data/lib/mamiya/steps/push.rb +34 -0
- data/lib/mamiya/storages.rb +17 -0
- data/lib/mamiya/storages/abstract.rb +48 -0
- data/lib/mamiya/storages/mock.rb +61 -0
- data/lib/mamiya/storages/s3.rb +127 -0
- data/lib/mamiya/util/label_matcher.rb +38 -0
- data/lib/mamiya/version.rb +3 -0
- data/mamiya.gemspec +35 -0
- data/misc/logger_test.rb +12 -0
- data/spec/agent/actions_spec.rb +37 -0
- data/spec/agent/fetcher_spec.rb +199 -0
- data/spec/agent/handlers/fetch_spec.rb +121 -0
- data/spec/agent_spec.rb +255 -0
- data/spec/config_spec.rb +50 -0
- data/spec/dsl_spec.rb +291 -0
- data/spec/fixtures/dsl_test_load.rb +1 -0
- data/spec/fixtures/dsl_test_use.rb +1 -0
- data/spec/fixtures/helpers/foo.rb +1 -0
- data/spec/fixtures/test-package-source/.mamiya.meta.json +1 -0
- data/spec/fixtures/test-package-source/greeting +1 -0
- data/spec/fixtures/test-package.tar.gz +0 -0
- data/spec/fixtures/test.yml +4 -0
- data/spec/logger_spec.rb +68 -0
- data/spec/master/agent_monitor_spec.rb +269 -0
- data/spec/master/web_spec.rb +121 -0
- data/spec/master_spec.rb +94 -0
- data/spec/package_spec.rb +394 -0
- data/spec/script_spec.rb +78 -0
- data/spec/spec_helper.rb +38 -0
- data/spec/steps/build_spec.rb +261 -0
- data/spec/steps/extract_spec.rb +68 -0
- data/spec/steps/fetch_spec.rb +96 -0
- data/spec/steps/push_spec.rb +73 -0
- data/spec/storages/abstract_spec.rb +22 -0
- data/spec/storages/s3_spec.rb +342 -0
- data/spec/storages_spec.rb +33 -0
- data/spec/support/dummy_serf.rb +70 -0
- data/spec/util/label_matcher_spec.rb +85 -0
- metadata +272 -0
@@ -0,0 +1,137 @@
|
|
1
|
+
require 'thread'
|
2
|
+
require 'mamiya/steps/fetch'
|
3
|
+
|
4
|
+
require 'mamiya/storages/abstract'
|
5
|
+
|
6
|
+
module Mamiya
|
7
|
+
class Agent
|
8
|
+
##
|
9
|
+
# This class has a queue for fetching packages.
|
10
|
+
class Fetcher
|
11
|
+
GRACEFUL_TIMEOUT = 60
|
12
|
+
|
13
|
+
def initialize(config, logger: Mamiya::Logger.new)
|
14
|
+
@thread = nil
|
15
|
+
@queue = Queue.new
|
16
|
+
|
17
|
+
@config = config
|
18
|
+
@destination = config[:packages_dir]
|
19
|
+
@keep_packages = config[:keep_packages]
|
20
|
+
@current_job = nil
|
21
|
+
|
22
|
+
@logger = logger['fetcher']
|
23
|
+
@working = nil
|
24
|
+
end
|
25
|
+
|
26
|
+
attr_reader :thread
|
27
|
+
attr_reader :current_job
|
28
|
+
attr_writer :cleanup_hook
|
29
|
+
|
30
|
+
def enqueue(app, package, before: nil, &callback)
|
31
|
+
@queue << [app, package, before, callback]
|
32
|
+
end
|
33
|
+
|
34
|
+
def queue_size
|
35
|
+
@queue.size
|
36
|
+
end
|
37
|
+
|
38
|
+
def start!
|
39
|
+
@logger.info 'Starting...'
|
40
|
+
|
41
|
+
@thread = Thread.new(&method(:main_loop))
|
42
|
+
@thread.abort_on_exception = true
|
43
|
+
end
|
44
|
+
|
45
|
+
def stop!(graceful = false)
|
46
|
+
return unless @thread
|
47
|
+
|
48
|
+
if graceful
|
49
|
+
@queue << :suicide
|
50
|
+
@thread.join(GRACEFUL_TIMEOUT)
|
51
|
+
end
|
52
|
+
|
53
|
+
@thread.kill if @thread.alive?
|
54
|
+
ensure
|
55
|
+
@thread = nil
|
56
|
+
end
|
57
|
+
|
58
|
+
def running?
|
59
|
+
@thread && @thread.alive?
|
60
|
+
end
|
61
|
+
|
62
|
+
def working?
|
63
|
+
!!@current_job
|
64
|
+
end
|
65
|
+
|
66
|
+
def cleanup
|
67
|
+
Dir[File.join(@destination, '*')].each do |app|
|
68
|
+
packages = Dir[File.join(app, "*.tar.gz")]
|
69
|
+
packages.sort_by! { |_| [File.mtime(_), _] }
|
70
|
+
packages[0...-@keep_packages].each do |victim|
|
71
|
+
@logger.info "Cleaning up: remove #{victim}"
|
72
|
+
File.unlink(victim) if File.exist?(victim)
|
73
|
+
|
74
|
+
meta_victim = victim.sub(/\.tar\.gz\z/, '.json')
|
75
|
+
if File.exist?(meta_victim)
|
76
|
+
@logger.info "Cleaning up: remove #{meta_victim}"
|
77
|
+
File.unlink(meta_victim)
|
78
|
+
end
|
79
|
+
|
80
|
+
package_name = File.basename(victim, '.tar.gz')
|
81
|
+
if @cleanup_hook
|
82
|
+
@cleanup_hook.call(File.basename(app), package_name)
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
private
|
89
|
+
|
90
|
+
def main_loop
|
91
|
+
while order = @queue.pop
|
92
|
+
break if order == :suicide
|
93
|
+
handle_order(*order)
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
def handle_order(app, package, before_hook = nil, callback = nil)
|
98
|
+
@current_job = [app, package]
|
99
|
+
@logger.info "fetching #{app}:#{package}"
|
100
|
+
# TODO: Limit apps by configuration
|
101
|
+
|
102
|
+
destination = File.join(@destination, app)
|
103
|
+
|
104
|
+
Dir.mkdir(destination) unless File.exist?(destination)
|
105
|
+
|
106
|
+
before_hook.call if before_hook
|
107
|
+
|
108
|
+
# TODO: before run hook for agent.update_tags!
|
109
|
+
Mamiya::Steps::Fetch.new(
|
110
|
+
application: app,
|
111
|
+
package: package,
|
112
|
+
destination: destination,
|
113
|
+
config: @config,
|
114
|
+
).run!
|
115
|
+
|
116
|
+
callback.call if callback
|
117
|
+
|
118
|
+
@logger.info "fetched #{app}:#{package}"
|
119
|
+
|
120
|
+
cleanup
|
121
|
+
|
122
|
+
rescue Mamiya::Storages::Abstract::AlreadyFetched => e
|
123
|
+
@logger.info "skipped #{app}:#{package} (already fetched)"
|
124
|
+
callback.call(e) if callback
|
125
|
+
rescue Exception => e
|
126
|
+
@logger.fatal "fetch failed (#{app}:#{package}): #{e.inspect}"
|
127
|
+
e.backtrace.each do |line|
|
128
|
+
@logger.fatal "\t#{line}"
|
129
|
+
end
|
130
|
+
|
131
|
+
callback.call(e) if callback
|
132
|
+
ensure
|
133
|
+
@current_job = nil
|
134
|
+
end
|
135
|
+
end
|
136
|
+
end
|
137
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
require 'json'
|
2
|
+
|
3
|
+
module Mamiya
|
4
|
+
class Agent
|
5
|
+
module Handlers
|
6
|
+
class Abstract
|
7
|
+
def initialize(agent, event)
|
8
|
+
@agent = agent
|
9
|
+
@event = event
|
10
|
+
@payload = (event.payload && !event.payload.empty?) ? JSON.parse(event.payload) : {}
|
11
|
+
end
|
12
|
+
|
13
|
+
attr_reader :agent, :event, :payload
|
14
|
+
|
15
|
+
def run!
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,68 @@
|
|
1
|
+
require 'mamiya/agent/handlers/abstract'
|
2
|
+
require 'mamiya/storages/abstract'
|
3
|
+
|
4
|
+
module Mamiya
|
5
|
+
class Agent
|
6
|
+
module Handlers
|
7
|
+
class Fetch < Abstract
|
8
|
+
FETCH_ACK_EVENT = 'mamiya:fetch-result:ack'
|
9
|
+
FETCH_START_EVENT = 'mamiya:fetch-result:start'
|
10
|
+
FETCH_SUCCESS_EVENT = 'mamiya:fetch-result:success'
|
11
|
+
FETCH_ERROR_EVENT = 'mamiya:fetch-result:error'
|
12
|
+
|
13
|
+
IGNORED_ERRORS = [
|
14
|
+
Mamiya::Storages::Abstract::AlreadyFetched.new(''),
|
15
|
+
].freeze
|
16
|
+
|
17
|
+
def run!
|
18
|
+
agent.serf.event(FETCH_ACK_EVENT,
|
19
|
+
{
|
20
|
+
name: agent.serf.name,
|
21
|
+
application: payload['application'],
|
22
|
+
package: payload['package'],
|
23
|
+
pending: agent.fetcher.queue_size.succ,
|
24
|
+
}.to_json
|
25
|
+
)
|
26
|
+
|
27
|
+
agent.fetcher.enqueue(
|
28
|
+
payload['application'], payload['package'],
|
29
|
+
before: proc {
|
30
|
+
agent.serf.event(FETCH_START_EVENT,
|
31
|
+
{
|
32
|
+
name: agent.serf.name,
|
33
|
+
application: payload['application'],
|
34
|
+
package: payload['package'],
|
35
|
+
pending: agent.fetcher.queue_size.succ,
|
36
|
+
}.to_json
|
37
|
+
)
|
38
|
+
agent.update_tags!
|
39
|
+
}
|
40
|
+
) do |error|
|
41
|
+
if error && IGNORED_ERRORS.lazy.grep(error.class).none?
|
42
|
+
agent.serf.event(FETCH_ERROR_EVENT,
|
43
|
+
{
|
44
|
+
name: agent.serf.name,
|
45
|
+
application: payload['application'],
|
46
|
+
package: payload['package'],
|
47
|
+
error: error.inspect,
|
48
|
+
pending: agent.fetcher.queue_size,
|
49
|
+
}.to_json
|
50
|
+
)
|
51
|
+
else
|
52
|
+
agent.serf.event(FETCH_SUCCESS_EVENT,
|
53
|
+
{
|
54
|
+
name: agent.serf.name,
|
55
|
+
application: payload['application'],
|
56
|
+
package: payload['package'],
|
57
|
+
pending: agent.fetcher.queue_size,
|
58
|
+
}.to_json
|
59
|
+
)
|
60
|
+
end
|
61
|
+
|
62
|
+
agent.update_tags!
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
data/lib/mamiya/cli.rb
ADDED
@@ -0,0 +1,322 @@
|
|
1
|
+
require 'mamiya'
|
2
|
+
|
3
|
+
require 'mamiya/config'
|
4
|
+
require 'mamiya/script'
|
5
|
+
require 'mamiya/logger'
|
6
|
+
|
7
|
+
require 'mamiya/steps/build'
|
8
|
+
require 'mamiya/steps/push'
|
9
|
+
require 'mamiya/steps/fetch'
|
10
|
+
require 'mamiya/steps/extract'
|
11
|
+
|
12
|
+
require 'mamiya/agent'
|
13
|
+
require 'mamiya/master'
|
14
|
+
|
15
|
+
require 'thor'
|
16
|
+
require 'thread'
|
17
|
+
|
18
|
+
module Mamiya
|
19
|
+
class CLI < Thor
|
20
|
+
class_option :config, aliases: '-C', type: :string
|
21
|
+
class_option :script, aliases: '-S', type: :string
|
22
|
+
class_option :application, aliases: %w(-a --app), type: :string
|
23
|
+
class_option :debug, aliases: %w(-d), type: :boolean
|
24
|
+
class_option :color, type: :boolean
|
25
|
+
class_option :no_color, type: :boolean
|
26
|
+
# TODO: class_option :set, aliases: '-s', type: :array
|
27
|
+
|
28
|
+
no_commands do
|
29
|
+
def invoke_command(*)
|
30
|
+
super
|
31
|
+
rescue SystemExit
|
32
|
+
rescue Exception => e
|
33
|
+
logger.fatal "#{e.class}: #{e.message}"
|
34
|
+
|
35
|
+
e.backtrace.map{ |_| _.prepend("\t") }.each do |line|
|
36
|
+
logger.debug line
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
desc "status", "Show status of servers"
|
42
|
+
def status
|
43
|
+
# TODO:
|
44
|
+
end
|
45
|
+
|
46
|
+
desc "list-packages", "List packages in storage"
|
47
|
+
method_option :name_only, aliases: '-n'
|
48
|
+
def list_packages
|
49
|
+
unless options[:name_only]
|
50
|
+
puts "Available packages in #{application}:"
|
51
|
+
puts ""
|
52
|
+
end
|
53
|
+
|
54
|
+
puts storage.packages.sort
|
55
|
+
end
|
56
|
+
|
57
|
+
desc "list-applications", "List applications in storage"
|
58
|
+
def list_applications
|
59
|
+
puts _applications.keys
|
60
|
+
end
|
61
|
+
|
62
|
+
desc "show PACKAGE", "Show package"
|
63
|
+
method_option :format, aliases: %w(-f), type: :string, default: 'pp'
|
64
|
+
def show(package)
|
65
|
+
meta = storage.meta(package)
|
66
|
+
|
67
|
+
case options[:format]
|
68
|
+
when 'pp'
|
69
|
+
require 'pp'
|
70
|
+
pp meta
|
71
|
+
when 'json'
|
72
|
+
require 'json'
|
73
|
+
puts meta.to_json
|
74
|
+
when 'yaml'
|
75
|
+
require 'yaml'
|
76
|
+
puts meta.to_yaml
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
# ---
|
81
|
+
|
82
|
+
desc "deploy PACKAGE", "Run build->push->distribute->prepare->finalize"
|
83
|
+
def deploy
|
84
|
+
end
|
85
|
+
|
86
|
+
desc "rollback", "Switch back to previous release then finalize"
|
87
|
+
def rollback
|
88
|
+
end
|
89
|
+
|
90
|
+
desc "build", "Build package."
|
91
|
+
method_option :build_from, aliases: %w(--source -f), type: :string
|
92
|
+
method_option :build_to, aliases: %w(--destination -t), type: :string
|
93
|
+
method_option :skip_prepare_build, aliases: %w(--no-prepare-build -P), type: :boolean
|
94
|
+
method_option :force_prepare_build, aliases: %w(--prepare-build -p), type: :boolean
|
95
|
+
def build
|
96
|
+
# TODO: overriding name
|
97
|
+
%i(build_from build_to).each { |k| script.set(k, File.expand_path(options[k])) if options[k] }
|
98
|
+
|
99
|
+
if options[:force_prepare_build] && options[:skip_prepare_build]
|
100
|
+
logger.warn 'Both force_prepare_build and skip_prepare_build are enabled. ' \
|
101
|
+
'This results skipping prepare_build...'
|
102
|
+
end
|
103
|
+
|
104
|
+
if options[:force_prepare_build]
|
105
|
+
script.set :skip_prepare_build, false
|
106
|
+
end
|
107
|
+
|
108
|
+
if options[:skip_prepare_build]
|
109
|
+
script.set :skip_prepare_build, true
|
110
|
+
end
|
111
|
+
|
112
|
+
Mamiya::Steps::Build.new(script: script, logger: logger).run!
|
113
|
+
end
|
114
|
+
|
115
|
+
desc "push PACKAGE", "Upload built packages to storage."
|
116
|
+
def push(package_atom)
|
117
|
+
package_path = package_path_from_atom(package_atom)
|
118
|
+
|
119
|
+
if options[:application]
|
120
|
+
logger.warn "Overriding package's application name with given one: #{options[:application]}"
|
121
|
+
sleep 2
|
122
|
+
end
|
123
|
+
|
124
|
+
Mamiya::Steps::Push.new(
|
125
|
+
config: config,
|
126
|
+
package: package_path,
|
127
|
+
application: options[:application],
|
128
|
+
).run!
|
129
|
+
end
|
130
|
+
|
131
|
+
desc "fetch PACKAGE DESTINATION", "Retrieve package from storage"
|
132
|
+
def fetch(package_atom, destination)
|
133
|
+
Mamiya::Steps::Fetch.new(
|
134
|
+
script: script(:no_error),
|
135
|
+
config: config,
|
136
|
+
package: package_atom,
|
137
|
+
application: application,
|
138
|
+
destination: destination,
|
139
|
+
).run!
|
140
|
+
end
|
141
|
+
|
142
|
+
desc "extract PACKAGE DESTINATION", "Unpack package to DESTINATION"
|
143
|
+
def extract(package_atom, destination)
|
144
|
+
package_path = package_path_from_atom(package_atom)
|
145
|
+
|
146
|
+
Mamiya::Steps::Extract.new(
|
147
|
+
package: package_path,
|
148
|
+
destination: destination
|
149
|
+
).run!
|
150
|
+
end
|
151
|
+
|
152
|
+
desc "distribute PACKAGE", "Order clients to download specified package."
|
153
|
+
def distribute
|
154
|
+
end
|
155
|
+
|
156
|
+
desc "prepare", "Prepare package on clients."
|
157
|
+
def prepare
|
158
|
+
end
|
159
|
+
|
160
|
+
desc "finalize", "Finalize (start) prepared package on clients."
|
161
|
+
def finalize
|
162
|
+
end
|
163
|
+
|
164
|
+
|
165
|
+
# ---
|
166
|
+
|
167
|
+
desc "agent", "Start agent."
|
168
|
+
method_option :serf, type: :array
|
169
|
+
method_option :daemonize, aliases: '-D', type: :boolean, default: false
|
170
|
+
method_option :log, aliases: '-l', type: :string
|
171
|
+
method_option :pidfile, aliases: '-p', type: :string
|
172
|
+
def agent
|
173
|
+
prepare_agent_behavior!
|
174
|
+
merge_serf_option!
|
175
|
+
|
176
|
+
agent = Agent.new(config, logger: logger)
|
177
|
+
agent.run!
|
178
|
+
end
|
179
|
+
|
180
|
+
desc "master", "Start master"
|
181
|
+
method_option :serf, type: :array
|
182
|
+
method_option :daemonize, aliases: '-D', type: :boolean, default: false
|
183
|
+
method_option :log, aliases: '-l', type: :string
|
184
|
+
method_option :pidfile, aliases: '-p', type: :string
|
185
|
+
def master
|
186
|
+
prepare_agent_behavior!
|
187
|
+
merge_serf_option!
|
188
|
+
|
189
|
+
agent = Master.new(config, logger: logger)
|
190
|
+
agent.run!
|
191
|
+
end
|
192
|
+
|
193
|
+
# def worker
|
194
|
+
# end
|
195
|
+
|
196
|
+
# def event_handler
|
197
|
+
# end
|
198
|
+
|
199
|
+
private
|
200
|
+
|
201
|
+
def prepare_agent_behavior!
|
202
|
+
pidfile = File.expand_path(options[:pidfile]) if options[:pidfile]
|
203
|
+
logger # insitantiate
|
204
|
+
|
205
|
+
Process.daemon(:nochdir) if options[:daemonize]
|
206
|
+
|
207
|
+
if pidfile
|
208
|
+
open(pidfile, 'w') { |io| io.puts $$ }
|
209
|
+
at_exit { File.unlink(pidfile) if File.exist?(pidfile) }
|
210
|
+
end
|
211
|
+
|
212
|
+
reload_queue = Queue.new
|
213
|
+
reload_thread = Thread.new do
|
214
|
+
while reload_queue.pop
|
215
|
+
logger.info "Reopening"
|
216
|
+
logger.reopen
|
217
|
+
logger.info "Log reopened"
|
218
|
+
end
|
219
|
+
end
|
220
|
+
reload_thread.abort_on_exception = true
|
221
|
+
|
222
|
+
trap(:HUP) do
|
223
|
+
reload_queue << true
|
224
|
+
end
|
225
|
+
end
|
226
|
+
|
227
|
+
def config(dont_raise_error = false)
|
228
|
+
return @config if @config
|
229
|
+
path = [options[:config], './mamiya.yml', './config.yml'].compact.find { |_| File.exists?(_) }
|
230
|
+
|
231
|
+
if path
|
232
|
+
logger.debug "Using configuration: #{path}"
|
233
|
+
@config = Mamiya::Config.load(File.expand_path(path))
|
234
|
+
else
|
235
|
+
logger.debug "Couldn't find configuration file"
|
236
|
+
return nil if dont_raise_error
|
237
|
+
fatal! "Configuration File not found (try --config(-C) option or place it at ./mamiya.yml or ./config.yml)"
|
238
|
+
end
|
239
|
+
end
|
240
|
+
|
241
|
+
def script(dont_raise_error = false)
|
242
|
+
return @script if @script
|
243
|
+
path = [options[:script], './mamiya.rb', './deploy.rb'].compact.find { |_| File.exists?(_) }
|
244
|
+
|
245
|
+
if path
|
246
|
+
logger.debug "Using deploy script: #{path}"
|
247
|
+
@script = Mamiya::Script.new.load!(File.expand_path(path)).tap do |s|
|
248
|
+
s.set :application, options[:application] if options[:application]
|
249
|
+
s.set :logger, logger
|
250
|
+
end
|
251
|
+
else
|
252
|
+
logger.debug "Couldn't find deploy script."
|
253
|
+
return nil if dont_raise_error
|
254
|
+
fatal! "Deploy Script File not found (try --script(-S) option or place it at ./mamiya.rb or ./deploy.rb)"
|
255
|
+
end
|
256
|
+
end
|
257
|
+
|
258
|
+
def fatal!(message)
|
259
|
+
logger.fatal message
|
260
|
+
exit 1
|
261
|
+
end
|
262
|
+
|
263
|
+
def merge_serf_option!
|
264
|
+
(config[:serf] ||= {})[:agent] ||= {}
|
265
|
+
|
266
|
+
options[:serf].flat_map{ |_| _.split(/,/) }.each do |conf|
|
267
|
+
k,v = conf.split(/=/,2)
|
268
|
+
config[:serf][:agent][k.to_sym] = v
|
269
|
+
end
|
270
|
+
end
|
271
|
+
|
272
|
+
def application
|
273
|
+
options[:application] || config[:application] || script.application
|
274
|
+
end
|
275
|
+
|
276
|
+
def storage
|
277
|
+
config.storage_class.new(
|
278
|
+
config[:storage].merge(
|
279
|
+
application: application
|
280
|
+
)
|
281
|
+
)
|
282
|
+
end
|
283
|
+
|
284
|
+
def _applications
|
285
|
+
config.storage_class.find(config[:storage])
|
286
|
+
end
|
287
|
+
|
288
|
+
def logger
|
289
|
+
@logger ||= begin
|
290
|
+
$stdout.sync = ENV["MAMIYA_SYNC_OUT"] == '1'
|
291
|
+
outs = [$stdout]
|
292
|
+
outs << File.expand_path(options[:log]) if options[:log]
|
293
|
+
Mamiya::Logger.new(
|
294
|
+
color: options[:no_color] ? false : (options[:color] ? true : nil),
|
295
|
+
outputs: outs,
|
296
|
+
level: options[:debug] ? Mamiya::Logger::DEBUG : Mamiya::Logger.defaults[:level],
|
297
|
+
)
|
298
|
+
end
|
299
|
+
end
|
300
|
+
|
301
|
+
def package_path_from_atom(package_atom)
|
302
|
+
candidates = [
|
303
|
+
package_atom,
|
304
|
+
options[:build_to] && File.join(options[:build_to], package_atom),
|
305
|
+
options[:build_to] && File.join(options[:build_to], "#{package_atom}.tar.gz"),
|
306
|
+
script(:no_error) && script.build_to && File.join(script.build_to, package_atom),
|
307
|
+
script(:no_error) && script.build_to && File.join(script.build_to, "#{package_atom}.tar.gz"),
|
308
|
+
]
|
309
|
+
logger.debug "Candidates: #{candidates.inspect}"
|
310
|
+
|
311
|
+
package_path = candidates.select { |_| _ }.find { |_| File.exists?(_) }
|
312
|
+
|
313
|
+
unless package_path
|
314
|
+
fatal! "Package (#{package_atom}) couldn't find at #{candidates.join(', ')}"
|
315
|
+
end
|
316
|
+
|
317
|
+
package_path
|
318
|
+
end
|
319
|
+
end
|
320
|
+
end
|
321
|
+
|
322
|
+
require 'mamiya/cli/client'
|