aws-cfn-compiler 0.9.3 → 0.9.4

Sign up to get free protection for your applications and to get access to all the features.
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