aws-cfn-compiler 0.9.3 → 0.9.4

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 CHANGED
@@ -1,15 +1,15 @@
1
1
  ---
2
2
  !binary "U0hBMQ==":
3
3
  metadata.gz: !binary |-
4
- YTk3ODBmY2U3YTQzODI2YTBmNDQ5NDIwYTcxNjQxNzQ0YmVkZTZkYw==
4
+ NWQ2NjYyYzZmNmE5ZmU1ODhiYTU3YzA0NDhlOWEzNDY0YzU3NTM1Yg==
5
5
  data.tar.gz: !binary |-
6
- MzUxNDNkOWU4ZDRjZTI4OWFmNzc1OWVhYmM5MjVmYThlNjI4MTcyNA==
6
+ MzY4NzNlMzk3MjFmYzJhM2QwYTQxMDcxZTU1ZmFjZjdkYjE0OGQyYw==
7
7
  SHA512:
8
8
  metadata.gz: !binary |-
9
- YjNjNDU4NjEyYWVlZDhhNTA1NDM2ODkyYmQ4MWE3NWNjNWQzMGViMDMxYmRk
10
- OTExOGMzN2Q5MGI4ODkyNmI4NDg5MWI4OWZhMTU1MGE2ODQ2MDU1ZmI4N2Q5
11
- YzZiNDMwMjM2MGQ1YmZkZjUyZjM3YTY4YmJkZDE2MDNmZTY2YTQ=
9
+ MmIwZGVkN2RjZDU1NDVjZGQ0MjA2YWU2ZWFjOWEwYzk3MzEzM2EzMWJkM2I1
10
+ OGM3ZjYzZGJmOWIxZTY4MmU3Mjk3YTFhZjRjMzQxN2EwMzI0MmVhMjlhYTFk
11
+ ZTM0MTEzYTY3ZGI1OGRjN2I2MzdhZmNlZTNkYjRhZDQxYmZjYWQ=
12
12
  data.tar.gz: !binary |-
13
- MWIwYTZkMGQwZjAyMGIxZmM2OThjM2NiMzQ4YTM3ZTAxN2I5YmU3ZTQ3MmMw
14
- N2RhZmI0MzdhNzk0MTNkYzBmNmY3NjM1NjY2Yjk0NGQyYzdiN2M2NDFhODk2
15
- MGJhZDFlMmY3ZDRiNjZmOWY0YjAyODkzOGMwNzk2ZjA4ZDVlNjg=
13
+ NGJiYjQyYjgzYTczYjZiNDVkOWY0ZDZlNTVhYWMwMjQ0YTMxMzIyZGZiYmYx
14
+ ZGY2NTgxZjkyMDk1M2VhYTkyNDZkNDg0OWEwMjJiZjZiMzBmZmM3YmYzZjg4
15
+ NzIwOTllMTc4MzRmZDI5NGU2ZGIxMDhjMmU1ZTdlNDk4YWQzNTE=
@@ -23,6 +23,7 @@ Gem::Specification.new do |spec|
23
23
  spec.add_dependency 'json'
24
24
  spec.add_dependency 'slop'
25
25
  spec.add_dependency 'inifile'
26
+ spec.add_dependency 'semverse', '>= 1.1.0'
26
27
  spec.add_dependency 'aws-cfn-dsl', '>= 0.9.2'
27
28
  spec.add_dependency 'dldinternet-mixlib-cli', '>= 0.2.0'
28
29
  spec.add_dependency 'dldinternet-mixlib-logging', '>= 0.4.0'
data/aws-cfn-compiler.iml CHANGED
@@ -6,7 +6,7 @@
6
6
  <component name="NewModuleRootManager" inherit-compiler-output="true">
7
7
  <exclude-output />
8
8
  <content url="file://$MODULE_DIR$" />
