kumogata 0.3.2 → 0.3.3

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: baf7b8cbddd815d7f08705918dcb9bba0f426345
4
- data.tar.gz: d8df685f3891d4266da07997a2926a4a33083dfc
3
+ metadata.gz: 67a5c56f5378acd9da8583d197a558cca8b0d2fb
4
+ data.tar.gz: 53facba7232603a24adbb060ca8a534035033609
5
5
  SHA512:
6
- metadata.gz: 7b36d2411bdd49f4b2031efa2c45fd4f8fbd30591857c85098b1f004805b6e5cbe6615fccbfa998cc5e62becd5bd3a2324adbaf211848df68c19f7341097da94
7
- data.tar.gz: 0ad0e636569b330cb22849a41c2728c0b2419767d170e26225633069274b6cdb0b01a00be168003e2f066bbf4bd02ba2a5eb90362be0f61975115196aeb9908c
6
+ metadata.gz: 7f442adbf70667594dfee27379892ffb7a1d7334577c4e4f57e91aaa1204c0f8fce5e058dbb5b213c88b24d480da4e2ff4f2b5bd016b6a647535ecfa6e0ee411
7
+ data.tar.gz: 0484a0ac808e3cb894bb92b1890e8e49005bd20024b62c1e16ec1ac1e68562324ef13d2976e98eb91395bea91c3093348f23aaad1da69370908796ef29778a88
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?201403082134)](http://badge.fury.io/rb/kumogata)
9
- [![Build Status](https://drone.io/github.com/winebarrel/kumogata/status.png?201403082134)](https://drone.io/github.com/winebarrel/kumogata/latest)
8
+ [![Gem Version](https://badge.fury.io/rb/kumogata.png?201403091705)](http://badge.fury.io/rb/kumogata)
9
+ [![Build Status](https://drone.io/github.com/winebarrel/kumogata/status.png?201403091705)](https://drone.io/github.com/winebarrel/kumogata/latest)
10
10
 
11
11
  It can define a template in Ruby DSL, such as:
12
12
 
@@ -80,6 +80,7 @@ Options:
80
80
  -k, --access-key ACCESS_KEY
81
81
  -s, --secret-key SECRET_KEY
82
82
  -r, --region REGION
83
+ --format TMPLATE_FORMAT
83
84
  --skip-replace-underscore
84
85
  --deletion-policy-retain
85
86
  -p, --parameters KEY_VALUES
@@ -76,24 +76,25 @@ class Kumogata::ArgumentParser
76
76
  update_usage(opt)
77
77
 
78
78
  begin
79
- opt.on('-k', '--access-key ACCESS_KEY') {|v| options[:access_key_id] = v }
80
- opt.on('-s', '--secret-key SECRET_KEY') {|v| options[:secret_access_key] = v }
81
- opt.on('-r', '--region REGION') {|v| options[:region] = v }
82
- opt.on('' , '--skip-replace-underscore') { options[:replace_underscore] = false }
83
- opt.on('' , '--deletion-policy-retain') { options[:deletion_policy_retain] = true }
84
- opt.on('-p', '--parameters KEY_VALUES', Array) {|v| options[:parameters] = v }
85
- opt.on('-e', '--encrypt-parameters KEYS', Array) {|v| options[:encrypt_parameters] = v }
86
- opt.on('', '--encryption-password PASS') {|v| options[:encryption_password] = v }
87
- opt.on('', '--skip-send-password') { options[:skip_send_password] = true }
88
- opt.on('' , '--capabilities CAPABILITIES', Array) {|v| options[:capabilities] = v }
89
- opt.on('' , '--disable-rollback') { options[:disable_rollback] = true }
90
- opt.on('' , '--notify SNS_TOPICS', Array) {|v| options[:notify] = v }
91
- opt.on('' , '--timeout MINUTES', Integer) {|v| options[:timeout] = v }
92
- opt.on('' , '--result-log PATH') {|v| options[:result_log] = v }
93
- opt.on('' , '--force') { options[:force] = true }
94
- opt.on('-w', '--ignore-all-space') { options[:ignore_all_space] = true }
95
- opt.on('' , '--no-color') { options[:color] = false }
96
- opt.on('' , '--debug') { options[:debug] = true }
79
+ opt.on('-k', '--access-key ACCESS_KEY') {|v| options[:access_key_id] = v }
80
+ opt.on('-s', '--secret-key SECRET_KEY') {|v| options[:secret_access_key] = v }
81
+ opt.on('-r', '--region REGION') {|v| options[:region] = v }
82
+ opt.on('' , '--format TMPLATE_FORMAT', [:ruby, :json]) {|v| options[:format] = v }
83
+ opt.on('' , '--skip-replace-underscore') { options[:replace_underscore] = false }
84
+ opt.on('' , '--deletion-policy-retain') { options[:deletion_policy_retain] = true }
85
+ opt.on('-p', '--parameters KEY_VALUES', Array) {|v| options[:parameters] = v }
86
+ opt.on('-e', '--encrypt-parameters KEYS', Array) {|v| options[:encrypt_parameters] = v }
87
+ opt.on('', '--encryption-password PASS') {|v| options[:encryption_password] = v }
88
+ opt.on('', '--skip-send-password') { options[:skip_send_password] = true }
89
+ opt.on('' , '--capabilities CAPABILITIES', Array) {|v| options[:capabilities] = v }
90
+ opt.on('' , '--disable-rollback') { options[:disable_rollback] = true }
91
+ opt.on('' , '--notify SNS_TOPICS', Array) {|v| options[:notify] = v }
92
+ opt.on('' , '--timeout MINUTES', Integer) {|v| options[:timeout] = v }
93
+ opt.on('' , '--result-log PATH') {|v| options[:result_log] = v }
94
+ opt.on('' , '--force') { options[:force] = true }
95
+ opt.on('-w', '--ignore-all-space') { options[:ignore_all_space] = true }
96
+ opt.on('' , '--no-color') { options[:color] = false }
97
+ opt.on('' , '--debug') { options[:debug] = true }
97
98
  opt.parse!
98
99
 
99
100
  unless (command = ARGV.shift)
@@ -107,11 +107,16 @@ class Kumogata::Client
107
107
  private ###########################################################
108
108
 
109
109
  def open_template(path_or_url)
110
+ format = @options.format || (ruby_template?(path_or_url) ? :ruby : :json)
111
+
110
112
  open(path_or_url) do |f|
111
- if ruby_template?(path_or_url)
113
+ case format
114
+ when :ruby
112
115
  evaluate_template(f)
113
- else
116
+ when :json
114
117
  JSON.parse(f.read)
118
+ else
119
+ raise "Unknown format: #{format}"
115
120
  end
116
121
  end
117
122
  end
@@ -324,16 +329,41 @@ class Kumogata::Client
324
329
  end
325
330
 
326
331
  def while_in_progress(stack, complete_status)
332
+ event_log = {}
333
+
327
334
  while stack.status =~ /_IN_PROGRESS\Z/
328
- print '.'.intense_black unless @options.debug?
335
+ print_event_log(stack, event_log)
329
336
  sleep 1
330
337
  end
331
338
 
339
+ print_event_log(stack, event_log)
332
340
  completed = (stack.status == complete_status)
333
341
  Kumogata.logger.info(completed ? 'Successfully' : 'Failed')
334
342
  return completed
335
343
  end
336
344
 
345
+ def print_event_log(stack, event_log)
346
+ events_for(stack).sort_by {|i| i['Timestamp'] }.each do |event|
347
+ event_id = event['EventId']
348
+
349
+ unless event_log[event_id]
350
+ event_log[event_id] = event
351
+
352
+ timestamp = event['Timestamp']
353
+ summary = {}
354
+
355
+ ['LogicalResourceId', 'ResourceStatus', 'ResourceStatusReason'].map do |k|
356
+ summary[k] = event[k]
357
+ end
358
+
359
+ puts [
360
+ timestamp.getlocal.strftime('%Y/%m/%d %H:%M:%S %Z'),
361
+ summary.to_json.colorize_as(:json),
362
+ ].join(': ')
363
+ end
364
+ end
365
+ end
366
+
337
367
  def build_create_options
338
368
  opts = {}
339
369
  add_parameters(opts)
@@ -377,7 +407,7 @@ class Kumogata::Client
377
407
  def update_deletion_policy(template)
378
408
  if @options.delete_stack? or @options.deletion_policy_retain?
379
409
  template['Resources'].each do |k, v|
380
- v['DeletionPolicy'] = 'Retain'
410
+ v['DeletionPolicy'] ||= 'Retain'
381
411
  end
382
412
  end
383
413
  end
@@ -1,3 +1,3 @@
1
1
  module Kumogata
2
- VERSION = '0.3.2'
2
+ VERSION = '0.3.3'
3
3
  end
@@ -22,6 +22,69 @@ end
22
22
 
23
23
  run_client(:create, :template => template) do |client, cf|
24
24
  json = eval_template(template, :update_deletion_policy => true).to_json
25
+ client.should_receive(:print_event_log).twice
26
+
27
+ output = make_double('output') do |obj|
28
+ obj.should_receive(:key) { 'AZ' }
29
+ obj.should_receive(:value) { 'ap-northeast-1b' }
30
+ end
31
+
32
+ resource_summary = make_double('resource_summary') do |obj|
33
+ obj.should_receive(:[]).with(:logical_resource_id) { 'myEC2Instance' }
34
+ obj.should_receive(:[]).with(:physical_resource_id) { 'i-XXXXXXXX' }
35
+ obj.should_receive(:[]).with(:resource_type) { 'AWS::EC2::Instance' }
36
+ obj.should_receive(:[]).with(:resource_status) { 'CREATE_COMPLETE' }
37
+ obj.should_receive(:[]).with(:resource_status_reason) { nil }
38
+ obj.should_receive(:[]).with(:last_updated_timestamp) { '2014-03-02 04:35:12 UTC' }
39
+ end
40
+
41
+ stack = make_double('stack') do |obj|
42
+ obj.should_receive(:status).and_return(
43
+ 'CREATE_COMPLETE', 'CREATE_COMPLETE',
44
+ 'DELETE_COMPLETE', 'DELETE_COMPLETE', 'DELETE_COMPLETE')
45
+ obj.should_receive(:outputs) { [output] }
46
+ obj.should_receive(:resource_summaries) { [resource_summary] }
47
+ obj.should_receive(:delete)
48
+ end
49
+
50
+ stacks = make_double('stacks') do |obj|
51
+ obj.should_receive(:create)
52
+ .with('kumogata-user-host-XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX', json, {}) { stack }
53
+ obj.should_receive(:[])
54
+ .with('kumogata-user-host-XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX') { stack }
55
+ end
56
+
57
+ cf.should_receive(:stacks).twice { stacks }
58
+ end
59
+ end
60
+
61
+ it 'create a stack from Ruby template (include DeletionPolicy)' do
62
+ template = <<-EOS
63
+ Resources do
64
+ myEC2Instance do
65
+ Type "AWS::EC2::Instance"
66
+ Properties do
67
+ ImageId "ami-XXXXXXXX"
68
+ InstanceType "t1.micro"
69
+ end
70
+ DeletionPolicy "Delete"
71
+ end
72
+ end
73
+
74
+ Outputs do
75
+ AZ do
76
+ Value do
77
+ Fn__GetAtt "myEC2Instance", "AvailabilityZone"
78
+ end
79
+ end
80
+ end
81
+ EOS
82
+
83
+ run_client(:create, :template => template) do |client, cf|
84
+ template = eval_template(template, :update_deletion_policy => true)
85
+ expect(template['Resources']['myEC2Instance']['DeletionPolicy']).to eq('Delete')
86
+ json = template.to_json
87
+ client.should_receive(:print_event_log).twice
25
88
 
26
89
  output = make_double('output') do |obj|
27
90
  obj.should_receive(:key) { 'AZ' }
@@ -88,6 +151,7 @@ end
88
151
 
89
152
  run_client(:create, :template => template, :options => {:parameters => {'InstanceType'=>'m1.large'}}) do |client, cf|
90
153
  json = eval_template(template, :update_deletion_policy => true).to_json
154
+ client.should_receive(:print_event_log).twice
91
155
 
92
156
  output = make_double('output') do |obj|
93
157
  obj.should_receive(:key) { 'AZ' }
@@ -146,6 +210,7 @@ end
146
210
 
147
211
  run_client(:create, :arguments => ['MyStack'], :template => template) do |client, cf|
148
212
  json = eval_template(template).to_json
213
+ client.should_receive(:print_event_log).once
149
214
 
150
215
  output = make_double('output') do |obj|
151
216
  obj.should_receive(:key) { 'AZ' }
@@ -201,6 +266,7 @@ end
201
266
 
202
267
  run_client(:create, :arguments => ['MyStack'], :template => template, :options => {:deletion_policy_retain => true}) do |client, cf|
203
268
  json = eval_template(template, :update_deletion_policy => true).to_json
269
+ client.should_receive(:print_event_log).once
204
270
 
205
271
  output = make_double('output') do |obj|
206
272
  obj.should_receive(:key) { 'AZ' }
@@ -290,6 +356,7 @@ end
290
356
 
291
357
  run_client(:create, :template => template, :options => {:parameters => {'InstanceType'=>'m1.large'}, :encrypt_parameters => ['Password']}) do |client, cf|
292
358
  json = eval_template(template, :update_deletion_policy => true, :add_encryption_password => true).to_json
359
+ client.should_receive(:print_event_log).twice
293
360
 
294
361
  output = make_double('output') do |obj|
295
362
  obj.should_receive(:key) { 'AZ' }
@@ -1,6 +1,8 @@
1
1
  describe 'Kumogata::Client#delete' do
2
2
  it 'update a stack from Ruby template' do
3
3
  run_client(:delete, :arguments => ['MyStack'], :options => {:force => true}) do |client, cf|
4
+ client.should_receive(:print_event_log).once
5
+
4
6
  stack = make_double('stack') do |obj|
5
7
  obj.should_receive(:delete).with(no_args())
6
8
  obj.should_receive(:status).and_return(
@@ -22,6 +22,7 @@ end
22
22
 
23
23
  run_client(:update, :arguments => ['MyStack'], :template => template) do |client, cf|
24
24
  json = eval_template(template).to_json
25
+ client.should_receive(:print_event_log).once
25
26
 
26
27
  output = make_double('output') do |obj|
27
28
  obj.should_receive(:key) { 'AZ' }
@@ -85,6 +86,7 @@ end
85
86
 
86
87
  run_client(:update, :arguments => ['MyStack'], :template => template, :options => {:parameters => {'InstanceType'=>'m1.large'}}) do |client, cf|
87
88
  json = eval_template(template).to_json
89
+ client.should_receive(:print_event_log).once
88
90
 
89
91
  output = make_double('output') do |obj|
90
92
  obj.should_receive(:key) { 'AZ' }
@@ -173,6 +175,7 @@ end
173
175
 
174
176
  run_client(:update, :arguments => ['MyStack'], :template => template, :options => {:parameters => {'InstanceType'=>'m1.large'}, :encrypt_parameters => ['Password']}) do |client, cf|
175
177
  json = eval_template(template, :add_encryption_password => true).to_json
178
+ client.should_receive(:print_event_log).once
176
179
 
177
180
  output = make_double('output') do |obj|
178
181
  obj.should_receive(:key) { 'AZ' }
data/spec/spec_helper.rb CHANGED
@@ -80,7 +80,7 @@ end
80
80
 
81
81
  def update_deletion_policy(template)
82
82
  template['Resources'].each do |k, v|
83
- v['DeletionPolicy'] = 'Retain'
83
+ v['DeletionPolicy'] ||= 'Retain'
84
84
  end
85
85
  end
86
86
 
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.2
4
+ version: 0.3.3
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-08 00:00:00.000000000 Z
11
+ date: 2014-03-09 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: aws-sdk