mamiya 0.0.1.alpha8 → 0.0.1.alpha9

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: aaf47b18849f90c0acb28dcea4b4c367466357af
4
- data.tar.gz: 2b3bafda6e415b6adec0626f9dcceeb737a16ae9
3
+ metadata.gz: 3f7822be0f2ea92b439156730db75fc2608820ec
4
+ data.tar.gz: 34495ba570dab6778304c2f0cc68b2fdc9914477
5
5
  SHA512:
6
- metadata.gz: d541ca28c6c904b33ce224226955795b0d1087e36b1a3f0183707a092a3f868ef1a05fcc2edf8b58898319f8cd9aa952d00acac25f0648efc1bc11a41b12c10d
7
- data.tar.gz: 122b661348d2b91d397671e49aacd35d81c83ef2a8b9e9b3af0e92753224e516984396e4dc0abc9dd552b5cd0bd1557a12e8a9de461000443b1335fe866e465a
6
+ metadata.gz: a15d9f6afd8b69c60e12e22609fe1e713f5da3d85c1272923b171fc04946655e2cc6c19142e9af7d1b6e44927a80a59ccc79b59644dc15700a8b898da2a48a19
7
+ data.tar.gz: c3fddda1d60e1e2b348c6c0b635426abc9d265fe9a42bcbb9b22908063a62e41a4e32f536299d5c69f7841b7e99b5625ce995a4f311a00e25c0e30cd12ec2b64
data/.gitignore CHANGED
@@ -15,3 +15,4 @@ spec/reports
15
15
  test/tmp
16
16
  test/version_tmp
17
17
  tmp
18
+ /coverage/
data/docs/cli.md ADDED
@@ -0,0 +1,78 @@
1
+ # Commands
2
+
3
+ ## Global options
4
+
5
+ - `-C`, `--config`: path to configuration file (default: `./config.yml`)
6
+ - config file won't be required if a command don't need it.
7
+ - `-S`, `--script`: path to script file (default: `./deploy.rb`)
8
+ - script file won't be required if a command don't need it.
9
+ - `-a`, `--app`: Specify application name to operate
10
+ - `-d`, `--debug`: Enable debug mode
11
+ - `--color`, `--no-color`: Enable or disable colored output. When the stdout is a terminal, it'll be enabled by default.
12
+
13
+ ## Storage related commands
14
+
15
+ ### `list-applications` - list application in storage
16
+
17
+ ```
18
+ $ mamiya list-applications -C ./config.yml
19
+ ```
20
+
21
+ ### `list-packages` - list packages for specified app in storage
22
+
23
+ ```
24
+ $ mamiya list-packages -C ./config.yml -a myapp
25
+ ```
26
+
27
+ - __Requires:__ configuration file, application name
28
+ - application name will be retrieved from deploy script when not specified.
29
+ - __Options:__
30
+ - `-n`, `--name-only`: Show only names (without heading text)
31
+
32
+ ### `show` - show package information
33
+
34
+ ```
35
+ $ mamiya list-packages -C ./config.yml -a myapp PACKAGE_NAME
36
+ ```
37
+
38
+ - __Requires:__ configuration file, application name, package name
39
+ - application name will be retrieved from deploy script when not specified.
40
+ - __Options:__
41
+ - `-f`, `--format`: Choose output format from `pp`, `json`, or `yaml`. Default: `pp`.
42
+
43
+ ## Build, pushing and fetching packages
44
+
45
+ ### `build` - build package using script
46
+
47
+ ```
48
+ $ mamiya build --script ./deploy.rb --source source_dir --destination dest_dir
49
+ ```
50
+
51
+ - __Requires:__ application name, source, destination, deploy script
52
+ - source, description, and app name will be taken from deploy script, if omitted
53
+ - __Options:__
54
+ - `-f`, `--source`, `--build-from`: directory for package source.
55
+ - `-t`, `--destination`, `--build-to`: directory to save built packages.
56
+ - `-P`, `--skip-prepare-build`: Skip prepare build phase of deploy script.
57
+
58
+ ### `push` - push built package to the storage
59
+
60
+ ### `fetch`
61
+
62
+ ## Package related commands
63
+
64
+ ### `extract`
65
+
66
+ ## `client` - API client for `mamiya master`
67
+
68
+ ### `list-applications`
69
+
70
+ ### `list-packages`
71
+
72
+ ### `show-package`
73
+
74
+ ### `list-agents`
75
+
76
+ ### `show-agent`
77
+
78
+ ### `show-distribution`
@@ -11,52 +11,63 @@ module Mamiya
11
11
  GRACEFUL_TIMEOUT = 60