9
- <orderEntry type="jdk" jdkName="RVM: ruby-1.9.3-p547 [aws-cfn-compile]" jdkType="RUBY_SDK" />
9
+ <orderEntry type="jdk" jdkName="RVM: ruby-1.9.3-p547 [aws-cfn-yats]" jdkType="RUBY_SDK" />
10
10
  <orderEntry type="sourceFolder" forTests="false" />
11
11
  <orderEntry type="module" module-name="aws-cfn-dsl" />
12
12
  <orderEntry type="module-library">
@@ -28,18 +28,19 @@
28
28
  </orderEntry>
29
29
  <orderEntry type="module" module-name="dldinternet-mixlib-cli" />
30
30
  <orderEntry type="module" module-name="dldinternet-mixlib-logging" />
31
- <orderEntry type="library" scope="PROVIDED" name="awesome_print (v1.2.0, RVM: ruby-1.9.3-p547 [aws-cfn-compile]) [gem]" level="application" />
32
- <orderEntry type="library" scope="PROVIDED" name="detabulator (v0.1.0, RVM: ruby-1.9.3-p547 [aws-cfn-compile]) [gem]" level="application" />
33
- <orderEntry type="library" scope="PROVIDED" name="inifile (v2.0.2, RVM: ruby-1.9.3-p547 [aws-cfn-compile]) [gem]" level="application" />
34
- <orderEntry type="library" scope="PROVIDED" name="json (v1.8.1, RVM: ruby-1.9.3-p547 [aws-cfn-compile]) [gem]" level="application" />
35
- <orderEntry type="library" scope="PROVIDED" name="json_pure (v1.8.1, RVM: ruby-1.9.3-p547 [aws-cfn-compile]) [gem]" level="application" />
36
- <orderEntry type="library" scope="PROVIDED" name="little-plugger (v1.1.3, RVM: ruby-1.9.3-p547 [aws-cfn-compile]) [gem]" level="application" />
37
- <orderEntry type="library" scope="PROVIDED" name="logging (v1.8.2, RVM: ruby-1.9.3-p547 [aws-cfn-compile]) [gem]" level="application" />
38
- <orderEntry type="library" scope="PROVIDED" name="mixlib-cli (v1.5.0, RVM: ruby-1.9.3-p547 [aws-cfn-compile]) [gem]" level="application" />
39
- <orderEntry type="library" scope="PROVIDED" name="multi_json (v1.10.1, RVM: ruby-1.9.3-p547 [aws-cfn-compile]) [gem]" level="application" />
40
- <orderEntry type="library" scope="PROVIDED" name="psych (v2.0.5, RVM: ruby-1.9.3-p547 [aws-cfn-compile]) [gem]" level="application" />
41
- <orderEntry type="library" scope="PROVIDED" name="rake (v10.3.2, RVM: ruby-1.9.3-p547 [aws-cfn-compile]) [gem]" level="application" />
42
- <orderEntry type="library" scope="PROVIDED" name="slop (v3.5.0, RVM: ruby-1.9.3-p547 [aws-cfn-compile]) [gem]" level="application" />
31
+ <orderEntry type="library" scope="PROVIDED" name="awesome_print (v1.2.0, RVM: ruby-1.9.3-p547 [aws-cfn-yats]) [gem]" level="application" />
32
+ <orderEntry type="library" scope="PROVIDED" name="detabulator (v0.1.0, RVM: ruby-1.9.3-p547 [aws-cfn-yats]) [gem]" level="application" />
33
+ <orderEntry type="library" scope="PROVIDED" name="inifile (v2.0.2, RVM: ruby-1.9.3-p547 [aws-cfn-yats]) [gem]" level="application" />
34
+ <orderEntry type="library" scope="PROVIDED" name="json (v1.8.1, RVM: ruby-1.9.3-p547 [aws-cfn-yats]) [gem]" level="application" />
35
+ <orderEntry type="library" scope="PROVIDED" name="json_pure (v1.8.1, RVM: ruby-1.9.3-p547 [aws-cfn-yats]) [gem]" level="application" />
36
+ <orderEntry type="library" scope="PROVIDED" name="little-plugger (v1.1.3, RVM: ruby-1.9.3-p547 [aws-cfn-yats]) [gem]" level="application" />
37
+ <orderEntry type="library" scope="PROVIDED" name="logging (v1.8.2, RVM: ruby-1.9.3-p547 [aws-cfn-yats]) [gem]" level="application" />
38
+ <orderEntry type="library" scope="PROVIDED" name="mixlib-cli (v1.5.0, RVM: ruby-1.9.3-p547 [aws-cfn-yats]) [gem]" level="application" />
39
+ <orderEntry type="library" scope="PROVIDED" name="multi_json (v1.10.1, RVM: ruby-1.9.3-p547 [aws-cfn-yats]) [gem]" level="application" />
40
+ <orderEntry type="library" scope="PROVIDED" name="psych (v2.0.5, RVM: ruby-1.9.3-p547 [aws-cfn-yats]) [gem]" level="application" />
41
+ <orderEntry type="library" scope="PROVIDED" name="rake (v10.3.2, RVM: ruby-1.9.3-p547 [aws-cfn-yats]) [gem]" level="application" />
42
+ <orderEntry type="library" scope="PROVIDED" name="semverse (v1.1.0, RVM: ruby-1.9.3-p547 [aws-cfn-yats]) [gem]" level="application" />
43
+ <orderEntry type="library" scope="PROVIDED" name="slop (v3.5.0, RVM: ruby-1.9.3-p547 [aws-cfn-yats]) [gem]" level="application" />
43
44
  </component>
