kumogata 0.4.11 → 0.4.12
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 +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
|
-
[](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
|
|
@@ -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:
|