12
12
 
13
13
  def initialize(config, logger: Mamiya::Logger.new)
14
- @thread = nil
15
- @queue = Queue.new
14
+ @worker_thread = nil
15
+ @queueing_thread = nil
16
+ @external_queue = Queue.new
17
+ @internal_queue = Queue.new
16
18
 
17
19
  @config = config
18
20
  @destination = config[:packages_dir]
19
21
  @keep_packages = config[:keep_packages]
20
22
  @current_job = nil
23
+ @pending_jobs = []
21
24
 
22
25
  @logger = logger['fetcher']
23
- @working = nil
24
26
  end
25
27
 
26
- attr_reader :thread
28
+ attr_reader :worker_thread
29
+ attr_reader :queueing_thread
27
30
  attr_reader :current_job
31
+ attr_reader :pending_jobs
28
32
  attr_writer :cleanup_hook
29
33
 
30
34
  def enqueue(app, package, before: nil, &callback)
31
- @queue << [app, package, before, callback]
35
+ @external_queue << [app, package, before, callback]
32
36
  end
33
37
 
34
38
  def queue_size
35
- @queue.size
39
+ @internal_queue.size
36
40
  end
37
41
 
38
42
  def start!
43
+ stop!
39
44
  @logger.info 'Starting...'
40
45
 
41
- @thread = Thread.new(&method(:main_loop))
42
- @thread.abort_on_exception = true
46
+ @worker_thread = Thread.new(&method(:main_loop))
47
+ @worker_thread.abort_on_exception = true
48
+
49
+ @queueing_thread = Thread.new(&method(:queueing_loop))
50
+ @queueing_thread.abort_on_exception = true
43
51
  end
44
52
 
45
53
  def stop!(graceful = false)
46
- return unless @thread
54
+ {@external_queue => @queueing_thread, @internal_queue => @worker_thread}.each do |q, th|
55
+ next unless th
56
+ if graceful
57
+ q << :suicide
58
+ th.join(GRACEFUL_TIMEOUT)
59
+ end
47
60
 
48
- if graceful
49
- @queue << :suicide
50
- @thread.join(GRACEFUL_TIMEOUT)
61
+ th.kill if th.alive?
51
62
  end
52
-
53
- @thread.kill if @thread.alive?
54
63
  ensure
55
- @thread = nil
64
+ @worker_thread = nil
65
+ @queueing_thread = nil
56
66
  end
57
67
 
58
68
  def running?
59
- @thread && @thread.alive?
69
+ @worker_thread && @worker_thread.alive? && \
70
+ @queueing_thread && @queueing_thread.alive?
60
71
  end
61
72
 
62
73
  def working?
@@ -88,15 +99,31 @@ module Mamiya
88
99
  private
89
100
 
90
101
  def main_loop
91
- while order = @queue.pop
102
+ while order = @internal_queue.pop
92
103
  break if order == :suicide
104
+ @pending_jobs.delete(order)
93
105
  handle_order(*order)
94
106
  end
95
107
  end
96
108
 
109
+ def queueing_loop
110
+ while order = @external_queue.pop
111
+ break if order == :suicide
112
+ @pending_jobs << order
113
+ @internal_queue << order
114
+ end
115
+ end
116
+
97
117
  def handle_order(app, package, before_hook = nil, callback = nil)
98
118
  @current_job = [app, package]
99
119
  @logger.info "fetching #{app}:#{package}"
120
+
121
+ if @config[:fetch_sleep]
122
+ wait = rand(@config[:fetch_sleep])
123
+ @logger.debug "Sleeping #{wait} before starting fetch"
124
+ sleep wait
125
+ end
126
+
100
127
  # TODO: Limit apps by configuration
101
128
 
102
129
  destination = File.join(@destination, app)
@@ -113,6 +140,7 @@ module Mamiya
113
140
  config: @config,
114
141
  ).run!
115
142
 
143
+ @current_job = nil
116
144
  callback.call if callback
117
145
 
118
146
  @logger.info "fetched #{app}:#{package}"
data/lib/mamiya/agent.rb CHANGED
@@ -18,6 +18,8 @@ module Mamiya
18
18
  @serf = init_serf