44
45
  </module>
45
46
 
@@ -23,6 +23,36 @@ module Aws
23
23
  abort! 'No Resources!?' unless compiled['Resources']
24
24
  logStep 'Validating template'
25
25
 
26
+ prms = compiled['Parameters'].keys rescue []
27
+ compiled['Parameters'].each do |name,hash|
28
+ abort! "Parameter #{name} has an invalid compiled block!\n#{hash.ai}" unless hash.is_a?(Hash)
29
+ if hash['Type']
30
+ unless %w(String Number CommaDelimitedList).include?(hash['Type'])
31
+ abort! "Parameter #{name} has an invalid type: #{hash['Type']}"
32
+ end
33
+ end
34
+ if hash['Default']
35
+ unless hash['Default'].is_a?(String)
36
+ abort! "Parameter #{name} has an invalid default (Must be string): #{hash['Default']}"
37
+ end
38
+ end
39
+ end
40
+ @logger.info ' Parameters validated'
41
+
42
+ # Mappings => Resources
43
+ funs = find_fns(compiled) #.select { |a| !(a =~ /^AWS::/) }
44
+
45
+ bad = []
46
+ funs.each do |fn|
47
+ unless @valid_functions.include?(fn)
48
+ bad << fn
49
+ end
50
+ end
51
+ if bad.size > 0
52
+ abort! "Encountered unsupported function(s) ...\n#{bad.ai}\nSupported functions are:\n#{@valid_functions.ai}"
53
+ end
54
+ @logger.info ' Functions validated'
55
+
26
56
  # Mappings => Resources
27
57
  maps = find_maps(compiled) #.select { |a| !(a =~ /^AWS::/) }
28
58
  mpgs = compiled['Mappings'].nil? ? [] : compiled['Mappings'].keys
@@ -46,10 +76,10 @@ module Aws
46
76
 
47
77
  # Parameters => Resources => Outputs
48
78
  refs = find_refs(compiled).select { |a,_| !(a =~ /^AWS::/) }
49
- prms = compiled['Parameters'].keys rescue []
50
79
  rscs = compiled['Resources'].keys
80
+ cnds = compiled['Conditions'].keys rescue []
51
81
  # outs = compiled['Outputs'].keys rescue []
52
- names = rscs+prms
82
+ names = rscs+prms+cnds
53
83
 
