aws-cfn-dsl 0.6.0 → 0.7.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,15 +1,7 @@
1
1
  ---
2
- !binary "U0hBMQ==":
3
- metadata.gz: !binary |-
4
- OTVjY2UxNTJiYmQyZjgzYmQ2M2NhYzljZDE2NGRkMWU3ZGY3YzBjZA==
5
- data.tar.gz: !binary |-
6
- NTdkNGVhNWQ5NzRhMTVmNjA3ZTA4Y2QzOGZhOWM3N2IxYTc3ODk1OA==
2
+ SHA1:
3
+ metadata.gz: b9ba230058f9ce82bf26b89f880d91fe995fe42f
4
+ data.tar.gz: f2e68182943d453d15ff62e516fe6afdc74a3f7b
7
5
  SHA512:
8
- metadata.gz: !binary |-
9
- OTYzNDdmODQ2ODNkZTUxMjMzZDExYzU0ZTM4M2UwM2VjZjQ5YzVkNGM3NDk2
10
- ZTc2ZTBhZjc4MTU3OGY3ODlkYzMzOWMzYmMwM2U1Yjc1MGZlZmVhYTVmN2Vm
11
- MTMxYTI3MWM3MDMzYWVkYjllNTRkZWEyOGQ4MjRjMGQ5MWEzYTk=
12
- data.tar.gz: !binary |-
13
- NzFjZjgyNmJlNzcxOTMwNzUwZTk4NmMyZTg3NDRiM2JiNjQ3ZmQzNDM3MmEz
14
- NGJmNWYyZWI0NDhiYjBmZGJiOGY5NDMyMTE0YTNlNmQ1MjNlODZmMTU0YTBm
15
- NWMxMDMwYTQ3MmQ5NGY0ZmViOGUwZDZjODdhMTJiMDcwMzYwYTY=
6
+ metadata.gz: 3bd00bf073fe8842760c5727baf1828660df3699ca5c4be19bdf23ca9715ab74de6cd2b3e9031bf26a08e5d9fb8b7198f3e41c1b6acf1a8136b766b0c8b79768
7
+ data.tar.gz: 0e0e5bd09a2bfdc3218a91a3e2a9929882581837b92fad3861e8f333abc336a642169aa80c614916b760ecab6598095d82c6657574f5548f9ec391dc0353640f
data/Gemfile CHANGED
@@ -12,8 +12,6 @@ gem 'aws-cfn-compiler', :path => '../aws-cfn-compiler', :group => :development
12
12
  gem 'aws-cfn-yats', :path => '../aws-cfn-yats', :group => :development
13
13
  gem 'aws-cfn-stacker', :path => '../aws-cfn-stacker', :group => :development
14
14
 
15
- gem 'slop', :group => :development
16
-
17
15
  gem 'json_pure', :group => :development
18
16
  gem 'bundler', '~> 1.5', :group => :development
19
17
  gem 'rake', :group => :development
@@ -18,9 +18,10 @@ Gem::Specification.new do |spec|
18
18
  spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
19
  spec.require_paths = ["lib"]
20
20
 
21
- spec.add_dependency 'awesome_print'
21
+ spec.add_dependency 'awesome_print', '~> 1.2', '>= 1.2.0'
22
+ spec.add_dependency 'psych'
22
23
  spec.add_dependency 'json'
24
+ spec.add_dependency 'slop'
23
25
  spec.add_dependency 'cloudformation-ruby-dsl', '~> 0.4', '>= 0.4.3'
24
- spec.add_dependency "slop"
25
26
 
26
27
  end
@@ -7,7 +7,7 @@ module Aws
7
7
  module Dsl
8
8
  class Base
9
9
  attr_accessor :items
10
- attr_reader :output
10
+ attr_reader :template
11
11
 
12
12
  require 'dldinternet/mixlib/logging'
13
13
  include DLDInternet::Mixlib::Logging
