UNPKG

9.31 kBtext/coffeescriptView Raw
1fs = require 'fs'
2vm = require 'vm'
3path = require 'path'
4CoffeeScript = require 'coffee-script'
5
6class CloudFormationTemplateContext
7 constructor: ->
8 @_resources = {}
9 @_parameters = {}
10 @_mappings = null
11 @_outputs = {}
12 @_description = null
13 @_conditions = null
14 @_metadatas = null
15 @Params = {}
16 @Resources = {}
17 @Mappings = {}
18 @Conditions = {}
19 @AWS =
20 AutoScaling:
21 AutoScalingGroup: null
22 LaunchConfiguration: null
23 ScalingPolicy: null
24 LifecycleHook: null
25 ScheduledAction: null
26 Trigger: null
27 CloudFormation:
28 Authentication: null
29 CustomResource: null
30 Stack: null
31 WaitCondition: null
32 WaitConditionHandle: null
33 CloudFront:
34 Distribution: null
35 CloudWatch:
36 Alarm: null
37 CodeDeploy:
38 Application: null
39 DeploymentConfig: null
40 DeploymentGroup: null
41 CodePipeline:
42 Pipeline: null
43 CustomActionType: null
44 Config:
45 ConfigRule: null
46 ConfigurationRecorder: null
47 DeliveryChannel: null
48 DirectoryService:
49 MicrosoftAD: null
50 SimpleAD: null
51 CloudTrail:
52 Trail: null
53 DataPipeline:
54 Pipeline: null
55 DynamoDB:
56 Table: null
57 EC2:
58 CustomerGateway: null
59 DHCPOptions: null
60 EIP: null
61 EIPAssociation: null
62 Instance: null
63 InternetGateway: null
64 NatGateway: null
65 NetworkAcl: null
66 NetworkAclEntry: null
67 NetworkInterface: null
68 PlacementGroup: null
69 Route: null
70 RouteTable: null
71 SecurityGroup: null
72 SecurityGroupIngress: null
73 SecurityGroupEgress: null
74 Subnet: null
75 SubnetNetworkAclAssociation: null
76 SubnetRouteTableAssociation: null
77 SpotFleet: null
78 Volume: null
79 VolumeAttachment: null
80 VPC: null
81 VPCDHCPOptionsAssociation: null
82 VPCEndpoint: null
83 VPCGatewayAttachment: null
84 VPNConnection: null
85 VPNGateway: null
86 ECR:
87 Repository: null
88 ECS:
89 Cluster: null
90 Service: null
91 TaskDefinition: null
92 ElastiCache:
93 CacheCluster: null
94 ParameterGroup: null
95 ReplicationGroup: null
96 SecurityGroup: null
97 SecurityGroupIngress: null
98 SubnetGroup: null
99 ElasticBeanstalk:
100 Application: null
101 ApplicationVersion: null
102 Environment: null
103 ConfigurationTemplate: null
104 ElasticLoadBalancing:
105 LoadBalancer: null
106 Elasticsearch:
107 Domain: null
108 EFS:
109 FileSystem: null
110 MountTarget: null
111 EMR:
112 Cluster: null
113 InstanceGroupConfig: null
114 Step: null
115 GameLift:
116 Alias: null
117 Build: null
118 Fleet: null
119 IAM:
120 AccessKey: null
121 Group: null
122 InstanceProfile: null
123 ManagedPolicy: null
124 Policy: null
125 Role: null
126 User: null
127 UserToGroupAddition: null
128 Kinesis:
129 Stream: null
130 KMS:
131 Key: null
132 Logs:
133 Destination: null
134 LogGroup: null
135 LogStream: null
136 MetricFilter: null
137 SubscriptionFilter: null
138 Lambda:
139 Alias: null
140 EventSourceMapping: null
141 Function: null
142 Permission: null
143 Version: null
144 OpsWorks:
145 App: null
146 Instance: null
147 Layer: null
148 Stack: null
149 Redshift:
150 Cluster: null
151 ClusterParameterGroup: null
152 ClusterSecurityGroup: null
153 ClusterSubnetGroup: null
154 RDS:
155 DBCluster: null
156 DBClusterParameterGroup: null
157 DBInstance: null
158 DBParameterGroup: null
159 DBSubnetGroup: null
160 DBSecurityGroup: null
161 DBSecurityGroupIngress: null
162 EventSubscription: null
163 OptionGroup: null
164 Route53:
165 RecordSet: null
166 RecordSetGroup: null
167 HostedZone: null
168 HealthCheck: null
169 SDB:
170 Domain: null
171 S3:
172 Bucket: null
173 BucketPolicy: null
174 SNS:
175 Topic: null
176 TopicPolicy: null
177 SQS:
178 Queue: null
179 QueuePolicy: null
180 SSM:
181 Document: null
182 WAF:
183 ByteMatchSet: null
184 IPSet: null
185 Rule: null
186 SqlInjectionMatchSet: null
187 WebACL: null
188 WorkSpaces:
189 Workspace: null
190 @Param =
191 String: (name, arg1, arg2) => @_paramByType 'String', name, arg1, arg2
192 Number: (name, arg1, arg2) => @_paramByType 'Number', name, arg1, arg2
193 CommaDelimitedList: (name, arg1, arg2) => @_paramByType 'CommaDelimitedList', name, arg1, arg2
194 AWS: (type, name, arg1, arg2) => @_paramByType "AWS::#{type}", name, arg1, arg2
195 AWSList: (type, name, arg1, arg2) => @_paramByType "List<AWS::#{type}>", name, arg1, arg2
196 @_buildCall null, null, 'AWS', @AWS
197
198 _paramByType: (type, name, arg1, arg2) =>
199 result = {}
200 if not arg1?
201 result[name] = {}
202 else if not arg2?
203 result[name] = if typeof arg1 is 'string' then Description: arg1 else arg1
204 else
205 result[name] = arg2
206 result[name].Description = arg1
207 result[name].Type = type
208 @_set result, @_parameters
209 @Params[name] = Ref: name
210
211 _buildCall: (parent, lastKey, awsType, leaf) =>
212 if leaf?
213 for key, val of leaf
214 @_buildCall leaf, key, "#{awsType}::#{key}", val
215 return
216 parent[lastKey] = (name, props) =>
217 @_resourceByType awsType, name, props
218
219 # todo: this cheesy forward decl thing shouldn't be necessary
220 DeclareResource: (name) =>
221 @Resources[name] ?= Ref: name
222
223 _resourceByType: (type, name, props) =>
224 result = {}
225 if props?.Metadata? or props?.Properties? or props?.DependsOn? or props?.UpdatePolicy? or props?.CreationPolicy? or props?.Condition?
226 result[name] = props
227 result[name].Type = type
228 else
229 result[name] =
230 Type: type
231 Properties: props
232 @_set result, @_resources
233 @DeclareResource name
234
235 _set: (source, target) ->
236 for key, val of source
237 target[key] = val
238
239 Mapping: (name, map) =>
240 @_mappings ?= {}
241 result = {}
242 result[name] = map
243 @_set result, @_mappings
244
245 Output: (name, args...) =>
246 result = {}
247 if args.length is 1
248 result[name] =
249 Value: args[0]
250 if args.length is 2
251 result[name] =
252 Description: args[0]
253 Value: args[1]
254 @_set result, @_outputs
255
256 Condition: (name, intrinsicfn) =>
257 @_conditions ?= {}
258 result = {}
259 result[name] = intrinsicfn
260 @_set result, @_conditions
261
262 Description: (d) => @_description = d
263
264 Metadata: (o) =>
265 @_metadatas ?= {}
266 @_set o, @_metadatas
267
268 Tag: (key, val) ->
269 Key: key
270 Value: val
271
272 #utility functions
273 Join: (delimiter, args...) ->
274 if args.length is 1 and (args[0] instanceof Array)
275 'Fn::Join': [ delimiter, args[0] ]
276 else
277 'Fn::Join': [ delimiter, args ]
278 FindInMap: (args...) ->
279 'Fn::FindInMap': args
280 GetAtt: (args...) ->
281 'Fn::GetAtt': args
282 Base64: (arg) ->
283 'Fn::Base64': arg
284 GetAZs: (arg) ->
285 'Fn::GetAZs': arg
286 Select: (index, args...) ->
287 if args.length is 1 and (args[0] instanceof Array)
288 'Fn::Select': [index, args[0]]
289 else
290 'Fn::Select': [index, args]
291 And: (conditions...) ->
292 'Fn::And': conditions
293 Equals: (value_1, value_2) ->
294 'Fn::Equals': [ value_1, value_2 ]
295 If: (condition, value_if_true, value_if_false) ->
296 'Fn::If': [condition, value_if_true, value_if_false]
297 Not: (condition) ->
298 'Fn::Not': [condition]
299 Or: (conditions...) ->
300 'Fn::Or': conditions
301 AccountId: Ref: 'AWS::AccountId'
302 NotificationARNs: Ref: 'AWS::NotificationARNs'
303 NoValue: Ref: 'AWS::NoValue'
304 Region: Ref: 'AWS::Region'
305 StackId: Ref: 'AWS::StackId'
306 StackName: Ref: 'AWS::StackName'
307 InitScript: (arg) ->
308 existsSyncFunc = if fs.existsSync? then fs.existsSync else path.existsSync
309 if not existsSyncFunc(arg)
310 text = arg
311 else
312 text = fs.readFileSync(arg).toString()
313 chunks = []
314 #todo: fix this abhoration of regex
315 pattern = /((.|\n)*?)%{([^}?]+)}?((.|\n)*)/
316 match = text.match pattern
317 while match
318 chunks.push match[1]
319 compiled = CoffeeScript.compile match[3], {bare: true}
320 chunks.push eval compiled
321 text = match[4]
322 match = text.match pattern
323 chunks.push text if text and text.length > 0
324 @Base64 @Join '', chunks
325
326module.exports.CloudFormationTemplateContext = CloudFormationTemplateContext
327
328module.exports = (func) ->
329 context = new CloudFormationTemplateContext
330 func.apply context, [context]
331 template = AWSTemplateFormatVersion: '2010-09-09'
332 template.Description = context._description if context._description?
333 template.Parameters = context._parameters
334 template.Mappings = context._mappings if context._mappings?
335 template.Resources = context._resources
336 template.Outputs = context._outputs
337 template.Conditions = context._conditions if context._conditions?
338 template.Metadata = context._metadatas if context._metadatas?
339 template
340
341require('pkginfo')(module, 'version')