54
84
  net = (refs.keys-names)
55
85
  unless net.empty?
@@ -26,14 +26,33 @@ module Aws
26
26
  'Name' => ::Aws::Cfn::Compiler.name,
27
27
  'Version' => ::Aws::Cfn::Compiler::VERSION,
28
28
  }
29
+ when :Specification
30
+ File.basename(@config[:specification])
31
+ when :Template
32
+ File.basename(@config[:template])
29
33
  when :DescriptionString
30
- "#{meta(:Description)} - #{meta(:Name)} v#{meta(:Version)}; Parents: #{meta(:DependsOn)} [Compiled with #{meta(:Compiler,:Name)} v#{meta(:Compiler,:Version)}]"
34
+ v = nil
35
+ begin
36
+ parents = "Parents: #{meta(:DependsOn)} "
37
+ rescue
38
+ parents = ''
39
+ end
40
+ # noinspection RubyExpressionInStringInspection
41
+ template = '#{meta(:Project,:Description)}(#{meta(:Project,:Name)}) - #{meta(:Name)} v#{meta(:Version)}; #{parents} [Compiled with #{meta(:Compiler,:Name)} v#{meta(:Compiler,:Version)}]'
42
+ begin
43
+ eval %(v = "#{template}" )
44
+ rescue Exception => e
45
+ raise e.message + "\nIn:\n" + template
46
+ end
47
+ v
31
48
  else
32
49
  get_meta(spec, args.to_s)
33
50
  end
34
51
  elsif args.is_a?(String)
35
52
  if spec[args]
36
53
  spec[args]
54
+ else
55
+ raise "Meta:'#{args}' not set"
37
56
  end
38
57
  else
39
58
  nil
@@ -46,6 +65,8 @@ module Aws
46
65
  def meta(*args)
47
66
  if @spec['Meta']
48
67
  get_meta(@spec['Meta'],args)
68
+ else
69
+ raise "Specification contained no metadata while expanding #{args}"
49
70
  end
50
71
  end
51
72
 
@@ -60,17 +81,6 @@ module Aws
60
81
  'compiled template'
61
82
  end
62
83
 
63
- begin
64
- if desc.match(%r'#\{.+?\}')
65
- eval %(desc = "#{desc}")
66
- end
67
- rescue
68
- # noop
69
- end
70
- # ap meta(:Version)
71
- # ap meta(:Compiler,:Name)
72
- # ap meta(:Compiler,:Version)
73
-
74
84
  vers = if @config[:formatversion]
75
85
  @config[:formatversion]
76
86
  else
@@ -80,17 +90,63 @@ module Aws
80
90
  '2010-09-09'
81
91
  end
82
92
  end
93
+
94
+ desc = compile_value(desc)
95
+
83
96
  # [2014-06-29 Christo] IIRC it is important that the section names be strings instead of symbols ...
84
97
  # noinspection RubyStringKeysInHashInspection
85
98
  compiled =