19
19
  @events_only = events_only
20
20
 
21
+ @terminate = false
22
+
21
23
  @logger = logger['agent']
22
24
  end
23
25
 
@@ -35,15 +37,30 @@ module Mamiya
35
37
  logger.info "Started."
36
38
 
37
39
  loop do
38
- sleep 10
40
+ if @terminate
41
+ terminate
42
+ return
43
+ end
44
+ sleep 1
39
45
  end
40
46
  end
41
47
 
48
+ def stop!
49
+ @terminate = true
50
+ end
51
+
42
52
  def start
43
53
  serf_start
44
54
  fetcher_start
45
55
  end
46
56
 
57
+ def terminate
58
+ serf.stop!
59
+ fetcher.stop!
60
+ ensure
61
+ @terminate = false
62
+ end
63
+
47
64
  def update_tags!
48
65
  serf.tags['mamiya'] = ','.tap do |status|
49
66
  status.concat('fetching,') if fetcher.working?
@@ -63,6 +80,7 @@ module Mamiya
63
80
  s[:fetcher] = {
64
81
  fetching: fetcher.current_job,
65
82
  pending: fetcher.queue_size,
83
+ pending_jobs: fetcher.pending_jobs.map{ |_| _[0,2] },
66
84
  }
67
85
 
68
86
  s[:packages] = self.existing_packages
data/lib/mamiya/cli.rb CHANGED
@@ -179,8 +179,8 @@ module Mamiya
179
179
  prepare_agent_behavior!
180
180
  merge_serf_option!
181
181
 
182
- agent = Agent.new(config, logger: logger)
183
- agent.run!
182
+ @agent = Agent.new(config, logger: logger)
183
+ @agent.run!
184
184
  end
185
185
 
186
186
  desc "master", "Start master"
@@ -192,8 +192,8 @@ module Mamiya
192
192
  prepare_agent_behavior!
193
193
  merge_serf_option!
194
194
 
195
- agent = Master.new(config, logger: logger)
196
- agent.run!
195
+ @agent = Master.new(config, logger: logger)
196
+ @agent.run!
197
197
  end
198
198
 
199
199
  # def worker
@@ -216,9 +216,13 @@ module Mamiya
216
216
  end
217
217
 
218
218
  trap(:HUP) do
219
- $stderr.puts "hi"
220
219
  logger.reopen
221
220
  end
221
+
222
+ trap(:TERM) do
223
+ puts "Received SIGTERM..."
224
+ @agent.stop! if @agent
225
+ end
222
226
  end
223
227
 
224
228
  def config(dont_raise_error = false)
@@ -6,11 +6,17 @@ module Mamiya
6
6
  def fetch_result__ack(status, payload, event)
7
7
  status['fetcher'] ||= {}
8
8
  status['fetcher']['pending'] = payload['pending']
9
+
10
+ status['fetcher']['pending_jobs'] ||= []
11
+ status['fetcher']['pending_jobs'] << [payload['application'], payload['package']]
9
12
  end
10
13
 
11
14
  def fetch_result__start(status, payload, event)
12
15
  status['fetcher'] ||= {}
13
16
  status['fetcher']['fetching'] = [payload['application'], payload['package']]
17
+
18
+ status['fetcher']['pending_jobs'] ||= []
19
+ status['fetcher']['pending_jobs'].delete [payload['application'], payload['package']]
14
20
  end
15
21
 
16
22
  def fetch_result__error(status, payload, event)
data/lib/mamiya/master.rb CHANGED
@@ -33,6 +33,11 @@ module Mamiya
33
33
  monitor_start
34
34
  end
35
35
 
36
+ def terminate
37
+ @agent_monitor.stop!
38
+ super
39
+ end
40
+
36
41
  def distribute(application, package)
37
42
  trigger(:fetch, application: application, package: package)
38
43
  end
@@ -1,3 +1,3 @@
1
1
  module Mamiya
2
- VERSION = "0.0.1.alpha8"
2
+ VERSION = "0.0.1.alpha9"
3
3
  end
data/mamiya.gemspec CHANGED
@@ -32,4 +32,5 @@ Gem::Specification.new do |spec|
32
32
 
33
33
  spec.add_development_dependency "bundler", "~> 1.5"
34
34
  spec.add_development_dependency "rake"
