cfndsl 0.0.5 → 0.0.6

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.
data/lib/cfndsl.rb CHANGED
@@ -1,448 +1,17 @@
1
1
  require 'json';
2
2
 
3
- class Module
4
- private
5
- def dsl_attr_setter(*symbols)
6
- ##
7
- # Create setter methods
8
- #
9
- # Usage:
10
- # class Something
11
- # dsl_attr_setter :Thing
12
- # end
13
- #
14
- # Generates a setter method like this one for each symbol in *symbols:
15
- #
16
- # def Thing(value)
17
- # @Thing = value
18
- # end
19
- #
20
- symbols.each do |symbol|
21
- class_eval do
22
- define_method(symbol) do |value|
23
- instance_variable_set( "@#{symbol}", value)
24
- end
25
- end
26
- end
27
- end
28
-
29
- ##
30
- # Plural names for lists of content objects
31
- #
32
-
33
- @@plurals = {
34
- :Metadata => :Metadata,
35
- :Property => :Properties
36
- }
37
-
38
- def dsl_content_object(*symbols)
39
- ##
40
- # Create object declaration methods.
41
- #
42
- # Usage:
43
- # Class Something
44
- # dsl_content_object :Stuff
45
- # end
46
- #
47
- # Generates methods like this:
48
- #
49
- # def Stuff(name, *values, &block)
50
- # @Stuffs ||= {}
51
- # @Stuffs[name] ||= CfnDsl::#{symbol}Definition.new(*values)
52
- # @Stuffs[name].instance_eval &block if block_given?
53
- # return @Stuffs[name]
54
- # end
55
- #
56
- # The effect of this is that you can then create named sub-objects
57
- # from the main object. The sub objects get stuffed into a container
58
- # on the main object, and the block is then evaluated in the context
59
- # of the new object.
60
- #
61
- symbols.each do |symbol|
62
- plural = @@plurals[symbol] || "#{symbol}s"
63
- class_eval %Q/
64
- def #{symbol} (name,*values,&block)
65
- name = name.to_s
66
- @#{plural} ||= {}
67
- @#{plural}[name] ||= CfnDsl::#{symbol}Definition.new(*values)
68
- @#{plural}[name].instance_eval &block if block_given?
69
- return @#{plural}[name]
70
- end /
71
- end
72
- end
73
- end
74
-
75
-
76
- module RefCheck
77
- ##
78
- # This module defines some methods for walking the reference tree
79
- # of various objects.
80
- #
81
- def references(refs)
82
- ##
83
- # Build up a set of references.
84
- #
85
- raise "Circular reference" if @_visited
86
-
87
- @_visited = true
88
-
89
- if( self.respond_to?(:get_references ) ) then
90
- self.get_references.each do |ref|
91
- refs[ref.to_s] = 1
92
- end
93
- end
94
-
95
- self.ref_children.each do |elem|
96
- elem.references(refs) if elem.respond_to?(:references)
97
- end
98
-
99
- @_visited = nil
100
-
101
- return refs
102
- end
103
-
104
- def ref_children
105
- return []
106
- end
107
-
108
- end
109
-
110
- class Array
111
- include RefCheck
112
- def ref_children
113
- return self
114
- end
115
- end
116
-
117
- class Hash
118
- include RefCheck
119
- def ref_children
120
- return self.values
121
- end
122
- end
123
-
124
- module CfnDsl
125
- module Functions
126
-
127
- def Ref(value)
128
- ##
129
- # Equivalent to the CloudFormation template built in function Ref
130
- RefDefinition.new(value)
131
- end
132
-
133
- def FnBase64( value )
134
- ##
135
- # Equivalent to the CloudFormation template built in function Fn::Base64
136
- Fn.new("Base64", value);
137
- end
138
-
139
- def FnFindInMap( map, key, value)
140
- ##
141
- # Equivalent to the CloudFormation template built in function Fn::FindInMap
142
- Fn.new("FindInMap", [map,key,value] )
143
- end
144
-
145
- def FnGetAtt(logicalResource, attribute)
146
- ##
147
- # Equivalent to the CloudFormation template built in function Fn::GetAtt
148
- Fn.new( "GetAtt", [logicalResource, attribute], [logicalResource] )
149
- end
150
-
151
- def FnGetAZs(region)
152
- ##
153
- # Equivalent to the CloudFormation template built in function Fn::GetAZs
154
- Fn.new("GetAZs", region)
155
- end
156
-
157
- def FnJoin(string, array)
158
- ##
159
- # Equivalent to the CloudFormation template built in function Fn::Join
160
- Fn.new("Join", [ string, array] )
161
- end
162
-
163
- def FnFormat(string, *arguments)
164
- ##
165
- # Usage
166
- # FnFormat( "This is a %0. It is 100%% %1","test", "effective")
167
- #
168
- # This will generate a call to Fn::Join that when evaluated will produce
169
- # the string "This is a test. It is 100% effective."
170
- #
171
- # Think of this as %0,%1, etc in the format string being replaced by the
172
- # corresponding arguments given after the format string. '%%' is replaced
173
- # by the '%' character.
174
- #
175
- # The actual Fn::Join call corresponding to the above FnFormat call would be
176
- # {"Fn::Join": ["",["This is a ","test",". It is 100","%"," ","effective"]]}
177
- array = [];
178
- string.scan( /(.*?)(%(%|\d+)|\z)/m ) do |x,y|
179
- array.push $1 if $1 && $1 != ""
180
- if( $3 == '%' ) then
181
- array.push '%'
182
- elsif( $3 ) then
183
- array.push arguments[ $3.to_i ]
184
- end
185
- end
186
-
187
- Fn.new("Join", ["", array])
188
- end
189
- end
190
-
191
-
192
- class JSONable
193
- ##
194
- # This is the base class for just about everything useful in the
195
- # DSL. It knows how to turn DSL Objects into the corresponding
196
- # json, and it lets you create new built in function objects
197
- # from inside the context of a dsl object.
198
-
199
- include Functions
200
- extend Functions
201
- include RefCheck
202
-
203
- def to_json(*a)
204
- ##
205
- # Use instance variables to build a json object. Instance
206
- # variables that begin with a single underscore are elided.
207
- # Instance variables that begin with two underscores have one of
208
- # them removed.
209
- hash = {}
210
- self.instance_variables.each do |var|
211
- name = var[1..-1]
212
-
213
- if( name =~ /^__/ ) then
214
- # if a variable starts with double underscore, strip one off
215
- name = name[1..-1]
216
- elsif( name =~ /^_/ ) then
217
- # Hide variables that start with single underscore
218
- name = nil
219
- end
220
-
221
- hash[name] = self.instance_variable_get var if name
222
- end
223
- hash.to_json(*a)
224
- end
225
-
226
- def ref_children
227
- return self.instance_variables.map { |var| self.instance_variable_get var }
228
- end
229
-
230
- def declare(&block)
231
- self.instance_eval &block if block_given?
232
- end
233
-
234
- end
235
-
236
- class Fn < JSONable
237
- ##
238
- # Handles all of the Fn:: objects
239
- def initialize( function, argument, refs=[] )
240
- @function = function
241
- @argument = argument
242
- @_refs = refs
243
- end
244
-
245
- def to_json(*a)
246
- hash = {}
247
- hash["Fn::#{@function}"] = @argument
248
- hash.to_json(*a)
249
- end
250
-
251
- def get_references()
252
- return @_refs
253
- end
254
-
255
- def ref_children
256
- return [@argument]
257
- end
258
- end
259
-
260
-
261
- class RefDefinition < JSONable
262
- ##
263
- # Handles the Ref objects
264
- def initialize( value )
265
- @Ref = value
266
- end
267
-
268
- def get_references()
269
- [@Ref]
270
- end
271
- end
272
-
273
-
274
- class PropertyDefinition < JSONable
275
- ##
276
- # Handles property objects for Resources
277
- #
278
- # Usage
279
- # Resource("aaa") {
280
- # Property("propName", "propValue" )
281
- # }
282
- #
283
- def initialize(value)
284
- @value = value;
285
- end
286
-
287
- def to_json(*a)
288
- @value.to_json(*a)
289
- end
290
- end
291
-
292
- class MappingDefinition < JSONable
293
- ##
294
- # Handles mapping objects
295
- #
296
- # Usage:
297
- # Mapping("AWSRegionArch2AMI", {
298
- # "us-east-1" => { "32" => "ami-6411e20d", "64" => "ami-7a11e213" },
299
- # "us-west-1" => { "32" => "ami-c9c7978c", "64" => "ami-cfc7978a" },
300
- # "eu-west-1" => { "32" => "ami-37c2f643", "64" => "ami-31c2f645" },
301
- # "ap-southeast-1" => { "32" => "ami-66f28c34", "64" => "ami-60f28c32" },
302
- # "ap-northeast-1" => { "32" => "ami-9c03a89d", "64" => "ami-a003a8a1" }
303
- # })
304
-
305
- def initialize(value)
306
- @value = value
307
- end
308
-
309
- def to_json(*a)
310
- @value.to_json(*a)
311
- end
312
- end
313
-
314
- class ResourceDefinition < JSONable
315
- ##
316
- # Handles Resource objects
317
- dsl_attr_setter :Type, :DependsOn, :DeletionPolicy
318
- dsl_content_object :Property, :Metadata
319
-
320
- def get_references()
321
- refs = []
322
- if @DependsOn then
323
- if( @DependsOn.respond_to?(:each) ) then
324
- @DependsOn.each do |dep|
325
- refs.push dep
326
- end
327
- end
328
-
329
- if( @DependsOn.instance_of?(String) ) then
330
- refs.push @DependsOn
331
- end
332
- end
333
-
334
- refs
335
- end
336
- end
337
-
338
- class MetadataDefinition < JSONable
339
- ##
340
- # Handles Metadata objects
341
- end
342
-
343
-
344
- class ParameterDefinition < JSONable
345
- ##
346
- # Handles input parameter objects
347
- dsl_attr_setter :Type, :Default, :NoEcho, :AllowedValues, :AllowedPattern, :MaxLength, :MinLength, :MaxValue, :MinValue, :Description, :ConstraintDescription
348
- def initialize
349
- @Type = :String
350
- end
351
-
352
- def String
353
- @Type = :String
354
- end
355
-
356
- def Number
357
- @Type = :Number
358
- end
359
-
360
- def CommaDelimitedList
361
- @Type = :CommaDelimitedList
362
- end
363
-
364
- def to_hash()
365
- h = {}
366
- h[:Type] = @Type;
367
- h[:Default] = @Default if @Default
368
- end
369
- end
370
-
371
- class OutputDefinition < JSONable
372
- ##
373
- # Handles Output objects
374
- dsl_attr_setter :Value, :Description
375
-
376
- def initialize( value=nil)
377
- @Value = value if value
378
- end
379
- end
380
-
381
- class CloudFormationTemplate < JSONable
382
- ##
383
- # Handles the overall template object
384
- dsl_attr_setter :AWSTemplateFormatVersion, :Description
385
- dsl_content_object :Parameter, :Output, :Resource, :Mapping
386
-
387
- def initialize
388
- @AWSTemplateFormatVersion = "2010-09-09"
389
- end
390
-
391
- def generateOutput()
392
- puts self.to_json # uncomment for pretty printing # {:space => ' ', :indent => ' ', :object_nl => "\n", :array_nl => "\n" }
393
- end
394
-
395
- @@globalRefs = {
396
- "AWS::NotificationARNs" => 1,
397
- "AWS::Region" => 1,
398
- "AWS::StackId" => 1,
399
- "AWS::StackName" => 1
400
- }
401
-
402
- def isValidRef( ref, origin=nil)
403
- ref = ref.to_s
404
- origin = origin.to_s if origin
405
-
406
- return true if @@globalRefs.has_key?( ref )
407
-
408
- return true if @Parameters && @Parameters.has_key?( ref )
409
-
410
- if( @Resources.has_key?( ref ) ) then
411
- return !origin || !@_ResourceRefs || !@_ResourceRefs[ref] || !@_ResourceRefs[ref].has_key?(origin)
412
- end
413
-
414
- return false
415
- end
416
-
417
- def checkRefs()
418
- invalids = []
419
- @_ResourceRefs = {}
420
- if(@Resources) then
421
- @Resources.keys.each do |resource|
422
- @_ResourceRefs[resource.to_s] = @Resources[resource].references({})
423
- end
424
- @_ResourceRefs.keys.each do |origin|
425
- @_ResourceRefs[origin].keys.each do |ref|
426
- invalids.push "Invalid Reference: Resource #{origin} refers to #{ref}" unless isValidRef(ref,origin)
427
- end
428
- end
429
- end
430
- outputRefs = {}
431
- if(@Outputs) then
432
- @Outputs.keys.each do |resource|
433
- outputRefs[resource.to_s] = @Outputs[resource].references({})
434
- end
435
- outputRefs.keys.each do |origin|
436
- outputRefs[origin].keys.each do |ref|
437
- invalids.push "Invalid Reference: Output #{origin} refers to #{ref}" unless isValidRef(ref,nil)
438
- end
439
- end
440
- end
441
- return invalids.length>0 ? invalids : nil
442
- end
443
-
444
- end
445
- end
3
+ require 'cfndsl/module'
4
+ require 'cfndsl/Errors'
5
+ require 'cfndsl/RefCheck'
6
+ require 'cfndsl/JSONable'
7
+ require 'cfndsl/Types'
8
+ require 'cfndsl/Properties'
9
+ require 'cfndsl/Mappings'
10
+ require 'cfndsl/Resources'
11
+ require 'cfndsl/Metadata'
12
+ require 'cfndsl/Parameters'
13
+ require 'cfndsl/Outputs'
14
+ require 'cfndsl/CloudFormationTemplate'
446
15
 
447
16
  def CloudFormation(&block)
448
17
  x = CfnDsl::CloudFormationTemplate.new
@@ -451,6 +20,8 @@ def CloudFormation(&block)
451
20
  if( invalid_references ) then
452
21
  puts invalid_references.join("\n");
453
22
  exit(-1)
23
+ elsif( CfnDsl::Errors.errors? ) then
24
+ CfnDsl::Errors.report
454
25
  else
455
26
  x.generateOutput
456
27
  end