86
- {
87
- 'AWSTemplateFormatVersion' => vers,
88
- 'Description' => desc,
89
- 'Mappings' => @items['Mappings'],
90
- 'Parameters' => @items['Parameters'],
91
- 'Resources' => @items['Resources'],
92
- 'Outputs' => @items['Outputs'],
93
- }
99
+ {
100
+ 'AWSTemplateFormatVersion' => vers,
101
+ 'Description' => desc,
102
+ 'Mappings' => @items['Mappings'],
103
+ 'Parameters' => @items['Parameters'],
104
+ 'Conditions' => @items['Conditions'],
105
+ 'Resources' => @items['Resources'],
106
+ 'Outputs' => @items['Outputs'],
107
+ }
108
+
109
+ @all_sections.each do |section|
110
+ value = compile_value(@items[section])
111
+ compiled[section] = value if value
112
+ end
113
+ compiled
114
+ end
115
+
116
+ def compile_value(expr)
117
+ begin
118
+ if expr.is_a?(Hash)
119
+ val = expr
120
+ expr.each do |k,v|
121
+ val[k] = compile_value(v)
122
+ end
123
+ val
124
+ elsif expr.is_a?(Array)
125
+ expr.map{ |e|
126
+ compile_value(e)
127
+ }
128
+ elsif expr.is_a?(Symbol)
129
+ expr
130
+ elsif expr.is_a?(NilClass)
131
+ expr
132
+ elsif expr.is_a?(TrueClass)
133
+ expr
134
+ elsif expr.is_a?(FalseClass)
135
+ expr
136
+ elsif expr.is_a?(Fixnum)
137
+ expr
138
+ elsif expr.is_a?(String)
139
+ val = expr
140
+ if expr.match(%r'#\{.+?\}')
141
+ eval %(val = "#{expr}")
142
+ end
143
+ val
144
+ else
145
+ raise "The expression type #{expr.class.name} cannot be compiled!\n#{expr}"
146
+ end
147
+ rescue Exception => e
148
+ abort! "Specification expression error: #{e.message} on '#{expr}'"
149
+ end
94
150
  end
95
151
 
96
152
  def find_refs(hash, type='Reference', parent='')
@@ -98,19 +154,25 @@ module Aws
98
154
  newparent = parent
99
155
  if hash.is_a? Hash
100
156
  hash.keys.collect do |key|
101
- if %w{Mappings Parameters Resources Outputs}.include? key
157
+ if @all_sections.include? key
102
158
  type = key#.gsub(/s$/, '')
103
159
  newparent = key
104
- elsif %w{Mappings Parameters Resources Outputs}.include? parent
160
+ elsif @all_sections.include? parent
105
161
  newparent = key
106
162
  end
107
163
  if %w{Ref}.include? key
108
164
  h = { hash[key] => [type,newparent] }
109
165
  elsif 'Fn::GetAtt' == key
110
166
  h = { hash[key].first => [type,newparent] }
111
- # elsif %w{SourceSecurityGroupName CacheSecurityGroupNames SecurityGroupNames}.include? key
112
- # a = find_refs(hash[key],type,newparent)
113
- # h = merge(h, a, *[type,newparent])
167
+ elsif 'DependsOn' == key
168
+ if hash[key].is_a?(Array)
169
+ h = {}
170
+ hash[key].map { |dep|
171
+ h[dep] = [type,newparent]
172
+ }
173
+ else
174
+ h = { hash[key] => [type,newparent] }
175
+ end
114
176
  else
115
177
  a = find_refs(hash[key],type,newparent)
116
178
  h = merge(h, a, *[type,newparent])
@@ -143,9 +205,26 @@ module Aws
143
205
  h
144
206
  end
145
207
 
208
+ def find_fns(hash)
209
+ a = []
210
+ if hash.is_a? Hash
211
+ hash.each do |key,val|
212
+ if key.match %r'^Fn::'
213
+ a << key
214
+ end
215
+ a << find_fns(val)
216
+ end
217
+ elsif hash.is_a? Array
218
+ hash.collect{|e|
219
+ a << find_fns(e)
220
+ }
221
+ end
222
+ r = a.flatten.compact.uniq
223
+ r
224
+ end
225
+
146
226
  def find_maps(hash)
147
227
  if hash.is_a? Hash
148
- tr = []
149
228
  hash.keys.collect do |key|
150
229
  if 'Fn::FindInMap' == key
151
230
  hash[key].first
@@ -192,20 +271,33 @@ module Aws
192
271
  ref = match[2]
193
272
  # noinspection RubyParenthesesAroundConditionInspection
194
273
  if (subm = match[1].match(%r'^(.+?)/(.+)$'))
274
+ # Stack referenced with a path
195
275
  @config[:brick_path_list].each do |p|
196
276
  path = File.join(p,subm[1]) # File.dirname(@config[:directory])
