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 +4 -4
- data/.gitignore +1 -0
- data/docs/cli.md +78 -0
- data/lib/mamiya/agent/fetcher.rb +45 -17
- data/lib/mamiya/agent.rb +19 -1
- data/lib/mamiya/cli.rb +9 -5
- data/lib/mamiya/master/agent_monitor_handlers.rb +6 -0
- data/lib/mamiya/master.rb +5 -0
- data/lib/mamiya/version.rb +1 -1
- data/mamiya.gemspec +1 -0
- data/spec/agent/fetcher_spec.rb +47 -9
- data/spec/agent_spec.rb +6 -1
- data/spec/master/agent_monitor_spec.rb +4 -2
- data/spec/spec_helper.rb +5 -0
- metadata +17 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 3f7822be0f2ea92b439156730db75fc2608820ec
|
4
|
+
data.tar.gz: 34495ba570dab6778304c2f0cc68b2fdc9914477
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a15d9f6afd8b69c60e12e22609fe1e713f5da3d85c1272923b171fc04946655e2cc6c19142e9af7d1b6e44927a80a59ccc79b59644dc15700a8b898da2a48a19
|
7
|
+
data.tar.gz: c3fddda1d60e1e2b348c6c0b635426abc9d265fe9a42bcbb9b22908063a62e41a4e32f536299d5c69f7841b7e99b5625ce995a4f311a00e25c0e30cd12ec2b64
|
data/.gitignore
CHANGED
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`
|
data/lib/mamiya/agent/fetcher.rb
CHANGED
@@ -11,52 +11,63 @@ module Mamiya
|
|
11
11
|
GRACEFUL_TIMEOUT = 60
|
12
12
|
|
13
13
|
def initialize(config, logger: Mamiya::Logger.new)
|
14
|
-
@
|
15
|
-
@
|
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 :
|
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
|
-
@
|
35
|
+
@external_queue << [app, package, before, callback]
|
32
36
|
end
|
33
37
|
|
34
38
|
def queue_size
|
35
|
-
@
|
39
|
+
@internal_queue.size
|
36
40
|
end
|
37
41
|
|
38
42
|
def start!
|
43
|
+
stop!
|
39
44
|
@logger.info 'Starting...'
|
40
45
|
|
41
|
-
@
|
42
|
-
@
|
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
|
-
|
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
|
-
|
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
|
-
@
|
64
|
+
@worker_thread = nil
|
65
|
+
@queueing_thread = nil
|
56
66
|
end
|
57
67
|
|
58
68
|
def running?
|
59
|
-
@
|
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 = @
|
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
|
-
|
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
data/lib/mamiya/version.rb
CHANGED
data/mamiya.gemspec
CHANGED
data/spec/agent/fetcher_spec.rb
CHANGED
@@ -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.
|
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.
|
28
|
-
expect(fetcher.
|
29
|
-
th = fetcher.
|
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
|
-
|
34
|
+
20.times { break unless th.alive?; sleep 0.1 }
|
34
35
|
expect(th).not_to be_alive
|
35
36
|
|
36
|
-
expect(fetcher.
|
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
|
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
|
-
|
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
|
-
|
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:
|
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
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.
|
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-
|
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
|