35
+ spec.add_development_dependency 'simplecov', '~> 0.7.1'
35
36
  end
@@ -6,6 +6,7 @@ require 'fileutils'
6
6
  require 'mamiya/agent/fetcher'
7
7
  require 'mamiya/steps/fetch'
8
8
 
9
+
9
10
  describe Mamiya::Agent::Fetcher do
10
11
  let!(:tmpdir) { Dir.mktmpdir('mamiya-agent-fetcher-spec') }
11
12
  after { FileUtils.remove_entry_secure(tmpdir) if File.exist?(tmpdir) }
@@ -18,22 +19,22 @@ describe Mamiya::Agent::Fetcher do
18
19
 
19
20
  describe "lifecycle" do
20
21
  it "can start and stop" do
21
- expect(fetcher.thread).to be_nil
22
+ expect(fetcher.worker_thread).to be_nil
22
23
  expect(fetcher).not_to be_running
23
24
 
24
25
  fetcher.start!
25
26
 
26
27
  expect(fetcher).to be_running
27
- expect(fetcher.thread).to be_a(Thread)
28
- expect(fetcher.thread).to be_alive
29
- th = fetcher.thread
28
+ expect(fetcher.worker_thread).to be_a(Thread)
29
+ expect(fetcher.worker_thread).to be_alive
30
+ th = fetcher.worker_thread
30
31
 
31
32
  fetcher.stop!
32
33
 
33
- 10.times { break unless th.alive?; sleep 0.1 }
34
+ 20.times { break unless th.alive?; sleep 0.1 }
34
35
  expect(th).not_to be_alive
35
36
 
36
- expect(fetcher.thread).to be_nil
37
+ expect(fetcher.worker_thread).to be_nil
37
38
  expect(fetcher).not_to be_running
38
39
  end
39
40
 
@@ -92,6 +93,33 @@ describe Mamiya::Agent::Fetcher do
92
93
  end
93
94
  end
94
95
 
96
+ describe "#pending_jobs" do
97
+ before do
98
+ step = double('fetch-step')
99
+ allow(step).to receive(:run!)
100
+ allow(Mamiya::Steps::Fetch).to receive(:new).with(
101
+ application: 'myapp',
102
+ package: 'package',
103
+ destination: File.join(tmpdir, 'myapp'),
104
+ config: config,
105
+ ).and_return(step)
106
+ end
107
+
108
+ it "shows remaining jobs" do
109
+ fetcher.start!; fetcher.worker_thread.kill
110
+
111
+ expect {
112
+ fetcher.enqueue('myapp', 'package')
113
+ fetcher.stop!(:graceful)
114
+ }.to change { fetcher.pending_jobs } \
115
+ .from([]).to([['myapp', 'package', nil, nil]])
116
+
117
+ fetcher.start!; fetcher.stop!(:graceful)
118
+
119
+ expect(fetcher.pending_jobs).to be_empty
120
+ end
121
+ end
122
+
95
123
  describe "mainloop" do
96
124
  before do
97
125
  allow(step).to receive(:run!)
@@ -122,6 +150,7 @@ describe Mamiya::Agent::Fetcher do
122
150
  received = true
123
151
 
124
152
  fetcher.enqueue('myapp', 'package') do |succeeded|
153
+ expect(fetcher.working?).to be_false
125
154
  received = succeeded
126
155
  end
127
156
 
@@ -141,11 +170,11 @@ describe Mamiya::Agent::Fetcher do
141
170
  expect(fetcher.current_job).to be_nil
142
171
 
143
172
  received = false
144
- fetcher.enqueue('myapp', 'package') do |error|
145
- received = true
173
+ fetcher.enqueue 'myapp', 'package', before: proc { |error|
146
174
  expect(fetcher.working?).to be_true
147
175
  expect(fetcher.current_job).to eq %w(myapp package)
148
- end
176
+ received = true
177
+ }
149
178
 
150
179
  fetcher.stop!(:graceful)
151
180
  expect(received).to be_true
@@ -153,6 +182,15 @@ describe Mamiya::Agent::Fetcher do
153
182
  expect(fetcher.current_job).to be_nil
154
183
  end
155
184
 
185
+ context "with config.fetch_sleep" do
186
+ it "calls sleep" do
187
+ config[:fetch_sleep] = 1
188
+ expect(fetcher).to receive(:sleep)
189
+ fetcher.enqueue 'myapp', 'package'
190
+ fetcher.stop!(:graceful)
191
+ end
192
+ end
193
+
156
194
  context "with before hook" do