197
- unless File.directory?(path)
277
+ if File.directory?(path)
278
+ break
279
+ else
198
280
  path = nil
199
281
  end
200
282
  end
201
283
  sub = subm[2]
202
284
  else
203
- # sub = nil
204
- # path = File.join(File.dirname(@config[:directory]),match[1])
205
- @config[:brick_path_list].each do |p|
206
- path = File.join(p,match[1]) # File.dirname(@config[:directory])
207
- unless File.directory?(path)
208
- path = nil
285
+ # Stack referenced on stack_path ...
286
+ pstk = @config[:stack_path_list].map{ |p|
287
+ if File.basename(p) == match[1]
288
+ p
289
+ else
290
+ []
291
+ end
292
+ }.flatten.shift
293
+ if pstk
294
+ parseList(@config[:brick_path],':').each do |p|
295
+ path = File.join(pstk,p) # File.dirname(@config[:directory])
296
+ if File.directory?(path)
297
+ break
298
+ else
299
+ path = nil
300
+ end
209
301
  end
210
302
  end
211
303
  end
@@ -54,14 +54,19 @@ module Aws
54
54
  res
55
55
  end
56
56
 
57
- def vet_path(dir,base=nil,rel=false)
57
+ def get_brick_path(dir,rsrc,start=nil,rel=false)
58
+ File.join(get_brick_dirname(dir,rsrc,start,rel),rsrc)
59
+ end
60
+
61
+ def get_brick_dirname(dir,rsrc,start=nil,rel=false)
58
62
  path = nil
63
+ base = nil
59
64
  @config[:brick_path_list].each do |p|
60
65
  if rel
61
66
  # base = File.realpath(File.expand_path(File.join(@config[:directory], base)))
62
67
  base = File.realpath(File.expand_path(File.join(p, base)))
63
68
  else
64
- base = p unless base
69
+ base = start || p
65
70
  end
66
71
  [dir, dir.downcase].each do |d|
67
72
  path = File.join(base, dir)
@@ -69,13 +74,26 @@ module Aws
69
74
  break
70
75
  end
71
76
  end
72
- if File.directory?(path)
77
+ fileglob = File.join(path,rsrc)
78
+ if File.exists?(fileglob)
79
+ candidates = [fileglob]
80
+ else
81
+ fileglob += ".*"
82
+ candidates = Dir.glob(fileglob).map{ |e|
83
+ if e.match(%r'\.#{@format_regex}$')
84
+ e
85
+ else
86
+ []
87
+ end
88
+ }.flatten
89
+ end
90
+ if File.directory?(path) and candidates.size > 0
73
91
  break
74
92
  end
75
93
  end
76
94
  patn = path
77
95
  unless @config[:expandedpaths]
78
- patn = short_path(path)
96
+ patn = short_path(path,3)
79
97
  end
80
98
 
81
99
  unless File.directory?(path)
@@ -9,6 +9,7 @@ module Aws
9
9
  setup_options
10
10
 
11
11
  @opts.on :b, :brick_path=, 'A list of paths to template components (bricks). May also set as the BRICK_PATH environment variable.', as: String
12
+ @opts.on :S, :stack_path=, 'A list of paths to stacks. May also set as the STACK_PATH environment variable.', as: String
12
13
  @opts.on :F, :format=, 'The output format of the components. [JSON|YAML|Ruby]', { as: String, match: @format_regex, default: 'yaml' }
13
14
  @opts.on :s, :specification=, 'The specification to use when selecting components. A JSON or YAML file', { as: String
14
15
  }
@@ -44,35 +45,70 @@ module Aws
44
45
  @optional[:directory] = true
45
46
  setup_config
46
47
 