@@ -17,30 +17,42 @@ module Aws
17
17
  @output = []
18
18
  @config ||= {}
19
19
 
20
- lcs = ::Logging::ColorScheme.new( 'compiler', :levels => {
21
- :trace => :blue,
22
- :debug => :cyan,
23
- :info => :green,
24
- :step => :green,
25
- :warn => :yellow,
26
- :error => :red,
27
- :fatal => :red,
28
- :todo => :purple,
29
- })
30
- scheme = lcs.scheme
31
- scheme['trace'] = "\e[38;5;33m"
32
- scheme['fatal'] = "\e[38;5;89m"
33
- scheme['todo'] = "\e[38;5;55m"
34
- lcs.scheme scheme
35
- @config[:log_opts] = lambda{|mlll| {
36
- :pattern => "%#{mlll}l: %m %C\n",
37
- :date_pattern => '%Y-%m-%d %H:%M:%S',
38
- :color_scheme => 'compiler'
20
+ # noinspection RubyStringKeysInHashInspection
21
+ @formats = {
22
+ 'yaml' => 'yaml',
23
+ 'yml' => 'yaml',
24
+ 'yts' => 'yaml',
25
+ 'ytf' => 'yaml',
26
+ 'ytp' => 'yaml',
27
+ 'json' => 'json',
28
+ 'jml' => 'json',
29
+ 'jts' => 'json',
30
+ 'jtf' => 'json',
31
+ 'jtp' => 'json',
32
+ 'tpl' => 'json',
33
+ 'template' => 'json',
34
+ 'ruby' => 'ruby',
35
+ 'rb' => 'ruby',
39
36
  }
40
- }
41
- @config[:log_level] = :info
42
- @logger = getLogger(@config)
43
37
 
38
+
39
+ end
40
+
41
+ def ext2format(ext)
42
+ @formats.has_key? ext ? @formats[ext] : nil
43
+ end
44
+
45
+ def format2exts(format)
46
+ exts = @formats.select{ |_,v| v == format }
47
+ if exts.size > 0
48
+ exts.keys
49
+ else
50
+ []
51
+ end
52
+ end
53
+
54
+ def formats_compatible?(format, match)
55
+ @formats[match] == @formats[format]
44
56
  end
45
57
 
46
58
  def save_dsl(path=nil,parts=@items)
@@ -50,11 +62,13 @@ module Aws
50
62
 
51
63
  def load_template(file=nil)
52
64
  if file
53
- logStep "Loading #{file}"
65
+ filn = File.join(File.dirname(file), file)
66
+ filn = File.expand_path(file) if @config[:expandedpaths]
67
+ logStep "Loading #{filn}"
54
68
  begin
55
69
  abs = File.absolute_path(File.expand_path(file))
56
- unless File.exists?(abs) or @opts[:output].nil?
57
- abs = File.absolute_path(File.expand_path(File.join(@opts[:output],file)))
70
+ unless File.exists?(abs) or @config[:directory].nil?
71
+ abs = File.absolute_path(File.expand_path(File.join(@config[:directory],file)))
58
72
  end
59
73
  rescue
60
74
  # pass
@@ -71,78 +85,13 @@ module Aws
71
85
  else
72
86
  abort! "Unable to open template: #{abs}"
73
87
  end
74
- end
75
- end
76
-
77
- protected
78
-
79
- def simplify(val,start=false)
80
- logStep "Simplify a block ..." if start
81
- if val.is_a?(Hash)
82
- val = Hash[val.map { |k,v| [k, simplify(v)] }]
83
- if val.length != 1
84
- val
85
- else
86
- k, v = val.entries[0]
87
- case @opts[:functions]
88
- when /1|on|set|enable|yes|true/ then
89
- case
90
- # CloudFormation functions
91
- when k == 'Fn::Base64'
92
- FnCall.new 'base64', [v], true
93
- when k == 'Fn::FindInMap'
94
- FnCall.new 'find_in_map', v
95
- when k == 'Fn::GetAtt'
96
- FnCall.new 'get_att', v
97
- when k == 'Fn::GetAZs'
98
- FnCall.new 'get_azs', v != '' ? [v] : []
99
- when k == 'Fn::Join'
100
- FnCall.new 'join', [v[0]] + v[1], true
101
- when k == 'Fn::Select'
102
- FnCall.new 'select', v
103
- when k == 'Ref' && v == 'AWS::Region'
104
- FnCall.new 'aws_region', []
105
- when k == 'Ref' && v == 'AWS::StackName'
106
- FnCall.new 'aws_stack_name', []
107
- # CloudFormation internal references
108
- when k == 'Ref'
109
- FnCall.new 'ref', [v]
110
- else
111
- val
112
- end
113
- else
114
- val
115
- end
116
- end
117
- elsif val.is_a?(Array)
118
- val.map { |v| simplify(v) }
88
+ @items
119
89
  else
120
- val
121
- end
122
- end
123
-
124
- def pprint(val)
125
- logStep "Pretty print ..."
126
- case detect_type(val)
127
- when :template
128
- pprint_cfn_template(val)
129
- when :parameter
130
- pprint_cfn_section 'parameter', 'TODO', val, 'Parameters'
131
- when :resource
132
- pprint_cfn_resource 'TODO', val
133
- when :parameters
134
- val.each { |k, v| pprint_cfn_section 'parameter', k, v, 'Parameters' }
135
- when :resources
136
- val.each { |k, v| pprint_cfn_resource k, v }
137
- else
138
- pprint_value(val, '')
90
+ nil
139
91
  end
140
92
  end
141
93
 
142
- def module_name(parts=-1)
143
- name = self.class.to_s.split("::")
144
- name[0..parts-1].join('::')
145
- end
94
+ protected
146
95
 
147
96
  def abort!(msg=nil,rc=1)
148
97
  @logger.error msg if msg
@@ -150,361 +99,24 @@ module Aws
150
99
  exit rc
151
100
  end
152
101
 
153
- def write(*s)
154
- if s.is_a?(Array)
155
- s = s.join('')
156
- end
157
- if @output.size > 0
158
- @output[0].write s
159
- else
160
- print s
161
- end
162
- end
163
-
164
- def writeln(s='')
165
- if @output.size > 0
166
- @output[0].puts s
167
- else
168
- puts s
169
- end
170
- end
171
-
172
- # Attempt to figure out what fragment of the template we have. This is imprecise and can't
173
- # detect Mappings and Outputs sections reliably, so it doesn't attempt to.
174
- def detect_type(val)
175
- if val.is_a?(Hash) && val['AWSTemplateFormatVersion']
176
- :template
177
- elsif val.is_a?(Hash) && /^(String|Number)$/ =~ val['Type']
178
- :parameter
179
- elsif val.is_a?(Hash) && val['Type']
180
- :resource
181
- elsif val.is_a?(Hash) && val.values.all? { |v| detect_type(v) == :parameter }
182
- :parameters
183
- elsif val.is_a?(Hash) && val.values.all? { |v| detect_type(v) == :resource }
184
- :resources
185
- end
186
- end
187
-
188
- def pprint_cfn_template(tpl)
189
- file = File.basename(@opts[:template]).gsub(%r'\.(json|yaml|js|yaml)$'i, '.rb')
190
- # noinspection RubyParenthesesAroundConditionInspection
191
- if (iam = open_output('', file.gsub(%r'\.(json|yaml|js|yml|rb)'i, '')))
192
- logStep "Saving #{file}"
193
- writeln "#!/usr/bin/env ruby"
194
- print_maintainer('')
195
- writeln
196
- if @opts[:output]
197
- writeln "$:.unshift(File.dirname(__FILE__))"
198
- # noinspection RubyExpressionInStringInspection
199
- writeln '$:.unshift File.absolute_path("#{File.dirname(__FILE__)}/../lib")'
200
- end
201
- writeln "require 'bundler/setup'"
202
- writeln "require 'aws/cfn/dsl/template'"
203
- #writeln "require 'cloudformation-ruby-dsl/spotprice'"
204
- #writeln "require 'cloudformation-ruby-dsl/table'"
205
- writeln
206
- writeln "template do"
207
- writeln
208
- tpl.each do |section, v|
209
- case section
210
- when 'Parameters'
211
- when 'Mappings'
212
- when 'Resources'
213
- when 'Outputs'
214
- else
215
- write " value #{fmt_key(section)} => "
216
- pprint_value v, ' '
217
- writeln
218
- writeln
219
- end
220
- end
221
- else
222
- @logger.warn "Not overwriting template: '#{file}'"
223
- end
224
- %w(Mappings Parameters Resources Outputs).each do |section|
225
- writeln " # #{section}" if iam
226
- v = tpl[section]
227
- case section
228
- when 'Parameters'
229
- v.each { |name, options| pprint_cfn_section 'parameter', name, options, 'Parameters', iam }
230
- when 'Mappings'
231
- v.each { |name, options| pprint_cfn_section 'mapping', name, options, 'Mappings', iam }
232
- when 'Resources'
233
- v.each { |name, options| pprint_cfn_resource name, options, iam }
234
- when 'Outputs'
235
- v.each { |name, options| pprint_cfn_section 'output', name, options, 'Outputs', iam }
236
- else
237
- abort! "Internal Error: Unexpected section '#{section}'"
238
- end
239
- writeln if iam
240
- end
241
- writeln "end.exec!" if iam
242
- end
243
-
244
- def open_output(subdir,name)
245
- if @opts[:output]
246
- file = rb_file(subdir, name)
247
- if i_am_maintainer(file)
248
- @output.unshift File.open(file, 'w')
249
- true
250
- else
251
- false
252
- end
253
- else
254
- true
255
- end
256
- end
102
+ require "aws/cfn/dsl/mixins/options"
103
+ include Aws::Cfn::Dsl::Options
257
104
 
258
- def add_brick(subdir,name)
259
- if @opts[:output]
260
- #file = rb_file(subdir, name).gsub(%r'^#{@opts[:output]}/','')
261
- #writeln " file '#{file}'"
262
- s = subdir.downcase.gsub(%r's$','')
263
- writeln " #{s} '#{name}'"
264
- end
265
- end
105
+ require "aws/cfn/dsl/mixins/maintainer"
106
+ include Aws::Cfn::Dsl::Maintainer
266
107
 
267
- def rb_file(subdir, name)
268
- path = File.join(@opts[:output], subdir)
269
- unless File.directory? path
270
- Dir.mkdir path
271
- end
272
- file = File.join(path, "#{name}.rb")
273
- end
108
+ require "aws/cfn/dsl/mixins/simplify"
109
+ include Aws::Cfn::Dsl::Simplify
274
110
 
275
- def close_output()
276
- if @opts[:output] and @output.size > 0
277
- fp = @output.shift
278
- fp.close
279
- end
280
- end
111
+ require "aws/cfn/dsl/mixins/prettyprint"
112
+ include Aws::Cfn::Dsl::PrettyPrint
281
113
 
282
- def maintainer(parts=-1)
283
- "maintainer: #{module_name parts}"
284
- end
114
+ require "aws/cfn/dsl/mixins/output"
115
+ include Aws::Cfn::Dsl::Output
285
116
 
286
- def maintainer_comment(indent=' ')
287
- "#{indent}# WARNING: This code is generated. Your changes may be overwritten!\n" +
288
- "#{indent}# Remove this message and/or set the 'maintainer: <author name>' when you need your changes to survive.\n" +
289
- "#{indent}# Abscence of the 'maintainer: ' will be considered conscent to overwrite.\n" +
290
- "#{indent}# #{maintainer 3}\n" +
291
- "#\n"
292
- end
117
+ require "aws/cfn/dsl/mixins/dsl"
118
+ include Aws::Cfn::Dsl::DSL
293
119
 
294
- def print_maintainer(indent=' ')
295
- writeln maintainer_comment(indent)
296
- end
297
-
298
- def i_am_maintainer(file)
299
- # mod = module_name 2
300
- if File.exists?(file)
301
- src = IO.read(file)
302
- mtc = src.match(%r'#{maintainer 2}')
303
- iam = (not mtc.nil? or src.match(%r'#\s*maintainer:').nil?)
304
- ovr = @config[:overwrite]
305
- iam or ovr
306
- else
307
- true
308
- end
309
- end
310
-
311
- def prelude_code(indent=' ')
312
- "scope = Aws::Cfn::Compiler.binding[File.basename(File.dirname(__FILE__))][File.basename(__FILE__, '.rb')]\n"+
313
- "template = scope[:template]\n"+
314
- "\n"+
315
- "# noinspection RubyStringKeysInHashInspection\n"+
316
- "template." +
317
- ""
318
- end
319
-
320
- def print_with_wrapper(code,indent=' ')
321
- write prelude_code(indent)+code.gsub(%r'^\s+','')
322
- end
323
-
324
- def pprint_cfn_section(section, name, options, subdir, brick=true)
325
- if open_output(subdir,name)
326
- @logger.info "Pretty print #{section} '#{name}' to '#{rb_file(subdir, name)}'"
327
- print_maintainer ''
328
- print_with_wrapper "#{section} #{fmt_string(name)}"
329
- indent = ' ' + (' ' * section.length) + ' '
330
- hang = true
331
- options.each do |k, v|
332
- if hang
333
- writeln ','
334
- hang = false
335
- end
336
- write indent, fmt_key(k), " => "
337
- pprint_value v, indent
338
- hang = true
339
- end
340
- writeln
341
- writeln
342
- close_output
343
- add_brick(subdir,name) if brick
344
- else
345
- @logger.warn "NOT overwriting existing source file '#{rb_file(subdir, name)}'"
346
- end
347
- end
348
-
349
- def pprint_cfn_resource(name, options, brick=true)
350
- subdir = 'Resources'
351
- if open_output(subdir,name)
352
- @logger.info "Pretty print resource '#{name}' to '#{rb_file(subdir, name)}'"
353
- print_maintainer ''
354
- print_with_wrapper "resource #{fmt_string(name)}"
355
- indent = ' '
356
- hang = true
357
- options.each do |k, v|
358
- if hang
359
- writeln ','
360
- hang = false
361
- end
362
-
363
- case k
364
- when /^(Metadata|Properties)$/
365
- write "#{indent}#{fmt_key(k)} => "
366
- pprint_value options[k], indent
367
- hang = true
368
- else
369
- write "#{indent}#{fmt_key(k)} => "
370
- write "#{fmt(v)}"
371
- hang = true
372
- end
373
- end
374
- writeln
375
- close_output
376
- add_brick(subdir,name) if brick
377
- else
378
- @logger.warn "NOT overwriting existing source file '#{rb_file(subdir, name)}'"
379
- end
380
- end
381
-
382
- def pprint_value(val, indent)
383
- # Prefer to write the value on a single line if it's reasonable to do so
384
- single_line = is_single_line(val) || is_single_line_hack(val)
385
- if single_line && !is_multi_line_hack(val)
386
- s = fmt(val)
387
- if s.length < 120 || is_single_line_hack(val)
388
- write s
389
- return
390
- end
391
- end
392
-
393
- # Print the value across multiple lines
394
- if val.is_a?(Hash)
395
- writeln "{"
396
- val.each do |k, v|
397
- write "#{indent} #{fmt_key(k)} => "
398
- pprint_value v, indent + ' '
399
- writeln ","
400
- end
401
- write "#{indent}}"
402
-
403
- elsif val.is_a?(Array)
404
- writeln "["
405
- val.each do |v|
406
- write "#{indent} "
407
- pprint_value v, indent + ' '
408
- writeln ","
409
- end
410
- write "#{indent}]"
411
-
412
- elsif val.is_a?(FnCall) && val.multiline && @opts[:functions] != 'raw'
413
- write val.name, "("
414
- args = val.arguments
415
- sep = ''
416
- sub_indent = indent + ' '
417
- if val.name == 'join' && args.length > 1
418
- pprint_value args[0], indent + ' '
419
- args = args[1..-1]
420
- sep = ','
421
- sub_indent = indent + ' '
422
- end
423
- unless args.empty?
424
- args.each do |v|
425
- writeln sep
426
- write sub_indent
427
- pprint_value v, sub_indent
428
- sep = ','
429
- end
430
- if val.name == 'join' && args.length > 1
431
- write ","
432
- end
433
- writeln
434
- write indent
435
- end
436
- write ")"
437
-
438
- else
439
- write fmt(val)
440
- end
441
- end
442
-
443
- def is_single_line(val)
444
- if val.is_a?(Hash)
445
- is_single_line(val.values)
446
- elsif val.is_a?(Array)
447
- val.empty? ||
448
- (val.length == 1 && is_single_line(val[0]) && !val[0].is_a?(Hash)) ||
449
- val.all? { |v| v.is_a?(String) }
450
- else
451
- true
452
- end
453
- end
454
-
455
- # Emo-specific hacks to force the desired output formatting
456
- def is_single_line_hack(val)
457
- is_array_of_strings_hack(val)
458
- end
459
-
460
- # Emo-specific hacks to force the desired output formatting
461
- def is_multi_line_hack(val)
462
- val.is_a?(Hash) && val['email']
463
- end
464
-
465
- # Emo-specific hacks to force the desired output formatting
466
- def is_array_of_strings_hack(val)
467
- val.is_a?(Array) && val.all? { |v| v.is_a?(String) } && val.grep(/\s/).empty? && (
468
- val.include?('autoscaling:EC2_INSTANCE_LAUNCH') ||
469
- val.include?('m1.small')
470
- )
471
- end
472
-
473
- def fmt(val)
474
- if val == {}
475
- '{}'
476
- elsif val == []
477
- '[]'
478
- elsif val.is_a?(Hash)
479
- '{ ' + (val.map { |k,v| fmt_key(k) + ' => ' + fmt(v) }).join(', ') + ' }'
480
- elsif val.is_a?(Array) && is_array_of_strings_hack(val)
481
- '%w(' + val.join(' ') + ')'
482
- elsif val.is_a?(Array)
483
- '[ ' + (val.map { |v| fmt(v) }).join(', ') + ' ]'
484
- elsif val.is_a?(FnCall) && val.arguments.empty?
485
- val.name
486
- elsif val.is_a?(FnCall)
487
- val.name + '(' + (val.arguments.map { |v| fmt(v) }).join(', ') + ')'
488
- elsif val.is_a?(String)
489
- fmt_string(val)
490
- elsif val == nil
491
- 'null'
492
- else
493
- val.to_s # number, boolean
494
- end
495
- end
496
-
497
- def fmt_key(s)
498
- ':' + (/^[a-zA-Z_]\w+$/ =~ s ? s : fmt_string(s)) # returns a symbol like :Foo or :'us-east-1'
499
- end
500
-
501
- def fmt_string(s)
502
- if /[^ -~]/ =~ s
503
- s.dump # contains, non-ascii or control char, return double-quoted string
504
- else
505
- '\'' + s.gsub(/([\\'])/, '\\\\\1') + '\'' # return single-quoted string, escape \ and '
506
- end
507
- end
508
120
 
509
121
  end
510
122
  end