kumogata 0.2.12 → 0.2.13
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 +13 -5
- data/README.md +59 -2
- data/bin/kumogata +8 -8
- data/lib/kumogata/argument_parser.rb +51 -16
- data/lib/kumogata/client.rb +47 -10
- data/lib/kumogata/crypt.rb +32 -0
- data/lib/kumogata/ext/coderay_ext.rb +18 -0
- data/lib/kumogata/version.rb +1 -1
- data/lib/kumogata.rb +2 -16
- data/spec/kumogata_create_spec.rb +93 -1
- data/spec/kumogata_crypt_spec.rb +19 -0
- data/spec/kumogata_show_events_spec.rb +0 -2
- data/spec/kumogata_update_spec.rb +89 -1
- data/spec/spec_helper.rb +14 -0
- metadata +33 -30
checksums.yaml
CHANGED
@@ -1,7 +1,15 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
|
2
|
+
!binary "U0hBMQ==":
|
3
|
+
metadata.gz: !binary |-
|
4
|
+
MjUxM2NjNThmOTI1OTdlMmNlZTAyNjg5NzAwMjg4ZTViYzU5Mjk5NA==
|
5
|
+
data.tar.gz: !binary |-
|
6
|
+
ZmNlYWU3YTg2YjBkZDhkNzBkYTZmZTEyYzlhNzI2ZmJkMjU1NDQ0Zg==
|
5
7
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
|
8
|
+
metadata.gz: !binary |-
|
9
|
+
YjcxOGQxMjBmYTc2MTEwYjk0ZDMxNjgwMmNhNGNlMjJkYWI1YzE5YzRjNzlm
|
10
|
+
MDE1OTUwYTliZmM2NTcyNGMyYmM1MmExYjI2OTZkYzNiMThjYWRjMTMzMTNm
|
11
|
+
YzNmMWQ4ODRiNTliMDI5ZDI4OTQzOTk0ZjFjZmYzZWJkYWU1MTQ=
|
12
|
+
data.tar.gz: !binary |-
|
13
|
+
YmU1MzdmMGE3YTYyMzE3NzJhZjhjYjYwYzY0MGQzYjIzNjM0MzY4YTAxYzVj
|
14
|
+
NjAzY2MwNDFhNGVlNGFjODY1YjQ0MzM2N2ZhMjAzMmFkMjNmY2I2YmJjZmY0
|
15
|
+
Y2QzYjk0NzY1ZTBhYTM2ODY1ZTM3MzBiYjM2ZWZlNmYzZjQ3ZDk=
|
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
|
|
@@ -83,6 +83,9 @@ Options:
|
|
83
83
|
--skip-replace-underscore
|
84
84
|
--skip-delete-stack
|
85
85
|
-p, --parameters KEY_VALUES
|
86
|
+
-e, --encrypt-parameters KEYS
|
87
|
+
--encryption-password PASS
|
88
|
+
--skip-send-password
|
86
89
|
--capabilities CAPABILITIES
|
87
90
|
--disable-rollback
|
88
91
|
--notify SNS_TOPICS
|
@@ -208,6 +211,60 @@ end
|
|
208
211
|
}
|
209
212
|
```
|
210
213
|
|
214
|
+
### Encrypt parameters
|
215
|
+
|
216
|
+
* Command line
|
217
|
+
|
218
|
+
$ kumogata create template.rb -e 'Password1,Password2' -p 'Param1=xxx,Param2=xxx,Password1=xxx,Password2=xxx'
|
219
|
+
|
220
|
+
* Template
|
221
|
+
|
222
|
+
```ruby
|
223
|
+
Parameters do
|
224
|
+
Param1 { Type "String" }
|
225
|
+
Param2 { Type "String" }
|
226
|
+
Password1 { Type "String"; NoEcho true }
|
227
|
+
Password2 { Type "String"; NoEcho true }
|
228
|
+
end # Parameters
|
229
|
+
|
230
|
+
Resources do
|
231
|
+
myEC2Instance do
|
232
|
+
Type "AWS::EC2::Instance"
|
233
|
+
|
234
|
+
Properties do
|
235
|
+
ImageId "ami-XXXXXXXX"
|
236
|
+
|
237
|
+
UserData do
|
238
|
+
Fn__Base64 (<<-EOS).fn_join
|
239
|
+
#!/bin/bash
|
240
|
+
/opt/aws/bin/cfn-init -s <%= Ref "AWS::StackName" %> -r myEC2Instance --region <%= Ref "AWS::Region" %>
|
241
|
+
EOS
|
242
|
+
end
|
243
|
+
end
|
244
|
+
|
245
|
+
Metadata do
|
246
|
+
AWS__CloudFormation__Init do
|
247
|
+
config do
|
248
|
+
commands do
|
249
|
+
any_command do
|
250
|
+
command (<<-EOS).fn_join
|
251
|
+
ENCRYPTION_PASSWORD="`echo <%= Ref Kumogata::ENCRYPTION_PASSWORD %> | base64 -d`"
|
252
|
+
|
253
|
+
# Decrypt Password1
|
254
|
+
echo '<%= Ref "Password1" %>' | base64 -d | openssl enc -d -aes256 -pass pass:"$ENCRYPTION_PASSWORD" > password1
|
255
|
+
|
256
|
+
# Decrypt Password2
|
257
|
+
echo '<%= Ref "Password2" %>' | base64 -d | openssl enc -d -aes256 -pass pass:"$ENCRYPTION_PASSWORD" > password2
|
258
|
+
EOS
|
259
|
+
end
|
260
|
+
end
|
261
|
+
end
|
262
|
+
end
|
263
|
+
end
|
264
|
+
end # myEC2Instance
|
265
|
+
end # Resources
|
266
|
+
```
|
267
|
+
|
211
268
|
## Demo
|
212
269
|
|
213
270
|
* Create resources
|
data/bin/kumogata
CHANGED
@@ -5,15 +5,15 @@ require 'kumogata'
|
|
5
5
|
|
6
6
|
options = nil
|
7
7
|
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
}
|
8
|
+
parsed = Kumogata::ArgumentParser.parse! {|parser, cmd, args, opts|
|
9
|
+
if (opts.access_key_id? and not opts.secret_access_key?) or
|
10
|
+
(not opts.access_key_id? and opts.secret_access_key?)
|
11
|
+
puts parser.help
|
12
|
+
exit 1
|
13
|
+
end
|
14
|
+
}
|
16
15
|
|
16
|
+
begin
|
17
17
|
command, arguments, options = parsed
|
18
18
|
|
19
19
|
aws_opts = {}
|
@@ -1,6 +1,11 @@
|
|
1
1
|
Version = Kumogata::VERSION
|
2
2
|
|
3
|
+
module Kumogata
|
4
|
+
ENCRYPTION_PASSWORD = 'EncryptionPassword'
|
5
|
+
end
|
6
|
+
|
3
7
|
class Kumogata::ArgumentParser
|
8
|
+
|
4
9
|
DEFAULT_OPTIONS = {
|
5
10
|
:replace_underscore => true,
|
6
11
|
:delete_stack => true,
|
@@ -71,21 +76,24 @@ class Kumogata::ArgumentParser
|
|
71
76
|
update_usage(opt)
|
72
77
|
|
73
78
|
begin
|
74
|
-
opt.on('-k', '--access-key ACCESS_KEY') {|v| options[:access_key_id]
|
75
|
-
opt.on('-s', '--secret-key SECRET_KEY') {|v| options[:secret_access_key]
|
76
|
-
opt.on('-r', '--region REGION') {|v| options[:region]
|
77
|
-
opt.on('' , '--skip-replace-underscore') { options[:replace_underscore]
|
78
|
-
opt.on('' , '--skip-delete-stack') { options[:delete_stack]
|
79
|
-
opt.on('-p', '--parameters KEY_VALUES', Array) {|v| options[:parameters]
|
80
|
-
opt.on(''
|
81
|
-
opt.on(''
|
82
|
-
opt.on(''
|
83
|
-
opt.on('' , '--
|
84
|
-
opt.on('' , '--
|
85
|
-
opt.on('' , '--
|
86
|
-
opt.on('
|
87
|
-
opt.on('' , '--
|
88
|
-
opt.on('' , '--
|
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('' , '--skip-delete-stack') { options[:delete_stack] = false }
|
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 }
|
89
97
|
opt.parse!
|
90
98
|
|
91
99
|
unless (command = ARGV.shift)
|
@@ -108,8 +116,13 @@ class Kumogata::ArgumentParser
|
|
108
116
|
if block_given?
|
109
117
|
yield(opt, command, arguments, options)
|
110
118
|
end
|
119
|
+
|
120
|
+
if options.parameters?
|
121
|
+
update_parameters(options)
|
122
|
+
end
|
111
123
|
rescue => e
|
112
124
|
$stderr.puts("#{e.message}")
|
125
|
+
raise e if options[:debug]
|
113
126
|
exit 1
|
114
127
|
end
|
115
128
|
end
|
@@ -128,8 +141,8 @@ class Kumogata::ArgumentParser
|
|
128
141
|
cmd_max = COMMANDS.keys.map {|i| i.to_s.length }.max
|
129
142
|
|
130
143
|
cmd_arg_descs = COMMANDS.map {|command, attributes|
|
131
|
-
arguments = attributes[:arguments]
|
132
144
|
description = attributes[:description]
|
145
|
+
arguments = attributes[:arguments]
|
133
146
|
|
134
147
|
[
|
135
148
|
'%-*s %s' % [cmd_max, command, arguments_to_message(arguments)],
|
@@ -161,4 +174,26 @@ class Kumogata::ArgumentParser
|
|
161
174
|
def arguments_to_message(arguments)
|
162
175
|
arguments.map {|i| i.to_s.sub(/(.+)\?\Z/) { "[#{$1}]" }.upcase }.join(' ')
|
163
176
|
end
|
177
|
+
|
178
|
+
def update_parameters(options)
|
179
|
+
parameters = {}
|
180
|
+
passwd = options.encryption_password || Kumogata::Crypt.mkpasswd(16)
|
181
|
+
enc_params = options.encrypt_parameters
|
182
|
+
|
183
|
+
options.parameters.each do |i|
|
184
|
+
key, value = i.split('=', 2)
|
185
|
+
|
186
|
+
if enc_params and (enc_params.include?('*') or enc_params.include?(key))
|
187
|
+
value = Kumogata::Crypt.encrypt(passwd, value)
|
188
|
+
end
|
189
|
+
|
190
|
+
parameters[key] = value
|
191
|
+
end
|
192
|
+
|
193
|
+
options.parameters = parameters
|
194
|
+
|
195
|
+
if options.encrypt_parameters? and not options.skip_send_password?
|
196
|
+
options.parameters[Kumogata::ENCRYPTION_PASSWORD] = passwd.encode64
|
197
|
+
end
|
198
|
+
end
|
164
199
|
end
|
data/lib/kumogata/client.rb
CHANGED
@@ -6,15 +6,12 @@ class Kumogata::Client
|
|
6
6
|
end
|
7
7
|
|
8
8
|
def create(path_or_url, stack_name = nil)
|
9
|
+
validate_stack_name(stack_name)
|
10
|
+
|
9
11
|
@options.delete_stack = false if stack_name
|
10
12
|
template = open_template(path_or_url)
|
11
|
-
|
12
|
-
|
13
|
-
template['Resources'].each do |k, v|
|
14
|
-
v['DeletionPolicy'] = 'Retain'
|
15
|
-
end
|
16
|
-
end
|
17
|
-
|
13
|
+
update_deletion_policy(template)
|
14
|
+
add_encryption_password(template)
|
18
15
|
create_stack(template, stack_name)
|
19
16
|
nil
|
20
17
|
end
|
@@ -36,15 +33,20 @@ class Kumogata::Client
|
|
36
33
|
end
|
37
34
|
|
38
35
|
def update(path_or_url, stack_name)
|
36
|
+
validate_stack_name(stack_name)
|
37
|
+
|
39
38
|
template = open(path_or_url) do |f|
|
40
39
|
evaluate_template(f)
|
41
40
|
end
|
42
41
|
|
42
|
+
add_encryption_password(template)
|
43
43
|
update_stack(template, stack_name)
|
44
44
|
nil
|
45
45
|
end
|
46
46
|
|
47
47
|
def delete(stack_name)
|
48
|
+
validate_stack_name(stack_name)
|
49
|
+
|
48
50
|
if @options.force? or agree("Are you sure you want to delete `#{stack_name}`? ".yellow)
|
49
51
|
delete_stack(stack_name)
|
50
52
|
end
|
@@ -53,26 +55,36 @@ class Kumogata::Client
|
|
53
55
|
end
|
54
56
|
|
55
57
|
def list(stack_name = nil)
|
58
|
+
validate_stack_name(stack_name)
|
59
|
+
|
56
60
|
stacks = describe_stacks(stack_name)
|
57
61
|
JSON.pretty_generate(stacks).colorize_as(:json)
|
58
62
|
end
|
59
63
|
|
60
64
|
def export(stack_name)
|
65
|
+
validate_stack_name(stack_name)
|
66
|
+
|
61
67
|
template = export_template(stack_name)
|
62
68
|
devaluate_template(template).chomp.colorize_as(:ruby)
|
63
69
|
end
|
64
70
|
|
65
71
|
def show_events(stack_name)
|
72
|
+
validate_stack_name(stack_name)
|
73
|
+
|
66
74
|
events = describe_events(stack_name)
|
67
75
|
JSON.pretty_generate(events).colorize_as(:json)
|
68
76
|
end
|
69
77
|
|
70
78
|
def show_outputs(stack_name)
|
79
|
+
validate_stack_name(stack_name)
|
80
|
+
|
71
81
|
outputs = describe_outputs(stack_name)
|
72
82
|
JSON.pretty_generate(outputs).colorize_as(:json)
|
73
83
|
end
|
74
84
|
|
75
85
|
def show_resources(stack_name)
|
86
|
+
validate_stack_name(stack_name)
|
87
|
+
|
76
88
|
resources = describe_resources(stack_name)
|
77
89
|
JSON.pretty_generate(resources).colorize_as(:json)
|
78
90
|
end
|
@@ -333,8 +345,7 @@ class Kumogata::Client
|
|
333
345
|
if @options.parameters?
|
334
346
|
parameters = {}
|
335
347
|
|
336
|
-
@options.parameters.each do |
|
337
|
-
key, value = i.split('=', 2)
|
348
|
+
@options.parameters.each do |key, value|
|
338
349
|
parameters[key] = value
|
339
350
|
end
|
340
351
|
|
@@ -342,6 +353,25 @@ class Kumogata::Client
|
|
342
353
|
end
|
343
354
|
end
|
344
355
|
|
356
|
+
def update_deletion_policy(template)
|
357
|
+
if @options.delete_stack?
|
358
|
+
template['Resources'].each do |k, v|
|
359
|
+
v['DeletionPolicy'] = 'Retain'
|
360
|
+
end
|
361
|
+
end
|
362
|
+
end
|
363
|
+
|
364
|
+
def add_encryption_password(template)
|
365
|
+
if @options.encrypt_parameters? and not @options.skip_send_password?
|
366
|
+
template['Parameters'] ||= {}
|
367
|
+
|
368
|
+
template['Parameters'][Kumogata::ENCRYPTION_PASSWORD] = {
|
369
|
+
'Type' => 'String',
|
370
|
+
'NoEcho' => 'true',
|
371
|
+
}
|
372
|
+
end
|
373
|
+
end
|
374
|
+
|
345
375
|
def validate_template(template)
|
346
376
|
result = @cloud_formation.validate_template(template.to_json)
|
347
377
|
|
@@ -364,7 +394,6 @@ class Kumogata::Client
|
|
364
394
|
:resource_status,
|
365
395
|
:resource_status_reason,
|
366
396
|
:resource_type,
|
367
|
-
:stack,
|
368
397
|
:stack_id,
|
369
398
|
:stack_name,
|
370
399
|
:timestamp,
|
@@ -431,4 +460,12 @@ Stack Resource Summaries:
|
|
431
460
|
i[0, 1].upcase + i[1..-1].downcase
|
432
461
|
}.join
|
433
462
|
end
|
463
|
+
|
464
|
+
def validate_stack_name(stack_name)
|
465
|
+
return unless stack_name
|
466
|
+
|
467
|
+
unless /\A[a-zA-Z][-a-zA-Z0-9]*\Z/i =~ stack_name
|
468
|
+
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]*"
|
469
|
+
end
|
470
|
+
end
|
434
471
|
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
class Kumogata::Crypt
|
2
|
+
ALGORITHM = 'aes256'
|
3
|
+
PASSWORD_CHARS = 'abcdefghjkmnpqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ123456789_*;:@{}()[]#$%&=-'
|
4
|
+
|
5
|
+
class << self
|
6
|
+
def encrypt(pass, str)
|
7
|
+
IO.popen("openssl enc -e -#{ALGORITHM} -pass pass:#{enquote(pass)}", "r+") {|io|
|
8
|
+
io.print str
|
9
|
+
io.close_write
|
10
|
+
io.read
|
11
|
+
}.encode64
|
12
|
+
end
|
13
|
+
|
14
|
+
def decrypt(pass, str)
|
15
|
+
IO.popen("openssl enc -d -#{ALGORITHM} -pass pass:#{enquote(pass)}", "r+") {|io|
|
16
|
+
io.print Base64.decode64(str)
|
17
|
+
io.close_write
|
18
|
+
io.read
|
19
|
+
}
|
20
|
+
end
|
21
|
+
|
22
|
+
def mkpasswd(n)
|
23
|
+
PASSWORD_CHARS.split(//).sample(n).join
|
24
|
+
end
|
25
|
+
|
26
|
+
private
|
27
|
+
|
28
|
+
def enquote(str)
|
29
|
+
"'" + str.gsub("'", %!'"'"'!) + "'"
|
30
|
+
end
|
31
|
+
end # of class methods
|
32
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
CodeRay::Encoders::Terminal::TOKEN_COLORS[:constant] = "\e[1;34m"
|
2
|
+
CodeRay::Encoders::Terminal::TOKEN_COLORS[:float] = "\e[36m"
|
3
|
+
CodeRay::Encoders::Terminal::TOKEN_COLORS[:integer] = "\e[36m"
|
4
|
+
CodeRay::Encoders::Terminal::TOKEN_COLORS[:keyword] = "\e[1;31m"
|
5
|
+
|
6
|
+
CodeRay::Encoders::Terminal::TOKEN_COLORS[:key] = {
|
7
|
+
:self => "\e[1;34m",
|
8
|
+
:char => "\e[1;34m",
|
9
|
+
:delimiter => "\e[1;34m",
|
10
|
+
}
|
11
|
+
|
12
|
+
CodeRay::Encoders::Terminal::TOKEN_COLORS[:string] = {
|
13
|
+
:self => "\e[32m",
|
14
|
+
:modifier => "\e[1;32m",
|
15
|
+
:char => "\e[1;32m",
|
16
|
+
:delimiter => "\e[1;32m",
|
17
|
+
:escape => "\e[1;32m",
|
18
|
+
}
|
data/lib/kumogata/version.rb
CHANGED
data/lib/kumogata.rb
CHANGED
@@ -18,22 +18,8 @@ require 'uuidtools'
|
|
18
18
|
|
19
19
|
require 'kumogata/argument_parser'
|
20
20
|
require 'kumogata/client'
|
21
|
+
require 'kumogata/crypt'
|
22
|
+
require 'kumogata/ext/coderay_ext'
|
21
23
|
require 'kumogata/ext/json_ext'
|
22
24
|
require 'kumogata/ext/string_ext'
|
23
25
|
require 'kumogata/logger'
|
24
|
-
|
25
|
-
CodeRay::Encoders::Terminal::TOKEN_COLORS[:key] = {
|
26
|
-
:self => "\e[1;34m",
|
27
|
-
:char => "\e[1;34m",
|
28
|
-
:delimiter => "\e[1;34m",
|
29
|
-
}
|
30
|
-
|
31
|
-
CodeRay::Encoders::Terminal::TOKEN_COLORS[:string] = {
|
32
|
-
:self => "\e[32m",
|
33
|
-
:modifier => "\e[1;32m",
|
34
|
-
:char => "\e[1;32m",
|
35
|
-
:delimiter => "\e[1;32m",
|
36
|
-
:escape => "\e[1;32m",
|
37
|
-
}
|
38
|
-
|
39
|
-
CodeRay::Encoders::Terminal::TOKEN_COLORS[:keyword] = "\e[31m"
|
@@ -86,7 +86,7 @@ Outputs do
|
|
86
86
|
end
|
87
87
|
EOS
|
88
88
|
|
89
|
-
run_client(:create, :template => template, :options => {:parameters =>
|
89
|
+
run_client(:create, :template => template, :options => {:parameters => {'InstanceType'=>'m1.large'}}) do |client, cf|
|
90
90
|
json = eval_template(template, :update_deletion_policy => true).to_json
|
91
91
|
|
92
92
|
output = make_double('output') do |obj|
|
@@ -177,4 +177,96 @@ end
|
|
177
177
|
cf.should_receive(:stacks) { stacks }
|
178
178
|
end
|
179
179
|
end
|
180
|
+
|
181
|
+
it 'create a stack from Ruby template with invalid stack name' do
|
182
|
+
template = <<-EOS
|
183
|
+
Resources do
|
184
|
+
myEC2Instance do
|
185
|
+
Type "AWS::EC2::Instance"
|
186
|
+
Properties do
|
187
|
+
ImageId "ami-XXXXXXXX"
|
188
|
+
InstanceType "t1.micro"
|
189
|
+
end
|
190
|
+
end
|
191
|
+
end
|
192
|
+
|
193
|
+
Outputs do
|
194
|
+
AZ do
|
195
|
+
Value do
|
196
|
+
Fn__GetAtt "myEC2Instance", "AvailabilityZone"
|
197
|
+
end
|
198
|
+
end
|
199
|
+
end
|
200
|
+
EOS
|
201
|
+
|
202
|
+
expect {
|
203
|
+
run_client(:create, :arguments => ['0MyStack'], :template => template)
|
204
|
+
}.to raise_error("1 validation error detected: Value '0MyStack' at 'stackName' failed to satisfy constraint: Member must satisfy regular expression pattern: [a-zA-Z][-a-zA-Z0-9]*")
|
205
|
+
end
|
206
|
+
|
207
|
+
it 'create a stack from Ruby template with encrypted parameters' do
|
208
|
+
template = <<-EOS
|
209
|
+
Parameters do
|
210
|
+
InstanceType do
|
211
|
+
Default "t1.micro"
|
212
|
+
Description "Instance Type"
|
213
|
+
Type "String"
|
214
|
+
end
|
215
|
+
end
|
216
|
+
|
217
|
+
Resources do
|
218
|
+
myEC2Instance do
|
219
|
+
Type "AWS::EC2::Instance"
|
220
|
+
Properties do
|
221
|
+
ImageId "ami-XXXXXXXX"
|
222
|
+
InstanceType { Ref "InstanceType" }
|
223
|
+
end
|
224
|
+
end
|
225
|
+
end
|
226
|
+
|
227
|
+
Outputs do
|
228
|
+
AZ do
|
229
|
+
Value do
|
230
|
+
Fn__GetAtt "myEC2Instance", "AvailabilityZone"
|
231
|
+
end
|
232
|
+
end
|
233
|
+
end
|
234
|
+
EOS
|
235
|
+
|
236
|
+
run_client(:create, :template => template, :options => {:parameters => {'InstanceType'=>'m1.large'}, :encrypt_parameters => true}) do |client, cf|
|
237
|
+
json = eval_template(template, :update_deletion_policy => true, :add_encryption_password => true).to_json
|
238
|
+
|
239
|
+
output = make_double('output') do |obj|
|
240
|
+
obj.should_receive(:key) { 'AZ' }
|
241
|
+
obj.should_receive(:value) { 'ap-northeast-1b' }
|
242
|
+
end
|
243
|
+
|
244
|
+
resource_summary = make_double('resource_summary') do |obj|
|
245
|
+
obj.should_receive(:[]).with(:logical_resource_id) { 'myEC2Instance' }
|
246
|
+
obj.should_receive(:[]).with(:physical_resource_id) { 'i-XXXXXXXX' }
|
247
|
+
obj.should_receive(:[]).with(:resource_type) { 'AWS::EC2::Instance' }
|
248
|
+
obj.should_receive(:[]).with(:resource_status) { 'CREATE_COMPLETE' }
|
249
|
+
obj.should_receive(:[]).with(:resource_status_reason) { nil }
|
250
|
+
obj.should_receive(:[]).with(:last_updated_timestamp) { '2014-03-02 04:35:12 UTC' }
|
251
|
+
end
|
252
|
+
|
253
|
+
stack = make_double('stack') do |obj|
|
254
|
+
obj.should_receive(:status).and_return(
|
255
|
+
'CREATE_COMPLETE', 'CREATE_COMPLETE',
|
256
|
+
'DELETE_COMPLETE', 'DELETE_COMPLETE', 'DELETE_COMPLETE')
|
257
|
+
obj.should_receive(:outputs) { [output] }
|
258
|
+
obj.should_receive(:resource_summaries) { [resource_summary] }
|
259
|
+
obj.should_receive(:delete)
|
260
|
+
end
|
261
|
+
|
262
|
+
stacks = make_double('stacks') do |obj|
|
263
|
+
obj.should_receive(:create)
|
264
|
+
.with('kumogata-XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX', json, {:parameters=>{"InstanceType"=>"m1.large"}}) { stack }
|
265
|
+
obj.should_receive(:[])
|
266
|
+
.with('kumogata-XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX') { stack }
|
267
|
+
end
|
268
|
+
|
269
|
+
cf.should_receive(:stacks).twice { stacks }
|
270
|
+
end
|
271
|
+
end
|
180
272
|
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
describe Kumogata::Crypt do
|
2
|
+
it 'encrypt string' do
|
3
|
+
encrypted = Kumogata::Crypt.encrypt("my_password", "jugem jugem")
|
4
|
+
decrypted = Kumogata::Crypt.decrypt("my_password", encrypted)
|
5
|
+
expect(decrypted).to eq("jugem jugem")
|
6
|
+
end
|
7
|
+
|
8
|
+
it 'encrypt long string' do
|
9
|
+
encrypted = Kumogata::Crypt.encrypt("my_password", "jugem jugem" * 10240)
|
10
|
+
decrypted = Kumogata::Crypt.decrypt("my_password", encrypted)
|
11
|
+
expect(decrypted).to eq("jugem jugem" * 10240)
|
12
|
+
end
|
13
|
+
|
14
|
+
it 'make password' do
|
15
|
+
passwd = Kumogata::Crypt.mkpasswd(16)
|
16
|
+
expect(passwd).to be_kind_of(String)
|
17
|
+
expect(passwd.length).to eq(16)
|
18
|
+
end
|
19
|
+
end
|
@@ -10,7 +10,6 @@ describe 'Kumogata::Client#show_events' do
|
|
10
10
|
obj.should_receive(:resource_status) { "CREATE_FAILED" }
|
11
11
|
obj.should_receive(:resource_status_reason) { "The following resource(s) failed to create: [myEC2Instance]. " }
|
12
12
|
obj.should_receive(:resource_type) { "AWS::CloudFormation::Stack" }
|
13
|
-
obj.should_receive(:stack) { "#<AWS::CloudFormation::Stack:0x007ffe4384ca80>" }
|
14
13
|
obj.should_receive(:stack_id) { "arn:aws:cloudformation:ap-northeast-1:822997939312:stack/kumogata-f11118a4-a4f7-11e3-8183-98fe943e66ca/f1381a30-a4f7-11e3-a340-506cf9a1c096" }
|
15
14
|
obj.should_receive(:stack_name) { "kumogata-f11118a4-a4f7-11e3-8183-98fe943e66ca" }
|
16
15
|
obj.should_receive(:timestamp) { "2014-03-06 06:24:21 UTC" }
|
@@ -38,7 +37,6 @@ describe 'Kumogata::Client#show_events' do
|
|
38
37
|
"ResourceStatus": "CREATE_FAILED",
|
39
38
|
"ResourceStatusReason": "The following resource(s) failed to create: [myEC2Instance]. ",
|
40
39
|
"ResourceType": "AWS::CloudFormation::Stack",
|
41
|
-
"Stack": "#<AWS::CloudFormation::Stack:0x007ffe4384ca80>",
|
42
40
|
"StackId": "arn:aws:cloudformation:ap-northeast-1:822997939312:stack/kumogata-f11118a4-a4f7-11e3-8183-98fe943e66ca/f1381a30-a4f7-11e3-a340-506cf9a1c096",
|
43
41
|
"StackName": "kumogata-f11118a4-a4f7-11e3-8183-98fe943e66ca",
|
44
42
|
"Timestamp": "2014-03-06 06:24:21 UTC"
|
@@ -83,7 +83,7 @@ Outputs do
|
|
83
83
|
end
|
84
84
|
EOS
|
85
85
|
|
86
|
-
run_client(:update, :arguments => ['MyStack'], :template => template, :options => {:parameters =>
|
86
|
+
run_client(:update, :arguments => ['MyStack'], :template => template, :options => {:parameters => {'InstanceType'=>'m1.large'}}) do |client, cf|
|
87
87
|
json = eval_template(template).to_json
|
88
88
|
|
89
89
|
output = make_double('output') do |obj|
|
@@ -116,4 +116,92 @@ end
|
|
116
116
|
cf.should_receive(:stacks) { stacks }
|
117
117
|
end
|
118
118
|
end
|
119
|
+
|
120
|
+
it 'update a stack from Ruby template with invalid stack name' do
|
121
|
+
template = <<-EOS
|
122
|
+
Resources do
|
123
|
+
myEC2Instance do
|
124
|
+
Type "AWS::EC2::Instance"
|
125
|
+
Properties do
|
126
|
+
ImageId "ami-XXXXXXXX"
|
127
|
+
end
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
Outputs do
|
132
|
+
AZ do
|
133
|
+
Value do
|
134
|
+
Fn__GetAtt "myEC2Instance", "AvailabilityZone"
|
135
|
+
end
|
136
|
+
end
|
137
|
+
end
|
138
|
+
EOS
|
139
|
+
|
140
|
+
expect {
|
141
|
+
run_client(:update, :arguments => ['0MyStack'], :template => template)
|
142
|
+
}.to raise_error("1 validation error detected: Value '0MyStack' at 'stackName' failed to satisfy constraint: Member must satisfy regular expression pattern: [a-zA-Z][-a-zA-Z0-9]*")
|
143
|
+
end
|
144
|
+
|
145
|
+
it 'update a stack from Ruby template with encrypted parameters' do
|
146
|
+
template = <<-EOS
|
147
|
+
Parameters do
|
148
|
+
InstanceType do
|
149
|
+
Default "t1.micro"
|
150
|
+
Description "Instance Type"
|
151
|
+
Type "String"
|
152
|
+
end
|
153
|
+
end
|
154
|
+
|
155
|
+
Resources do
|
156
|
+
myEC2Instance do
|
157
|
+
Type "AWS::EC2::Instance"
|
158
|
+
Properties do
|
159
|
+
ImageId "ami-XXXXXXXX"
|
160
|
+
InstanceType { Ref "InstanceType" }
|
161
|
+
end
|
162
|
+
end
|
163
|
+
end
|
164
|
+
|
165
|
+
Outputs do
|
166
|
+
AZ do
|
167
|
+
Value do
|
168
|
+
Fn__GetAtt "myEC2Instance", "AvailabilityZone"
|
169
|
+
end
|
170
|
+
end
|
171
|
+
end
|
172
|
+
EOS
|
173
|
+
|
174
|
+
run_client(:update, :arguments => ['MyStack'], :template => template, :options => {:parameters => {'InstanceType'=>'m1.large'}, :encrypt_parameters => true}) do |client, cf|
|
175
|
+
json = eval_template(template, :add_encryption_password => true).to_json
|
176
|
+
|
177
|
+
output = make_double('output') do |obj|
|
178
|
+
obj.should_receive(:key) { 'AZ' }
|
179
|
+
obj.should_receive(:value) { 'ap-northeast-1b' }
|
180
|
+
end
|
181
|
+
|
182
|
+
resource_summary = make_double('resource_summary') do |obj|
|
183
|
+
obj.should_receive(:[]).with(:logical_resource_id) { 'myEC2Instance' }
|
184
|
+
obj.should_receive(:[]).with(:physical_resource_id) { 'i-XXXXXXXX' }
|
185
|
+
obj.should_receive(:[]).with(:resource_type) { 'AWS::EC2::Instance' }
|
186
|
+
obj.should_receive(:[]).with(:resource_status) { 'UPDATE_COMPLETE' }
|
187
|
+
obj.should_receive(:[]).with(:resource_status_reason) { nil }
|
188
|
+
obj.should_receive(:[]).with(:last_updated_timestamp) { '2014-03-02 04:35:12 UTC' }
|
189
|
+
end
|
190
|
+
|
191
|
+
stack = make_double('stack') do |obj|
|
192
|
+
obj.should_receive(:update).with(:template => json, :parameters=>{"InstanceType"=>"m1.large"})
|
193
|
+
obj.should_receive(:status).and_return(
|
194
|
+
'UPDATE_COMPLETE', 'UPDATE_COMPLETE', 'UPDATE_COMPLETE')
|
195
|
+
obj.should_receive(:outputs) { [output] }
|
196
|
+
obj.should_receive(:resource_summaries) { [resource_summary] }
|
197
|
+
end
|
198
|
+
|
199
|
+
stacks = make_double('stacks') do |obj|
|
200
|
+
obj.should_receive(:[])
|
201
|
+
.with('MyStack') { stack }
|
202
|
+
end
|
203
|
+
|
204
|
+
cf.should_receive(:stacks) { stacks }
|
205
|
+
end
|
206
|
+
end
|
119
207
|
end
|
data/spec/spec_helper.rb
CHANGED
@@ -24,6 +24,7 @@ def run_client(command, options = {})
|
|
24
24
|
kumogata_template = options[:template]
|
25
25
|
kumogata_arguments = options[:arguments] || []
|
26
26
|
kumogata_options = Kumogata::ArgumentParser::DEFAULT_OPTIONS.merge(options[:options] || {})
|
27
|
+
kumogata_options[:result_log] = '/dev/null'
|
27
28
|
template_ext = options[:template_ext] || '.rb'
|
28
29
|
|
29
30
|
client = Kumogata::Client.new(kumogata_options)
|
@@ -52,6 +53,10 @@ def eval_template(template, options = {})
|
|
52
53
|
update_deletion_policy(template)
|
53
54
|
end
|
54
55
|
|
56
|
+
if options[:add_encryption_password]
|
57
|
+
add_encryption_password(template)
|
58
|
+
end
|
59
|
+
|
55
60
|
return template
|
56
61
|
end
|
57
62
|
|
@@ -61,6 +66,15 @@ def update_deletion_policy(template)
|
|
61
66
|
end
|
62
67
|
end
|
63
68
|
|
69
|
+
def add_encryption_password(template)
|
70
|
+
template['Parameters'] ||= {}
|
71
|
+
|
72
|
+
template['Parameters'][Kumogata::ENCRYPTION_PASSWORD] = {
|
73
|
+
'Type' => 'String',
|
74
|
+
'NoEcho' => 'true',
|
75
|
+
}
|
76
|
+
end
|
77
|
+
|
64
78
|
def make_double(name)
|
65
79
|
obj = double(name)
|
66
80
|
yield(obj)
|
metadata
CHANGED
@@ -1,181 +1,181 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: kumogata
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.2.
|
4
|
+
version: 0.2.13
|
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-07 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: aws-sdk
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
|
-
- - '>='
|
17
|
+
- - ! '>='
|
18
18
|
- !ruby/object:Gem::Version
|
19
19
|
version: '0'
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
|
-
- - '>='
|
24
|
+
- - ! '>='
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: '0'
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: coderay
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
|
-
- - '>='
|
31
|
+
- - ! '>='
|
32
32
|
- !ruby/object:Gem::Version
|
33
33
|
version: '0'
|
34
34
|
type: :runtime
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
|
-
- - '>='
|
38
|
+
- - ! '>='
|
39
39
|
- !ruby/object:Gem::Version
|
40
40
|
version: '0'
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
42
|
name: diffy
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
44
44
|
requirements:
|
45
|
-
- - '>='
|
45
|
+
- - ! '>='
|
46
46
|
- !ruby/object:Gem::Version
|
47
47
|
version: '0'
|
48
48
|
type: :runtime
|
49
49
|
prerelease: false
|
50
50
|
version_requirements: !ruby/object:Gem::Requirement
|
51
51
|
requirements:
|
52
|
-
- - '>='
|
52
|
+
- - ! '>='
|
53
53
|
- !ruby/object:Gem::Version
|
54
54
|
version: '0'
|
55
55
|
- !ruby/object:Gem::Dependency
|
56
56
|
name: dslh
|
57
57
|
requirement: !ruby/object:Gem::Requirement
|
58
58
|
requirements:
|
59
|
-
- - '>='
|
59
|
+
- - ! '>='
|
60
60
|
- !ruby/object:Gem::Version
|
61
61
|
version: 0.2.4
|
62
62
|
type: :runtime
|
63
63
|
prerelease: false
|
64
64
|
version_requirements: !ruby/object:Gem::Requirement
|
65
65
|
requirements:
|
66
|
-
- - '>='
|
66
|
+
- - ! '>='
|
67
67
|
- !ruby/object:Gem::Version
|
68
68
|
version: 0.2.4
|
69
69
|
- !ruby/object:Gem::Dependency
|
70
70
|
name: hashie
|
71
71
|
requirement: !ruby/object:Gem::Requirement
|
72
72
|
requirements:
|
73
|
-
- - '>='
|
73
|
+
- - ! '>='
|
74
74
|
- !ruby/object:Gem::Version
|
75
75
|
version: '0'
|
76
76
|
type: :runtime
|
77
77
|
prerelease: false
|
78
78
|
version_requirements: !ruby/object:Gem::Requirement
|
79
79
|
requirements:
|
80
|
-
- - '>='
|
80
|
+
- - ! '>='
|
81
81
|
- !ruby/object:Gem::Version
|
82
82
|
version: '0'
|
83
83
|
- !ruby/object:Gem::Dependency
|
84
84
|
name: highline
|
85
85
|
requirement: !ruby/object:Gem::Requirement
|
86
86
|
requirements:
|
87
|
-
- - '>='
|
87
|
+
- - ! '>='
|
88
88
|
- !ruby/object:Gem::Version
|
89
89
|
version: '0'
|
90
90
|
type: :runtime
|
91
91
|
prerelease: false
|
92
92
|
version_requirements: !ruby/object:Gem::Requirement
|
93
93
|
requirements:
|
94
|
-
- - '>='
|
94
|
+
- - ! '>='
|
95
95
|
- !ruby/object:Gem::Version
|
96
96
|
version: '0'
|
97
97
|
- !ruby/object:Gem::Dependency
|
98
98
|
name: json
|
99
99
|
requirement: !ruby/object:Gem::Requirement
|
100
100
|
requirements:
|
101
|
-
- - '>='
|
101
|
+
- - ! '>='
|
102
102
|
- !ruby/object:Gem::Version
|
103
103
|
version: '0'
|
104
104
|
type: :runtime
|
105
105
|
prerelease: false
|
106
106
|
version_requirements: !ruby/object:Gem::Requirement
|
107
107
|
requirements:
|
108
|
-
- - '>='
|
108
|
+
- - ! '>='
|
109
109
|
- !ruby/object:Gem::Version
|
110
110
|
version: '0'
|
111
111
|
- !ruby/object:Gem::Dependency
|
112
112
|
name: term-ansicolor
|
113
113
|
requirement: !ruby/object:Gem::Requirement
|
114
114
|
requirements:
|
115
|
-
- - '>='
|
115
|
+
- - ! '>='
|
116
116
|
- !ruby/object:Gem::Version
|
117
117
|
version: '0'
|
118
118
|
type: :runtime
|
119
119
|
prerelease: false
|
120
120
|
version_requirements: !ruby/object:Gem::Requirement
|
121
121
|
requirements:
|
122
|
-
- - '>='
|
122
|
+
- - ! '>='
|
123
123
|
- !ruby/object:Gem::Version
|
124
124
|
version: '0'
|
125
125
|
- !ruby/object:Gem::Dependency
|
126
126
|
name: uuidtools
|
127
127
|
requirement: !ruby/object:Gem::Requirement
|
128
128
|
requirements:
|
129
|
-
- - '>='
|
129
|
+
- - ! '>='
|
130
130
|
- !ruby/object:Gem::Version
|
131
131
|
version: '0'
|
132
132
|
type: :runtime
|
133
133
|
prerelease: false
|
134
134
|
version_requirements: !ruby/object:Gem::Requirement
|
135
135
|
requirements:
|
136
|
-
- - '>='
|
136
|
+
- - ! '>='
|
137
137
|
- !ruby/object:Gem::Version
|
138
138
|
version: '0'
|
139
139
|
- !ruby/object:Gem::Dependency
|
140
140
|
name: bundler
|
141
141
|
requirement: !ruby/object:Gem::Requirement
|
142
142
|
requirements:
|
143
|
-
- - '>='
|
143
|
+
- - ! '>='
|
144
144
|
- !ruby/object:Gem::Version
|
145
145
|
version: '0'
|
146
146
|
type: :development
|
147
147
|
prerelease: false
|
148
148
|
version_requirements: !ruby/object:Gem::Requirement
|
149
149
|
requirements:
|
150
|
-
- - '>='
|
150
|
+
- - ! '>='
|
151
151
|
- !ruby/object:Gem::Version
|
152
152
|
version: '0'
|
153
153
|
- !ruby/object:Gem::Dependency
|
154
154
|
name: rake
|
155
155
|
requirement: !ruby/object:Gem::Requirement
|
156
156
|
requirements:
|
157
|
-
- - '>='
|
157
|
+
- - ! '>='
|
158
158
|
- !ruby/object:Gem::Version
|
159
159
|
version: '0'
|
160
160
|
type: :development
|
161
161
|
prerelease: false
|
162
162
|
version_requirements: !ruby/object:Gem::Requirement
|
163
163
|
requirements:
|
164
|
-
- - '>='
|
164
|
+
- - ! '>='
|
165
165
|
- !ruby/object:Gem::Version
|
166
166
|
version: '0'
|
167
167
|
- !ruby/object:Gem::Dependency
|
168
168
|
name: rspec
|
169
169
|
requirement: !ruby/object:Gem::Requirement
|
170
170
|
requirements:
|
171
|
-
- - '>='
|
171
|
+
- - ! '>='
|
172
172
|
- !ruby/object:Gem::Version
|
173
173
|
version: 2.11.0
|
174
174
|
type: :development
|
175
175
|
prerelease: false
|
176
176
|
version_requirements: !ruby/object:Gem::Requirement
|
177
177
|
requirements:
|
178
|
-
- - '>='
|
178
|
+
- - ! '>='
|
179
179
|
- !ruby/object:Gem::Version
|
180
180
|
version: 2.11.0
|
181
181
|
description: A tool for AWS CloudFormation. It can define a template in Ruby DSL.
|
@@ -197,6 +197,8 @@ files:
|
|
197
197
|
- lib/kumogata.rb
|
198
198
|
- lib/kumogata/argument_parser.rb
|
199
199
|
- lib/kumogata/client.rb
|
200
|
+
- lib/kumogata/crypt.rb
|
201
|
+
- lib/kumogata/ext/coderay_ext.rb
|
200
202
|
- lib/kumogata/ext/json_ext.rb
|
201
203
|
- lib/kumogata/ext/string_ext.rb
|
202
204
|
- lib/kumogata/logger.rb
|
@@ -207,6 +209,7 @@ files:
|
|
207
209
|
- spec/Drupal_Single_Instance.template.rb
|
208
210
|
- spec/kumogata_convert_spec.rb
|
209
211
|
- spec/kumogata_create_spec.rb
|
212
|
+
- spec/kumogata_crypt_spec.rb
|
210
213
|
- spec/kumogata_delete_spec.rb
|
211
214
|
- spec/kumogata_diff_spec.rb
|
212
215
|
- spec/kumogata_export_spec.rb
|
@@ -227,17 +230,17 @@ require_paths:
|
|
227
230
|
- lib
|
228
231
|
required_ruby_version: !ruby/object:Gem::Requirement
|
229
232
|
requirements:
|
230
|
-
- - '>='
|
233
|
+
- - ! '>='
|
231
234
|
- !ruby/object:Gem::Version
|
232
235
|
version: '0'
|
233
236
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
234
237
|
requirements:
|
235
|
-
- - '>='
|
238
|
+
- - ! '>='
|
236
239
|
- !ruby/object:Gem::Version
|
237
240
|
version: '0'
|
238
241
|
requirements: []
|
239
242
|
rubyforge_project:
|
240
|
-
rubygems_version: 2.
|
243
|
+
rubygems_version: 2.1.11
|
241
244
|
signing_key:
|
242
245
|
specification_version: 4
|
243
246
|
summary: A tool for AWS CloudFormation.
|
@@ -246,6 +249,7 @@ test_files:
|
|
246
249
|
- spec/Drupal_Single_Instance.template.rb
|
247
250
|
- spec/kumogata_convert_spec.rb
|
248
251
|
- spec/kumogata_create_spec.rb
|
252
|
+
- spec/kumogata_crypt_spec.rb
|
249
253
|
- spec/kumogata_delete_spec.rb
|
250
254
|
- spec/kumogata_diff_spec.rb
|
251
255
|
- spec/kumogata_export_spec.rb
|
@@ -256,4 +260,3 @@ test_files:
|
|
256
260
|
- spec/kumogata_update_spec.rb
|
257
261
|
- spec/kumogata_validate_spec.rb
|
258
262
|
- spec/spec_helper.rb
|
259
|
-
has_rdoc:
|