47
- if @config[:brick_path]
48
- brick_path = @config[:brick_path]
49
- elsif ENV['BRICK_PATH']
50
- brick_path = ENV['BRICK_PATH']
48
+ set_config_path_option(@config[:stack_path],'STACK_PATH',@config[:directory] || '.',:stack_path_list,'stack path')
49
+ set_config_path_option(@config[:brick_path],'BRICK_PATH',@config[:directory],:brick_path_list,'brick path',:stack_path_list)
50
+
51
+ end
52
+
53
+ def set_config_path_option(value,envstr,default,listsym,type,relto=nil)
54
+ if value
55
+ path = value
56
+ elsif ENV[envstr]
57
+ path = ENV[envstr]
51
58
  else
52
- brick_path = @config[:directory]
59
+ path = default
53
60
  end
54
- if brick_path
55
- @config[:brick_path_list] = parseList(brick_path,':','parsePath')
56
-
57
- mia = []
58
- @config[:brick_path_list].each do |path|
59
- unless File.directory? path
60
- mia << path
61
+ if path
62
+ @config[listsym] = parseList(path, ':')
63
+ newlist = @config[listsym].map{ |r|
64
+ if relto
65
+ if r.match(%r'^/')
66
+ # Absolute paths not relative to stacks
67
+ r
68
+ else
69
+ a = []
70
+ @config[relto].each{|b|
71
+ # noinspection RubyAssignmentExpressionInConditionalInspection
72
+ if File.directory?(p=File.expand_path(File.join(b,r)))
73
+ a << File.realpath(p)
74
+ end
75
+ }
76
+ a
77
+ end
78
+ else
79
+ File.expand_path(r)
61
80
  end
62
- end
81
+ }
82
+ @config[listsym] = newlist.flatten.uniq
83
+
84
+ mia = find_mia(@config[listsym])
63
85
 
64
86
  if mia.size > 0
65
- hints = []
66
- mia.each do |p|
67
- hints << hint_paths(p,Dir.pwd)
68
- end
69
- hints.flatten!
70
- abort! "Invalid brick path: #{brick_path}! #{mia.size > 1 ? 'These' : 'This'} path#{mia.size > 1 ? 's' : ''} does not exist or cannot be read!\n #{mia.join("\n\t")}
71
- Did you mean one of these? #{@config[:expandedpaths] ? "(Above #{Dir.pwd})" : ""}
72
- \t#{hints.join("\n\t")}\n"
87
+ report_mia(path, mia, type)
73
88
  end
74
89
  end
90
+ end
75
91
 
92
+ def report_mia(path, mia, type)
93
+ hints = []
94
+ mia.each do |p|
95
+ hints << hint_paths(p, Dir.pwd)
96
+ end
97
+ hints.flatten!
98
+ abort! "Invalid #{type}: #{path}!
99
+ #{mia.size > 1 ? 'These' : 'This'} path#{mia.size > 1 ? 's' : ''} does not exist or cannot be read!\n #{mia.join("\n\t")}
100
+ Did you mean one of these? #{@config[:expandedpaths] ? "(Above #{Dir.pwd})" : ""}
101
+ \t#{hints.join("\n\t")}\n"
102
+ end
103
+
104
+ def find_mia(list)
105
+ mia = []
106
+ list.each do |path|
107
+ unless File.directory? path
108
+ mia << path
109
+ end
110
+ end
111
+ mia
76
112
  end
77
113
 
78
114
  def hint_paths(p,pwd,n=0,rel='',f=nil)
@@ -1,15 +1,59 @@
1
+ require 'rubygems/dependency'
2
+ require 'semverse'
3
+ require 'awesome_print'
4
+
1
5
  module Aws
2
6
  module Cfn
3
7
  module Compiler
4
8
  module Parse
5
9
 
6
10
  def parse
11
+ parse_meta(@spec)
7
12
  @dsl ||= Aws::Cfn::Dsl::Template.new(@config[:directory])
8
- %w( Mappings Parameters Resources Outputs ).each do |section|
13
+ @all_sections.each do |section|
9
14
  parse_section(section,@spec)
10
15
  end
11
16
  end
12
17
 
