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 CHANGED
@@ -1,15 +1,15 @@
1
1
  ---
2
2
  !binary "U0hBMQ==":
3
3
  metadata.gz: !binary |-
4
- ZDVkOTFjYWZhMzc2OTdhYjlkM2RlYWY3ZDI4MjcyYzNjYmZlN2NhYQ==
4
+ NWY1ZGU1ZTExOTU3MWMyMmYwNGViNGVkNTc0ZGI3OTkxMzI2NTRkNA==
5
5
  data.tar.gz: !binary |-
6
- MmYyNjA2YjZkZTZjNzJkZDljOWQzNjU2NzNkMDgwYjQ3MzBiN2Q5Nw==
6
+ NjE4MjUwNWQ5ZjQ0Njg5YzUzNDYxZDQwOTIzNTdjZmFlZGViM2RjNQ==
7
7
  SHA512:
8
8
  metadata.gz: !binary |-
9
- NDBjZDk1YTY2YTZkMDM1YjkzMDE1ZDU3ZDdiOTZlNTFhYWY4NGQ3YmY1OGNk
10
- YmMwZDc5Yzc3MmI0MTExNzU0ZTNhYTQ0MTI2ZTFlZWJhYTg5MzcyZjY2ZjJm
11
- NmZhYjQ2ZWMyMjU3OGUxMTA3MThlNzdmNjk4ODhlYjQ2YmE5NmQ=
9
+ YjE1YzNkYWJmMTcwZTNiMjdmMjZhMWUwNDc2ZDJkOWQzYjgwOTRlMDY3NTM4
10
+ NWQzZTYxM2U5OTY1NjgwMGE3MWI5YjRmYmRmZjI3OGM4MTJlMzdhOTJkZmFm
11
+ OGIzNTc3NTliMjYzMjVlNzYxOWE5Y2Y2YTJlMDZlYjNjMDVjMDc=
12
12
  data.tar.gz: !binary |-
13
- MTRiY2EzMDIyYjBkZDdhNmYyOTgwZTM1ZDg3ZWEzMjc3MGViMmY0NjhlMzE1
14
- NTExMjFmNmI4ZmUzM2M2MWFkZmNlY2MyODI3ODY1MjI0Yzk4Y2JiZDZiMDFm
15
- NWM0MmVkMjljMGNjYTNmNDViNWRhYjIyNDYwNDgzMzAxNDNmNTI=
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
- [![Gem Version](https://badge.fury.io/rb/kumogata.png?201403111456)](http://badge.fury.io/rb/kumogata)
9
- [![Build Status](https://drone.io/github.com/winebarrel/kumogata/status.png?201403111456)](https://drone.io/github.com/winebarrel/kumogata/latest)
8
+ [![Gem Version](https://badge.fury.io/rb/kumogata.png?201403121243)](http://badge.fury.io/rb/kumogata)
9
+ [![Build Status](https://drone.io/github.com/winebarrel/kumogata/status.png?201403121243)](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
- retryable(:tries => connect_tries, :on => Net::SSH::Disconnect, :sleep => retry_interval) do
140
- Net::SSH.start(*args) {|ssh| ssh_exec!(ssh, command) }
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
- rescue Net::SSH::HostKeyMismatch => e
143
- e.remember_host!
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
- Open3.capture3(command)
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 print_command_result(out, err, status)
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
@@ -1,3 +1,3 @@
1
1
  module Kumogata
2
- VERSION = '0.3.13'
2
+ VERSION = '0.3.14'
3
3
  end
@@ -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
- Open3.should_receive(:capture3).with("echo ap-northeast-1b\necho ap-northeast-1\n")
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
- Open3.should_receive(:capture3).with("echo ap-northeast-1\necho ap-northeast-1b\n")
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
- Net::SSH.should_receive(:start).with("127.0.0.1", "ec2-user")
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
- Open3.should_receive(:capture3).with("echo ap-northeast-1b\necho ap-northeast-1\n")
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
- Open3.should_receive(:capture3).with("echo ap-northeast-1\necho ap-northeast-1b\n")
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
- Open3.should_receive(:capture3).with("echo ap-northeast-1b\necho ap-northeast-1\n")
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
- Open3.should_receive(:capture3).with("echo ap-northeast-1\necho ap-northeast-1b\n")
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
- Net::SSH.should_receive(:start).with("127.0.0.1", "ec2-user")
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
- Open3.should_receive(:capture3).with("echo ap-northeast-1b\necho ap-northeast-1\n")
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
- Open3.should_receive(:capture3).with("echo ap-northeast-1\necho ap-northeast-1b\n")
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.13
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 00:00:00.000000000 Z
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