kumogata 0.3.13 → 0.3.14
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 +8 -8
- data/README.md +2 -2
- data/lib/kumogata.rb +2 -0
- data/lib/kumogata/post_processing.rb +80 -14
- data/lib/kumogata/string_stream.rb +39 -0
- data/lib/kumogata/version.rb +1 -1
- data/spec/kumogata_create_spec.rb +15 -5
- data/spec/kumogata_update_spec.rb +15 -5
- data/spec/string_stream_spec.rb +123 -0
- metadata +5 -2
checksums.yaml
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
---
|
2
2
|
!binary "U0hBMQ==":
|
3
3
|
metadata.gz: !binary |-
|
4
|
-
|
4
|
+
NWY1ZGU1ZTExOTU3MWMyMmYwNGViNGVkNTc0ZGI3OTkxMzI2NTRkNA==
|
5
5
|
data.tar.gz: !binary |-
|
6
|
-
|
6
|
+
NjE4MjUwNWQ5ZjQ0Njg5YzUzNDYxZDQwOTIzNTdjZmFlZGViM2RjNQ==
|
7
7
|
SHA512:
|
8
8
|
metadata.gz: !binary |-
|
9
|
-
|
10
|
-
|
11
|
-
|
9
|
+
YjE1YzNkYWJmMTcwZTNiMjdmMjZhMWUwNDc2ZDJkOWQzYjgwOTRlMDY3NTM4
|
10
|
+
NWQzZTYxM2U5OTY1NjgwMGE3MWI5YjRmYmRmZjI3OGM4MTJlMzdhOTJkZmFm
|
11
|
+
OGIzNTc3NTliMjYzMjVlNzYxOWE5Y2Y2YTJlMDZlYjNjMDVjMDc=
|
12
12
|
data.tar.gz: !binary |-
|
13
|
-
|
14
|
-
|
15
|
-
|
13
|
+
Y2ZiMzE5MmM3ZDU0MGJlZjJjNGVlYjRhOWI3MGNlZmU2YTFlOTc3NTU5YzM2
|
14
|
+
N2JiMzk1ZTJmNzllNDM5NzMyOWIzZmQ3NWU2NWQ1Mzk3NDMzMWY3YTQxZjMz
|
15
|
+
ZGJiNDNmNDE1OWMyNDU2MDU1Yzg5Y2Q4NDUxMTYxZjM4MGNhYzY=
|
data/README.md
CHANGED
@@ -5,8 +5,8 @@
|
|
5
5
|
|
6
6
|
Kumogata is a tool for [AWS CloudFormation](https://aws.amazon.com/cloudformation/).
|
7
7
|
|
8
|
-
[](http://badge.fury.io/rb/kumogata)
|
9
|
+
[](https://drone.io/github.com/winebarrel/kumogata/latest)
|
10
10
|
|
11
11
|
It can define a template in Ruby DSL, such as:
|
12
12
|
|
data/lib/kumogata.rb
CHANGED
@@ -19,6 +19,7 @@ require 'set'
|
|
19
19
|
require 'singleton'
|
20
20
|
require 'strscan'
|
21
21
|
require 'term/ansicolor'
|
22
|
+
require 'thread'
|
22
23
|
require 'uuidtools'
|
23
24
|
|
24
25
|
require 'kumogata/argument_parser'
|
@@ -29,4 +30,5 @@ require 'kumogata/ext/json_ext'
|
|
29
30
|
require 'kumogata/ext/string_ext'
|
30
31
|
require 'kumogata/logger'
|
31
32
|
require 'kumogata/post_processing'
|
33
|
+
require 'kumogata/string_stream'
|
32
34
|
require 'kumogata/utils'
|
@@ -135,13 +135,22 @@ class Kumogata::PostProcessing
|
|
135
135
|
connect_tries = (ssh['connect_tries'] || 36).to_i
|
136
136
|
retry_interval = (ssh['retry_interval'] || 5).to_i
|
137
137
|
|
138
|
+
stderr_orig = nil
|
139
|
+
|
138
140
|
begin
|
139
|
-
|
140
|
-
|
141
|
+
stderr_orig = STDERR.dup
|
142
|
+
STDERR.reopen('/dev/null', 'w')
|
143
|
+
|
144
|
+
begin
|
145
|
+
retryable(:tries => connect_tries, :on => Net::SSH::Disconnect, :sleep => retry_interval) do
|
146
|
+
Net::SSH.start(*args) {|ssh| ssh_exec!(ssh, command) }
|
147
|
+
end
|
148
|
+
rescue Net::SSH::HostKeyMismatch => e
|
149
|
+
e.remember_host!
|
150
|
+
retry
|
141
151
|
end
|
142
|
-
|
143
|
-
|
144
|
-
retry
|
152
|
+
ensure
|
153
|
+
STDERR.reopen(stderr_orig)
|
145
154
|
end
|
146
155
|
end
|
147
156
|
|
@@ -151,6 +160,9 @@ class Kumogata::PostProcessing
|
|
151
160
|
exit_code = nil
|
152
161
|
#exit_signal = nil
|
153
162
|
|
163
|
+
stdout_stream = create_stdout_stream
|
164
|
+
stderr_stream = create_stderr_stream
|
165
|
+
|
154
166
|
ssh.open_channel do |channel|
|
155
167
|
channel.exec(command) do |ch, success|
|
156
168
|
unless success
|
@@ -158,10 +170,12 @@ class Kumogata::PostProcessing
|
|
158
170
|
end
|
159
171
|
|
160
172
|
channel.on_data do |ch, data|
|
173
|
+
stdout_stream.push data
|
161
174
|
stdout_data << data
|
162
175
|
end
|
163
176
|
|
164
177
|
channel.on_extended_data do |ch, type, data|
|
178
|
+
stderr_stream.push data
|
165
179
|
stderr_data << data
|
166
180
|
end
|
167
181
|
|
@@ -177,13 +191,57 @@ class Kumogata::PostProcessing
|
|
177
191
|
|
178
192
|
ssh.loop
|
179
193
|
|
194
|
+
stdout_stream.close
|
195
|
+
stderr_stream.close
|
196
|
+
|
180
197
|
#[stdout_data, stderr_data, exit_code, exit_signal]
|
181
198
|
[stdout_data, stderr_data, exit_code]
|
182
199
|
end
|
183
200
|
|
184
201
|
def run_shell_command(command, outputs)
|
185
202
|
command = evaluate_command_template(command, outputs)
|
186
|
-
|
203
|
+
|
204
|
+
stdout_data = ''
|
205
|
+
stderr_data = ''
|
206
|
+
exit_code = nil
|
207
|
+
|
208
|
+
Open3.popen3(command) do |stdin, stdout, stderr, wait_thr|
|
209
|
+
mutex = Mutex.new
|
210
|
+
|
211
|
+
th_out = Thread.start do
|
212
|
+
stdout_stream = create_stdout_stream
|
213
|
+
|
214
|
+
stdout.each_line do |line|
|
215
|
+
mutex.synchronize do
|
216
|
+
stdout_stream.push line
|
217
|
+
end
|
218
|
+
|
219
|
+
stdout_data << line
|
220
|
+
end
|
221
|
+
|
222
|
+
stdout_stream.close
|
223
|
+
end
|
224
|
+
|
225
|
+
th_err = Thread.start do
|
226
|
+
stderr_stream = create_stderr_stream
|
227
|
+
|
228
|
+
stderr.each_line do |line|
|
229
|
+
mutex.synchronize do
|
230
|
+
stderr_stream.push line
|
231
|
+
end
|
232
|
+
stderr_data << line
|
233
|
+
end
|
234
|
+
|
235
|
+
stderr_stream.close
|
236
|
+
end
|
237
|
+
|
238
|
+
th_out.join
|
239
|
+
th_err.join
|
240
|
+
exit_code = wait_thr.value
|
241
|
+
end
|
242
|
+
|
243
|
+
#[stdout_data, stderr_data, exit_code, exit_signal]
|
244
|
+
[stdout_data, stderr_data, exit_code]
|
187
245
|
end
|
188
246
|
|
189
247
|
def validate_command_template(name, command, outputs)
|
@@ -232,17 +290,25 @@ Command: #{name.intense_blue}
|
|
232
290
|
EOS
|
233
291
|
end
|
234
292
|
|
235
|
-
def
|
293
|
+
def create_stdout_stream
|
294
|
+
Kumogata::StringStream.new do |line|
|
295
|
+
puts '1> '.intense_green + line
|
296
|
+
$stdout.flush
|
297
|
+
end
|
298
|
+
end
|
299
|
+
|
300
|
+
def create_stderr_stream
|
301
|
+
Kumogata::StringStream.new do |line|
|
302
|
+
puts '2> '.intense_red + line
|
303
|
+
$stdout.flush
|
304
|
+
end
|
305
|
+
end
|
306
|
+
|
307
|
+
def print_command_result(out, err, status) # XXX:
|
236
308
|
status = status.to_i
|
237
|
-
dspout = (out || '').lines.map {|i| "1> ".intense_green + i }.join.chomp
|
238
|
-
dsperr = (err || '').lines.map {|i| "2> ".intense_red + i }.join.chomp
|
239
309
|
|
240
310
|
puts <<-EOS
|
241
|
-
Status: #{status.zero? ? status : status.to_s.red}
|
242
|
-
dspout.empty? ? '' : ("\n---\n" + dspout)
|
243
|
-
}#{
|
244
|
-
dsperr.empty? ? '' : ("\n---\n" + dsperr)
|
245
|
-
}
|
311
|
+
Status: #{status.zero? ? status : status.to_s.red}
|
246
312
|
EOS
|
247
313
|
end
|
248
314
|
|
@@ -0,0 +1,39 @@
|
|
1
|
+
class Kumogata::StringStream
|
2
|
+
def initialize(&block)
|
3
|
+
@buf = StringScanner.new('')
|
4
|
+
@block = block
|
5
|
+
|
6
|
+
@fiber = Fiber.new do
|
7
|
+
self.run
|
8
|
+
end
|
9
|
+
|
10
|
+
# Step to `yield`
|
11
|
+
@fiber.resume
|
12
|
+
end
|
13
|
+
|
14
|
+
def run
|
15
|
+
loop do
|
16
|
+
chunk = Fiber.yield
|
17
|
+
break unless chunk
|
18
|
+
|
19
|
+
@buf << chunk.to_s
|
20
|
+
self.each_line
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def each_line
|
25
|
+
while (line = @buf.scan_until(/(\r\n|\r|\n)/))
|
26
|
+
@block.call(line.chomp)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def push(chunk)
|
31
|
+
@fiber.resume(chunk)
|
32
|
+
end
|
33
|
+
|
34
|
+
def close
|
35
|
+
self.each_line
|
36
|
+
@block.call(@buf.rest) if @buf.rest?
|
37
|
+
@fiber.resume
|
38
|
+
end
|
39
|
+
end
|
data/lib/kumogata/version.rb
CHANGED
@@ -146,9 +146,13 @@ end
|
|
146
146
|
process_status1 = make_double('process_status1') {|obj| obj.should_receive(:to_i).and_return(0) }
|
147
147
|
process_status2 = make_double('process_status2') {|obj| obj.should_receive(:to_i).and_return(0) }
|
148
148
|
|
149
|
-
|
149
|
+
client.instance_variable_get(:@post_processing)
|
150
|
+
.should_receive(:run_shell_command)
|
151
|
+
.with(" echo <%= Key \"AZ\" %>\n echo <%= Key \"Region\" %>\n", {"AZ"=>"ap-northeast-1b", "Region"=>"ap-northeast-1"})
|
150
152
|
.and_return(["ap-northeast-1b\nap-northeast-1\n", "", process_status1])
|
151
|
-
|
153
|
+
client.instance_variable_get(:@post_processing)
|
154
|
+
.should_receive(:run_shell_command)
|
155
|
+
.with(" echo <%= Key \"Region\" %>\n echo <%= Key \"AZ\" %>\n", {"AZ"=>"ap-northeast-1b", "Region"=>"ap-northeast-1"})
|
152
156
|
.and_return(["ap-northeast-1\nap-northeast-1b\n", "", process_status2])
|
153
157
|
|
154
158
|
client.instance_variable_get(:@post_processing)
|
@@ -240,7 +244,9 @@ end
|
|
240
244
|
|
241
245
|
cf.should_receive(:stacks).twice { stacks }
|
242
246
|
|
243
|
-
|
247
|
+
client.instance_variable_get(:@post_processing)
|
248
|
+
.should_receive(:run_ssh_command)
|
249
|
+
.with({"host"=>"<%= Key \"PublicIp\" %>", "user"=>"ec2-user"}, " ls\n", {"PublicIp"=>"127.0.0.1"})
|
244
250
|
.and_return(["file1\nfile2\n", "", 0])
|
245
251
|
|
246
252
|
client.instance_variable_get(:@post_processing)
|
@@ -345,9 +351,13 @@ end
|
|
345
351
|
process_status1 = make_double('process_status1') {|obj| obj.should_receive(:to_i).and_return(0) }
|
346
352
|
process_status2 = make_double('process_status2') {|obj| obj.should_receive(:to_i).and_return(0) }
|
347
353
|
|
348
|
-
|
354
|
+
client.instance_variable_get(:@post_processing)
|
355
|
+
.should_receive(:run_shell_command)
|
356
|
+
.with(" echo <%= Key \"AZ\" %>\n echo <%= Key \"Region\" %>\n", {"AZ"=>"ap-northeast-1b", "Region"=>"ap-northeast-1"})
|
349
357
|
.and_return(["ap-northeast-1b\nap-northeast-1\n", "", process_status1])
|
350
|
-
|
358
|
+
client.instance_variable_get(:@post_processing)
|
359
|
+
.should_receive(:run_shell_command)
|
360
|
+
.with(" echo <%= Key \"Region\" %>\n echo <%= Key \"AZ\" %>\n", {"AZ"=>"ap-northeast-1b", "Region"=>"ap-northeast-1"})
|
351
361
|
.and_return(["ap-northeast-1\nap-northeast-1b\n", "", process_status2])
|
352
362
|
|
353
363
|
client.instance_variable_get(:@post_processing)
|
@@ -141,9 +141,13 @@ end
|
|
141
141
|
process_status1 = make_double('process_status1') {|obj| obj.should_receive(:to_i).and_return(0) }
|
142
142
|
process_status2 = make_double('process_status2') {|obj| obj.should_receive(:to_i).and_return(0) }
|
143
143
|
|
144
|
-
|
144
|
+
client.instance_variable_get(:@post_processing)
|
145
|
+
.should_receive(:run_shell_command)
|
146
|
+
.with(" echo <%= Key \"AZ\" %>\n echo <%= Key \"Region\" %>\n", {"AZ"=>"ap-northeast-1b", "Region"=>"ap-northeast-1"})
|
145
147
|
.and_return(["ap-northeast-1b\nap-northeast-1\n", "", process_status1])
|
146
|
-
|
148
|
+
client.instance_variable_get(:@post_processing)
|
149
|
+
.should_receive(:run_shell_command)
|
150
|
+
.with(" echo <%= Key \"Region\" %>\n echo <%= Key \"AZ\" %>\n", {"AZ"=>"ap-northeast-1b", "Region"=>"ap-northeast-1"})
|
147
151
|
.and_return(["ap-northeast-1\nap-northeast-1b\n", "", process_status2])
|
148
152
|
|
149
153
|
client.instance_variable_get(:@post_processing)
|
@@ -232,7 +236,9 @@ end
|
|
232
236
|
|
233
237
|
cf.should_receive(:stacks) { stacks }
|
234
238
|
|
235
|
-
|
239
|
+
client.instance_variable_get(:@post_processing)
|
240
|
+
.should_receive(:run_ssh_command)
|
241
|
+
.with({"host"=>"<%= Key \"PublicIp\" %>", "user"=>"ec2-user"}, " ls\n", {"PublicIp"=>"127.0.0.1"})
|
236
242
|
.and_return(["file1\nfile2\n", "", 0])
|
237
243
|
|
238
244
|
client.instance_variable_get(:@post_processing)
|
@@ -336,9 +342,13 @@ end
|
|
336
342
|
process_status1 = make_double('process_status1') {|obj| obj.should_receive(:to_i).and_return(0) }
|
337
343
|
process_status2 = make_double('process_status2') {|obj| obj.should_receive(:to_i).and_return(0) }
|
338
344
|
|
339
|
-
|
345
|
+
client.instance_variable_get(:@post_processing)
|
346
|
+
.should_receive(:run_shell_command)
|
347
|
+
.with(" echo <%= Key \"AZ\" %>\n echo <%= Key \"Region\" %>\n", {"AZ"=>"ap-northeast-1b", "Region"=>"ap-northeast-1"})
|
340
348
|
.and_return(["ap-northeast-1b\nap-northeast-1\n", "", process_status1])
|
341
|
-
|
349
|
+
client.instance_variable_get(:@post_processing)
|
350
|
+
.should_receive(:run_shell_command)
|
351
|
+
.with(" echo <%= Key \"Region\" %>\n echo <%= Key \"AZ\" %>\n", {"AZ"=>"ap-northeast-1b", "Region"=>"ap-northeast-1"})
|
342
352
|
.and_return(["ap-northeast-1\nap-northeast-1b\n", "", process_status2])
|
343
353
|
|
344
354
|
client.instance_variable_get(:@post_processing)
|
@@ -0,0 +1,123 @@
|
|
1
|
+
describe Kumogata::StringStream do
|
2
|
+
it 'pass the line ("\n")' do
|
3
|
+
lines = []
|
4
|
+
|
5
|
+
sstream = Kumogata::StringStream.new do |line|
|
6
|
+
lines << line
|
7
|
+
end
|
8
|
+
|
9
|
+
sstream.push("chunk1")
|
10
|
+
sstream.push("chunk2\n")
|
11
|
+
sstream.push("chunk3")
|
12
|
+
sstream.push("chunk4")
|
13
|
+
sstream.push("chunk5\n")
|
14
|
+
sstream.push("\n")
|
15
|
+
sstream.push("\n")
|
16
|
+
sstream.push("chunk6")
|
17
|
+
sstream.push("chunk7")
|
18
|
+
sstream.close
|
19
|
+
|
20
|
+
expect(lines).to eq([
|
21
|
+
"chunk1chunk2",
|
22
|
+
"chunk3chunk4chunk5",
|
23
|
+
"",
|
24
|
+
"",
|
25
|
+
"chunk6chunk7",
|
26
|
+
])
|
27
|
+
end
|
28
|
+
|
29
|
+
it 'pass the line ("\r")' do
|
30
|
+
lines = []
|
31
|
+
|
32
|
+
sstream = Kumogata::StringStream.new do |line|
|
33
|
+
lines << line
|
34
|
+
end
|
35
|
+
|
36
|
+
sstream.push("chunk1")
|
37
|
+
sstream.push("chunk2\r")
|
38
|
+
sstream.push("chunk3")
|
39
|
+
sstream.push("chunk4")
|
40
|
+
sstream.push("chunk5\r")
|
41
|
+
sstream.push("\r")
|
42
|
+
sstream.push("\r")
|
43
|
+
sstream.push("chunk6")
|
44
|
+
sstream.push("chunk7")
|
45
|
+
sstream.close
|
46
|
+
|
47
|
+
expect(lines).to eq([
|
48
|
+
"chunk1chunk2",
|
49
|
+
"chunk3chunk4chunk5",
|
50
|
+
"",
|
51
|
+
"",
|
52
|
+
"chunk6chunk7",
|
53
|
+
])
|
54
|
+
end
|
55
|
+
|
56
|
+
it 'pass the line ("\r\n")' do
|
57
|
+
lines = []
|
58
|
+
|
59
|
+
sstream = Kumogata::StringStream.new do |line|
|
60
|
+
lines << line
|
61
|
+
end
|
62
|
+
|
63
|
+
sstream.push("chunk1")
|
64
|
+
sstream.push("chunk2\r\n")
|
65
|
+
sstream.push("chunk3")
|
66
|
+
sstream.push("chunk4")
|
67
|
+
sstream.push("chunk5\r\n")
|
68
|
+
sstream.push("\r\n")
|
69
|
+
sstream.push("\r\n")
|
70
|
+
sstream.push("chunk6")
|
71
|
+
sstream.push("chunk7")
|
72
|
+
sstream.close
|
73
|
+
|
74
|
+
expect(lines).to eq([
|
75
|
+
"chunk1chunk2",
|
76
|
+
"chunk3chunk4chunk5",
|
77
|
+
"",
|
78
|
+
"",
|
79
|
+
"chunk6chunk7",
|
80
|
+
])
|
81
|
+
end
|
82
|
+
|
83
|
+
it 'pass the line ("\n" / "\r" / "\r\n")' do
|
84
|
+
lines = []
|
85
|
+
|
86
|
+
sstream = Kumogata::StringStream.new do |line|
|
87
|
+
lines << line
|
88
|
+
end
|
89
|
+
|
90
|
+
sstream.push("chunk1")
|
91
|
+
sstream.push("chunk2\n")
|
92
|
+
sstream.push("chunk3")
|
93
|
+
sstream.push("chunk4")
|
94
|
+
sstream.push("chunk5\r")
|
95
|
+
sstream.push("\r\n")
|
96
|
+
sstream.push("\n")
|
97
|
+
sstream.push("chunk6")
|
98
|
+
sstream.push("chunk7")
|
99
|
+
sstream.push("chunk1")
|
100
|
+
sstream.push("chunk2\r")
|
101
|
+
sstream.push("chunk3")
|
102
|
+
sstream.push("chunk4")
|
103
|
+
sstream.push("chunk5\n\r")
|
104
|
+
sstream.push("\n")
|
105
|
+
sstream.push("\r")
|
106
|
+
sstream.push("chunk6")
|
107
|
+
sstream.push("chunk7")
|
108
|
+
sstream.close
|
109
|
+
|
110
|
+
expect(lines).to eq([
|
111
|
+
"chunk1chunk2",
|
112
|
+
"chunk3chunk4chunk5",
|
113
|
+
"",
|
114
|
+
"",
|
115
|
+
"chunk6chunk7chunk1chunk2",
|
116
|
+
"chunk3chunk4chunk5",
|
117
|
+
"",
|
118
|
+
"",
|
119
|
+
"",
|
120
|
+
"chunk6chunk7",
|
121
|
+
])
|
122
|
+
end
|
123
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: kumogata
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.3.
|
4
|
+
version: 0.3.14
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Genki Sugawara
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-03-
|
11
|
+
date: 2014-03-12 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: aws-sdk
|
@@ -231,6 +231,7 @@ files:
|
|
231
231
|
- lib/kumogata/ext/string_ext.rb
|
232
232
|
- lib/kumogata/logger.rb
|
233
233
|
- lib/kumogata/post_processing.rb
|
234
|
+
- lib/kumogata/string_stream.rb
|
234
235
|
- lib/kumogata/utils.rb
|
235
236
|
- lib/kumogata/version.rb
|
236
237
|
- packer/CentOS-6.4-x86_64-with_Updates-Asia_Pacific.json
|
@@ -250,6 +251,7 @@ files:
|
|
250
251
|
- spec/kumogata_update_spec.rb
|
251
252
|
- spec/kumogata_validate_spec.rb
|
252
253
|
- spec/spec_helper.rb
|
254
|
+
- spec/string_stream_spec.rb
|
253
255
|
homepage: https://github.com/winebarrel/kumogata
|
254
256
|
licenses:
|
255
257
|
- MIT
|
@@ -290,3 +292,4 @@ test_files:
|
|
290
292
|
- spec/kumogata_update_spec.rb
|
291
293
|
- spec/kumogata_validate_spec.rb
|
292
294
|
- spec/spec_helper.rb
|
295
|
+
- spec/string_stream_spec.rb
|