18
+ def parse_meta(spec)
19
+ begin
20
+ reqs = meta(:Require)
21
+ if reqs
22
+ reqs.each do |name,args|
23
+ requirement(name,args)
24
+ end
25
+ end
26
+ rescue Exception => e
27
+ # pass ... abort! e
28
+ end
29
+ end
30
+
31
+ def requirement(name, *args)
32
+
33
+ #options = args.last.is_a?(Hash) ? args.pop.dup : {}
34
+ constraint = case args.class.name
35
+ when /Array/
36
+ args.shift
37
+ when /Symbol/
38
+ args.to_s
39
+ when /String/
40
+ args
41
+ else
42
+ raise "Unsupported class #{args.class.name} for #{args.ai}"
43
+ end
44
+ version,constraint = case name
45
+ when /Compiler/
46
+ [Aws::Cfn::Compiler::VERSION,constraint]
47
+ # when /MinVersion/
48
+ # [Aws::Cfn::Compiler::VERSION,">= #{constraint}"]
49
+ else
50
+ raise "#{name} constraint not supported"
51
+ end
52
+
53
+ raise "The constraint failed: #{name} #{constraint}" unless ::Semverse::Constraint.new(constraint).satisfies?(::Semverse::Version.new(version))
54
+
55
+ end
56
+
13
57
  # noinspection RubyGlobalVariableNamingConvention
14
58
  def parse_section(section,spec=nil)
15
59
  logStep "Parsing #{section}..."
@@ -23,9 +67,9 @@ module Aws
23
67
  @logger.debug "\tUsing #{section}::#{rsrc}"
24
68
  refp,sub,base,rel = map_resource_reference(rsrc)
25
69
  if refp.nil?
26
- path = vet_path(section)
70
+ path = get_brick_dirname(section, rsrc)
27
71
  else
28
- path = vet_path(sub ? sub : section, refp, rel)
72
+ path = get_brick_dirname(sub ? sub : section, rsrc, refp, rel)
29
73
  end
30
74
  abort! "No such directory: #{path} (I am here: #{Dir.pwd})" unless File.directory?(path)
31
75
  unless get[path]
@@ -74,7 +118,7 @@ module Aws
74
118
  @items[section].merge! item
75
119
 
76
120
  unless @items[section].keys.count == spec[section].count
77
- abort! " !! error: Suspect that a #{section} item was missed! \nRequested: #{spec[section]}\n Found: #{@items[section].keys}"
121
+ abort! " !! error: Suspect that a #{section} item was missed or not properly named (Brick name and file name mismatch?)! \nRequested: #{spec[section]}\n Found: #{@items[section].keys}"
78
122
  end
79
123
  end
80
124
 
@@ -1,7 +1,7 @@
1
1
  module Aws
2
2
  module Cfn
3
3
  module Compiler
4
- VERSION = '0.9.3'
4
+ VERSION = '0.9.4'
5
5
  end
6
6
  end
7
7
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: aws-cfn-compiler
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.9.3
4
+ version: 0.9.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - PKinney
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-07-05 00:00:00.000000000 Z
11
+ date: 2014-07-07 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: awesome_print
@@ -86,6 +86,20 @@ dependencies:
86
86
  - - ! '>='
87
87
  - !ruby/object:Gem::Version
88
88
  version: '0'
89
+ - !ruby/object:Gem::Dependency
90
+ name: semverse
91
+ requirement: !ruby/object:Gem::Requirement
92
+ requirements:
93
+ - - ! '>='
94
+ - !ruby/object:Gem::Version
95
+ version: 1.1.0
96
+ type: :runtime
97
+ prerelease: false
98
+ version_requirements: !ruby/object:Gem::Requirement
99
+ requirements:
100
+ - - ! '>='
101
+ - !ruby/object:Gem::Version
102
+ version: 1.1.0
89
103
  - !ruby/object:Gem::Dependency
90
104
  name: aws-cfn-dsl
91
105
  requirement: !ruby/object:Gem::Requirement