157
195
  it "calls callback" do
158
196
  run = false
data/spec/agent_spec.rb CHANGED
@@ -111,7 +111,8 @@ describe Mamiya::Agent do
111
111
  allow(agent).to receive(:existing_packages).and_return("app" => ["pkg"])
112
112
  allow(fetcher).to receive(:queue_size).and_return(42)
113
113
  allow(fetcher).to receive(:working?).and_return(false)
114
- allow(fetcher).to receive(:current_job).and_return(nil)
114
+ allow(fetcher).to receive(:current_job).and_return(nil)
115
+ allow(fetcher).to receive(:pending_jobs).and_return([['app', 'pkg2', nil, nil]])
115
116
  end
116
117
 
117
118
  subject(:status) { agent.status }
@@ -129,6 +130,10 @@ describe Mamiya::Agent do
129
130
  expect(status[:fetcher][:pending]).to eq 42
130
131
  end
131
132
 
133
+ it "includes pendings job" do
134
+ expect(status[:fetcher][:pending_jobs]).to eq([['app', 'pkg2']])
135
+ end
136
+
132
137
  it "shows fetching status" do
133
138
  expect(status[:fetcher][:fetching]).to be_nil
134
139
  end
@@ -157,20 +157,22 @@ describe Mamiya::Master::AgentMonitor do
157
157
  end
158
158
 
159
159
  it "updates pending" do
160
- commit('mamiya:fetch-result:ack', pending: 72)
160
+ commit('mamiya:fetch-result:ack', pending: 72, application: 'foo', package: 'bar')
161
161
  expect(new_status["fetcher"]["pending"]).to eq 72
162
+ expect(new_status["fetcher"]["pending_jobs"]).to eq [%w(foo bar)]
162
163
  end
163
164
  end
164
165
 
165
166
  describe ":start" do
166
167
  let(:status) do
167
- {fetcher: {fetching: nil, pending: 0}}
168
+ {fetcher: {fetching: nil, pending: 1, pending_jobs: [%w(app pkg)]}}
168
169
  end
169
170
 
170
171
  it "updates fetching" do
171
172
  commit('mamiya:fetch-result:start',
172
173
  application: 'app', package: 'pkg', pending: 0)
173
174
  expect(new_status["fetcher"]["fetching"]).to eq ['app', 'pkg']
175
+ expect(new_status["fetcher"]["pending_jobs"]).to be_empty
174
176
  end
175
177
  end
176
178
 
data/spec/spec_helper.rb CHANGED
@@ -1,4 +1,9 @@
1
+ require 'simplecov'
1
2
  require 'rack/test'
3
+ SimpleCov.start do
4
+ add_filter "/spec/"
5
+ end
6
+
2
7
  require 'mamiya/storages/mock'
3
8
  require 'mamiya/logger'
4
9
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: mamiya
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1.alpha8
4
+ version: 0.0.1.alpha9
5
5
  platform: ruby
6
6
  authors:
7
7
  - Shota Fukumori (sora_h)
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-06-03 00:00:00.000000000 Z
11
+ date: 2014-06-04 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: thor
@@ -136,6 +136,20 @@ dependencies:
136
136
  - - ">="
137
137
  - !ruby/object:Gem::Version
138
138
  version: '0'
139
+ - !ruby/object:Gem::Dependency
140
+ name: simplecov
141
+ requirement: !ruby/object:Gem::Requirement
142
+ requirements:
143
+ - - "~>"
144
+ - !ruby/object:Gem::Version
145
+ version: 0.7.1
146
+ type: :development
147
+ prerelease: false
148
+ version_requirements: !ruby/object:Gem::Requirement
149
+ requirements:
150
+ - - "~>"
151
+ - !ruby/object:Gem::Version
152
+ version: 0.7.1
139
153
  description: Deploy tool using tarballs and serf for lot of servers
140
154
  email:
141
155
  - her@sorah.jp
@@ -153,6 +167,7 @@ files:
153
167
  - Rakefile
154
168
  - bin/mamiya
155
169
  - config.example.yml
170
+ - docs/cli.md
156
171
  - docs/sequences/deploy.png
157
172
  - docs/sequences/deploy.uml
158
173
  - example.rb