mamiya 0.0.1.alpha2
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 +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'
|