mamiya 0.0.1.alpha8 → 0.0.1.alpha9

Sign up to get free protection for your applications and to get access to all the features.
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