kumogata 0.4.11 → 0.4.12
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +59 -3
- data/lib/kumogata/client.rb +14 -0
- data/lib/kumogata/version.rb +1 -1
- data/spec/kumogata_create_spec.rb +92 -0
- data/spec/kumogata_update_spec.rb +90 -0
- data/spec/spec_helper.rb +6 -0
- metadata +2 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 60b666d69792655cd9d5f1ef9b67d8bc73aa1801
|
4
|
+
data.tar.gz: b40df1b37bad8bc10c9fa2f680324fad09ada144
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 0d1acf88ed630a8ecba7cfa15ac2b8503d128ee9dcb9617cfea4eba019f1047e1548bd4c84c26b1c4909846b782a547cd8c4d8477969b1f7fe746eb83538ef6b
|
7
|
+
data.tar.gz: 5647c1968838158a41bf6568842074cfeed764a8471737454ffe645f658eca9cfde5fb201252efa97cbe470753c97015d553c2afc00c433f1adb9a5ae8ae308d
|
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?
|
9
|
-
[![Build Status](https://drone.io/github.com/winebarrel/kumogata/status.png?
|
8
|
+
[![Gem Version](https://badge.fury.io/rb/kumogata.png?201404231403)](http://badge.fury.io/rb/kumogata)
|
9
|
+
[![Build Status](https://drone.io/github.com/winebarrel/kumogata/status.png?201404231403)](https://drone.io/github.com/winebarrel/kumogata/latest)
|
10
10
|
|
11
11
|
It can define a template in Ruby DSL, such as:
|
12
12
|
|
@@ -281,6 +281,32 @@ Resources do
|
|
281
281
|
end # Resources
|
282
282
|
```
|
283
283
|
|
284
|
+
## Iteration
|
285
|
+
|
286
|
+
You can use the Iteration in the template using `_(...)` method.
|
287
|
+
|
288
|
+
```ruby
|
289
|
+
Resources do
|
290
|
+
['instance1', 'instance2', 'instance3'].echo {|instance_name|
|
291
|
+
_(instance_name) do
|
292
|
+
Type "AWS::EC2::Instance"
|
293
|
+
Properties do
|
294
|
+
ImageId "ami-XXXXXXXX"
|
295
|
+
InstanceType { Ref "InstanceType" }
|
296
|
+
KeyName "your_key_name"
|
297
|
+
|
298
|
+
UserData (<<-EOS).undent.encode64
|
299
|
+
#!/bin/bash
|
300
|
+
yum install -y httpd
|
301
|
+
service httpd start
|
302
|
+
hostname #{instance_name}
|
303
|
+
EOS
|
304
|
+
end
|
305
|
+
end
|
306
|
+
}
|
307
|
+
end
|
308
|
+
```
|
309
|
+
|
284
310
|
## Post command
|
285
311
|
|
286
312
|
You can run shell/ssh commands after building servers using `_post()`.
|
@@ -340,7 +366,7 @@ Status: 0
|
|
340
366
|
|
341
367
|
## YAML template
|
342
368
|
|
343
|
-
You can also use the template
|
369
|
+
You can also use the YAML template instead of JSON and Ruby.
|
344
370
|
|
345
371
|
```yaml
|
346
372
|
---
|
@@ -384,6 +410,36 @@ Outputs:
|
|
384
410
|
|
385
411
|
$ kumogata convert Drupal_Single_Instance.template --output-format=yaml
|
386
412
|
|
413
|
+
## Outputs Filter
|
414
|
+
|
415
|
+
```ruby
|
416
|
+
Outputs do
|
417
|
+
MyPublicIp do
|
418
|
+
Value { Fn__GetAtt "MyInstance", "PublicIp" }
|
419
|
+
end
|
420
|
+
end
|
421
|
+
|
422
|
+
_outputs_filter do |output|
|
423
|
+
outputs["PublicIp"].gsub!('.', '_')
|
424
|
+
# PublicIp: XXX.XXX.XXX.XXX => XXX-XXX-XXX-XXX
|
425
|
+
end
|
426
|
+
|
427
|
+
_post do
|
428
|
+
...
|
429
|
+
end
|
430
|
+
```
|
431
|
+
|
432
|
+
## Configuration File
|
433
|
+
|
434
|
+
Kumogata supports [aws-cli configuration file](http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-waitcondition.html).
|
435
|
+
|
436
|
+
```
|
437
|
+
[default]
|
438
|
+
aws_access_key_id=AKIAIOSFODNN7EXAMPLE
|
439
|
+
aws_secret_access_key=wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY
|
440
|
+
aws_security_token=texample123324
|
441
|
+
```
|
442
|
+
|
387
443
|
## Demo
|
388
444
|
|
389
445
|
* Create resources
|
data/lib/kumogata/client.rb
CHANGED
@@ -15,6 +15,7 @@ class Kumogata::Client
|
|
15
15
|
add_encryption_password(template)
|
16
16
|
|
17
17
|
outputs = create_stack(template, stack_name)
|
18
|
+
filter_outputs(template, outputs)
|
18
19
|
@post_processing.run(:create, outputs)
|
19
20
|
|
20
21
|
outputs
|
@@ -58,6 +59,7 @@ class Kumogata::Client
|
|
58
59
|
add_encryption_password(template)
|
59
60
|
|
60
61
|
outputs = update_stack(template, stack_name)
|
62
|
+
filter_outputs(template, outputs)
|
61
63
|
@post_processing.run(:update, outputs)
|
62
64
|
|
63
65
|
outputs
|
@@ -262,6 +264,10 @@ class Kumogata::Client
|
|
262
264
|
@__hash__[path] = value
|
263
265
|
end
|
264
266
|
|
267
|
+
def _outputs_filter(&block)
|
268
|
+
@__hash__[:_outputs_filter] = block
|
269
|
+
end
|
270
|
+
|
265
271
|
def _post(options = {}, &block)
|
266
272
|
commands = Dslh::ScopeBlock.nest(binding, 'block')
|
267
273
|
|
@@ -618,4 +624,12 @@ EOS
|
|
618
624
|
raise "1 validation error detected: Value '#{stack_name}' at 'stackName' failed to satisfy constraint: Member must satisfy regular expression pattern: [a-zA-Z][-a-zA-Z0-9]*"
|
619
625
|
end
|
620
626
|
end
|
627
|
+
|
628
|
+
def filter_outputs(template, outputs)
|
629
|
+
if (_outputs_filter = template.delete(:_outputs_filter))
|
630
|
+
_outputs_filter.call(outputs)
|
631
|
+
end
|
632
|
+
|
633
|
+
return outputs
|
634
|
+
end
|
621
635
|
end
|
data/lib/kumogata/version.rb
CHANGED
@@ -262,6 +262,98 @@ end
|
|
262
262
|
end
|
263
263
|
end
|
264
264
|
|
265
|
+
it 'create a stack from Ruby template and run ssh command (modify outputs)' do
|
266
|
+
template = <<-TEMPLATE
|
267
|
+
Resources do
|
268
|
+
myEC2Instance do
|
269
|
+
Type "AWS::EC2::Instance"
|
270
|
+
Properties do
|
271
|
+
ImageId "ami-XXXXXXXX"
|
272
|
+
InstanceType "t1.micro"
|
273
|
+
end
|
274
|
+
end
|
275
|
+
end
|
276
|
+
|
277
|
+
Outputs do
|
278
|
+
PublicIp do
|
279
|
+
Value do
|
280
|
+
Fn__GetAtt "myEC2Instance", "PublicIp"
|
281
|
+
end
|
282
|
+
end
|
283
|
+
end
|
284
|
+
|
285
|
+
_outputs_filter do |outputs|
|
286
|
+
outputs['MyOutput'] = 100
|
287
|
+
end
|
288
|
+
|
289
|
+
_post do
|
290
|
+
ssh_command do
|
291
|
+
ssh do
|
292
|
+
host { Key "PublicIp" }
|
293
|
+
user "ec2-user"
|
294
|
+
end
|
295
|
+
command <<-EOS
|
296
|
+
ls
|
297
|
+
EOS
|
298
|
+
end
|
299
|
+
end
|
300
|
+
TEMPLATE
|
301
|
+
|
302
|
+
run_client(:create, :template => template) do |client, cf|
|
303
|
+
json = eval_template(template, :update_deletion_policy => true).to_json
|
304
|
+
client.should_receive(:print_event_log).twice
|
305
|
+
client.should_receive(:create_event_log).once
|
306
|
+
|
307
|
+
output = make_double('output') do |obj|
|
308
|
+
obj.should_receive(:key) { 'PublicIp' }
|
309
|
+
obj.should_receive(:value) { '127.0.0.1' }
|
310
|
+
end
|
311
|
+
|
312
|
+
resource_summary = make_double('resource_summary') do |obj|
|
313
|
+
obj.should_receive(:[]).with(:logical_resource_id) { 'myEC2Instance' }
|
314
|
+
obj.should_receive(:[]).with(:physical_resource_id) { 'i-XXXXXXXX' }
|
315
|
+
obj.should_receive(:[]).with(:resource_type) { 'AWS::EC2::Instance' }
|
316
|
+
obj.should_receive(:[]).with(:resource_status) { 'CREATE_COMPLETE' }
|
317
|
+
obj.should_receive(:[]).with(:resource_status_reason) { nil }
|
318
|
+
obj.should_receive(:[]).with(:last_updated_timestamp) { '2014-03-02 04:35:12 UTC' }
|
319
|
+
end
|
320
|
+
|
321
|
+
stack = make_double('stack') do |obj|
|
322
|
+
obj.should_receive(:status).and_return(
|
323
|
+
'CREATE_COMPLETE', 'CREATE_COMPLETE',
|
324
|
+
'DELETE_COMPLETE', 'DELETE_COMPLETE', 'DELETE_COMPLETE')
|
325
|
+
obj.should_receive(:outputs) { [output] }
|
326
|
+
obj.should_receive(:resource_summaries) { [resource_summary] }
|
327
|
+
obj.should_receive(:delete)
|
328
|
+
end
|
329
|
+
|
330
|
+
stacks = make_double('stacks') do |obj|
|
331
|
+
obj.should_receive(:create)
|
332
|
+
.with('kumogata-user-host-XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX', json, {}) { stack }
|
333
|
+
obj.should_receive(:[])
|
334
|
+
.with('kumogata-user-host-XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX') { stack }
|
335
|
+
end
|
336
|
+
|
337
|
+
cf.should_receive(:stacks).twice { stacks }
|
338
|
+
|
339
|
+
client.instance_variable_get(:@post_processing)
|
340
|
+
.should_receive(:run_ssh_command)
|
341
|
+
.with({"host"=>"<%= Key \"PublicIp\" %>", "user"=>"ec2-user", "request_pty"=>true}, " ls\n", {"PublicIp"=>"127.0.0.1", "MyOutput"=>100})
|
342
|
+
.and_return(["file1\nfile2\n", "", 0])
|
343
|
+
|
344
|
+
client.instance_variable_get(:@post_processing)
|
345
|
+
.should_receive(:print_command).with('ssh_command')
|
346
|
+
|
347
|
+
client.instance_variable_get(:@post_processing)
|
348
|
+
.should_receive(:print_command_result)
|
349
|
+
.with("file1\nfile2\n", "", 0)
|
350
|
+
|
351
|
+
client.instance_variable_get(:@post_processing)
|
352
|
+
.should_receive(:save_command_results)
|
353
|
+
.with([{'ssh_command' => {'ExitStatus' => 0, 'StdOut' => "file1\nfile2\n", 'StdErr' => ""}}])
|
354
|
+
end
|
355
|
+
end
|
356
|
+
|
265
357
|
it 'create a stack from Ruby template and run command (specifies timing)' do
|
266
358
|
template = <<-TEMPLATE
|
267
359
|
Resources do
|
@@ -299,6 +299,96 @@ end
|
|
299
299
|
end
|
300
300
|
end
|
301
301
|
|
302
|
+
it 'update a stack from Ruby template and run ssh command (modify outputs)' do
|
303
|
+
template = <<-TEMPLATE
|
304
|
+
Resources do
|
305
|
+
myEC2Instance do
|
306
|
+
Type "AWS::EC2::Instance"
|
307
|
+
Properties do
|
308
|
+
ImageId "ami-XXXXXXXX"
|
309
|
+
InstanceType "t1.micro"
|
310
|
+
end
|
311
|
+
end
|
312
|
+
end
|
313
|
+
|
314
|
+
Outputs do
|
315
|
+
PublicIp do
|
316
|
+
Value do
|
317
|
+
Fn__GetAtt "myEC2Instance", "PublicIp"
|
318
|
+
end
|
319
|
+
end
|
320
|
+
end
|
321
|
+
|
322
|
+
_outputs_filter do |outputs|
|
323
|
+
outputs['PublicIp'].gsub!('.', '-')
|
324
|
+
end
|
325
|
+
|
326
|
+
_post do
|
327
|
+
ssh_command do
|
328
|
+
after :update
|
329
|
+
ssh do
|
330
|
+
host { Key "PublicIp" }
|
331
|
+
user "ec2-user"
|
332
|
+
end
|
333
|
+
command <<-EOS
|
334
|
+
ls
|
335
|
+
EOS
|
336
|
+
end
|
337
|
+
end
|
338
|
+
TEMPLATE
|
339
|
+
|
340
|
+
run_client(:update, :arguments => ['MyStack'], :template => template) do |client, cf|
|
341
|
+
json = eval_template(template).to_json
|
342
|
+
client.should_receive(:print_event_log).once
|
343
|
+
client.should_receive(:create_event_log).once
|
344
|
+
|
345
|
+
output = make_double('output') do |obj|
|
346
|
+
obj.should_receive(:key) { 'PublicIp' }
|
347
|
+
obj.should_receive(:value) { '127.0.0.1' }
|
348
|
+
end
|
349
|
+
|
350
|
+
resource_summary = make_double('resource_summary') do |obj|
|
351
|
+
obj.should_receive(:[]).with(:logical_resource_id) { 'myEC2Instance' }
|
352
|
+
obj.should_receive(:[]).with(:physical_resource_id) { 'i-XXXXXXXX' }
|
353
|
+
obj.should_receive(:[]).with(:resource_type) { 'AWS::EC2::Instance' }
|
354
|
+
obj.should_receive(:[]).with(:resource_status) { 'UPDATE_COMPLETE' }
|
355
|
+
obj.should_receive(:[]).with(:resource_status_reason) { nil }
|
356
|
+
obj.should_receive(:[]).with(:last_updated_timestamp) { '2014-03-02 04:35:12 UTC' }
|
357
|
+
end
|
358
|
+
|
359
|
+
stack = make_double('stack') do |obj|
|
360
|
+
obj.should_receive(:update).with(:template => json)
|
361
|
+
obj.should_receive(:status).and_return(
|
362
|
+
'UPDATE_COMPLETE', 'UPDATE_COMPLETE', 'UPDATE_COMPLETE')
|
363
|
+
obj.should_receive(:outputs) { [output] }
|
364
|
+
obj.should_receive(:resource_summaries) { [resource_summary] }
|
365
|
+
end
|
366
|
+
|
367
|
+
stacks = make_double('stacks') do |obj|
|
368
|
+
obj.should_receive(:[])
|
369
|
+
.with('MyStack') { stack }
|
370
|
+
end
|
371
|
+
|
372
|
+
cf.should_receive(:stacks) { stacks }
|
373
|
+
|
374
|
+
client.instance_variable_get(:@post_processing)
|
375
|
+
.should_receive(:run_ssh_command)
|
376
|
+
.with({"host"=>"<%= Key \"PublicIp\" %>", "user"=>"ec2-user", "request_pty"=>true}, " ls\n", {"PublicIp"=>"127-0-0-1"})
|
377
|
+
.and_return(["file1\nfile2\n", "", 0])
|
378
|
+
|
379
|
+
client.instance_variable_get(:@post_processing)
|
380
|
+
.should_receive(:print_command).with('ssh_command')
|
381
|
+
|
382
|
+
client.instance_variable_get(:@post_processing)
|
383
|
+
.should_receive(:print_command_result)
|
384
|
+
.with("file1\nfile2\n", "", 0)
|
385
|
+
|
386
|
+
client.instance_variable_get(:@post_processing)
|
387
|
+
.should_receive(:save_command_results)
|
388
|
+
.with([{'ssh_command' => {'ExitStatus' => 0, 'StdOut' => "file1\nfile2\n", 'StdErr' => ""}}])
|
389
|
+
end
|
390
|
+
end
|
391
|
+
|
302
392
|
it 'update a stack from Ruby template and run command (specifies timing)' do
|
303
393
|
template = <<-TEMPLATE
|
304
394
|
Resources do
|
data/spec/spec_helper.rb
CHANGED
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.4.
|
4
|
+
version: 0.4.12
|
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-04-
|
11
|
+
date: 2014-04-23 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: aws-sdk
|
@@ -326,4 +326,3 @@ test_files:
|
|
326
326
|
- spec/kumogata_validate_spec.rb
|
327
327
|
- spec/spec_helper.rb
|
328
328
|
- spec/string_stream_spec.rb
|
329
|
-
has_rdoc:
|