cfhighlander 0.2.0.alpha.10
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 +7 -0
- data/README.md +411 -0
- data/bin/cfhighlander +3 -0
- data/bin/highlander.rb +158 -0
- data/cfndsl_ext/config/managed_policies.yaml +172 -0
- data/cfndsl_ext/iam_helper.rb +55 -0
- data/cfndsl_ext/lambda_helper.rb +86 -0
- data/cfndsl_ext/sg.rb +26 -0
- data/hl_ext/aws_helper.rb +13 -0
- data/hl_ext/common_helper.rb +21 -0
- data/hl_ext/mapping_helper.rb +99 -0
- data/hl_ext/vpc.rb +12 -0
- data/lib/highlander.compiler.rb +306 -0
- data/lib/highlander.dsl.base.rb +25 -0
- data/lib/highlander.dsl.component.rb +243 -0
- data/lib/highlander.dsl.params.rb +113 -0
- data/lib/highlander.dsl.rb +428 -0
- data/lib/highlander.factory.rb +359 -0
- data/lib/highlander.helper.rb +23 -0
- data/lib/highlander.mapproviders.rb +31 -0
- data/lib/highlander.publisher.rb +71 -0
- data/lib/highlander.validator.rb +72 -0
- data/lib/util/zip.util.rb +57 -0
- data/templates/cfndsl.component.template.erb +45 -0
- metadata +248 -0
@@ -0,0 +1,428 @@
|
|
1
|
+
# require all extensions
|
2
|
+
|
3
|
+
extensions_folder = "#{File.dirname(__FILE__)}/../hl_ext"
|
4
|
+
|
5
|
+
Dir["#{extensions_folder}/*.rb"].each { |f|
|
6
|
+
require f
|
7
|
+
}
|
8
|
+
|
9
|
+
# require libraries
|
10
|
+
|
11
|
+
require_relative './highlander.dsl.base'
|
12
|
+
require_relative './highlander.dsl.params'
|
13
|
+
require_relative './highlander.dsl.component'
|
14
|
+
|
15
|
+
module Highlander
|
16
|
+
|
17
|
+
module Dsl
|
18
|
+
|
19
|
+
class Template < DslBase
|
20
|
+
|
21
|
+
attr_accessor :mappings,
|
22
|
+
:parameters,
|
23
|
+
:name,
|
24
|
+
:components,
|
25
|
+
:version,
|
26
|
+
:distribute_url,
|
27
|
+
:distribution_bucket,
|
28
|
+
:distribution_prefix,
|
29
|
+
:lambda_functions_keys,
|
30
|
+
:description,
|
31
|
+
:dependson_components
|
32
|
+
|
33
|
+
def initialize
|
34
|
+
@mappings = []
|
35
|
+
@components = []
|
36
|
+
@config = { 'mappings' => {}, 'component_version' => 'latest' }
|
37
|
+
@component_configs = {}
|
38
|
+
@version = 'latest'
|
39
|
+
@distribute_url = nil
|
40
|
+
@distribution_prefix = ''
|
41
|
+
@component_sources = []
|
42
|
+
@parameters = Parameters.new
|
43
|
+
@lambda_functions_keys = []
|
44
|
+
@dependson_components_templates = []
|
45
|
+
@dependson_components = []
|
46
|
+
end
|
47
|
+
|
48
|
+
# DSL statements
|
49
|
+
|
50
|
+
def addMapping(name, map)
|
51
|
+
@mappings << name
|
52
|
+
@config['mappings'] = {} unless @config.key?('mappings')
|
53
|
+
@config['mappings'][name] = map
|
54
|
+
end
|
55
|
+
|
56
|
+
def Name(name)
|
57
|
+
@name = name
|
58
|
+
@config['component_name'] = name
|
59
|
+
end
|
60
|
+
|
61
|
+
def Description(description)
|
62
|
+
@description = description
|
63
|
+
@config['description'] = description
|
64
|
+
end
|
65
|
+
|
66
|
+
def Parameters(&block)
|
67
|
+
@parameters.config = @config
|
68
|
+
@parameters.instance_eval(&block)
|
69
|
+
end
|
70
|
+
|
71
|
+
def DynamicMappings(providerName)
|
72
|
+
maps = mappings_provider_maps(providerName, self.config)
|
73
|
+
maps.each { |name, map| addMapping(name, map) } unless maps.nil?
|
74
|
+
end
|
75
|
+
|
76
|
+
def DependsOn(template)
|
77
|
+
@dependson_components_templates << template
|
78
|
+
end
|
79
|
+
|
80
|
+
|
81
|
+
def Component(name:, template:, param_values: {}, config: {}, export_config: {}, &block)
|
82
|
+
puts "Initialize #{name} with template #{template}"
|
83
|
+
|
84
|
+
# load component
|
85
|
+
component = Highlander::Dsl::Component.new(self,
|
86
|
+
name,
|
87
|
+
template,
|
88
|
+
param_values,
|
89
|
+
@component_sources,
|
90
|
+
config,
|
91
|
+
export_config
|
92
|
+
)
|
93
|
+
component.distribute_bucket = @distribution_bucket unless @distribution_bucket.nil?
|
94
|
+
component.distribute_prefix = @distribution_prefix unless @distribution_prefix.nil?
|
95
|
+
component.version = @version unless @version.nil?
|
96
|
+
@component_configs[name] = config
|
97
|
+
@components << component
|
98
|
+
end
|
99
|
+
|
100
|
+
def ComponentVersion(version)
|
101
|
+
@version = version
|
102
|
+
@config['component_version'] = version
|
103
|
+
build_distribution_url
|
104
|
+
end
|
105
|
+
|
106
|
+
def DistributionPrefix(prefix)
|
107
|
+
@distribution_prefix = prefix
|
108
|
+
build_distribution_url
|
109
|
+
end
|
110
|
+
|
111
|
+
def DistributionBucket(bucket_name)
|
112
|
+
@distribution_bucket = bucket_name
|
113
|
+
build_distribution_url
|
114
|
+
end
|
115
|
+
|
116
|
+
def ComponentDistribution(s3_url)
|
117
|
+
if s3_url.start_with? 's3://'
|
118
|
+
if s3_url.split('/').length < 4
|
119
|
+
raise 'Unrecognised distribution url, only supporting s3://bucket/prefix urls'
|
120
|
+
end
|
121
|
+
parts = s3_url.split('/')
|
122
|
+
@distribution_bucket = parts[2]
|
123
|
+
@distribution_prefix = parts[3]
|
124
|
+
i = 4
|
125
|
+
while i < parts.size()
|
126
|
+
@distribution_prefix += "/#{parts[i]}"
|
127
|
+
i += 1
|
128
|
+
end
|
129
|
+
@distribution_prefix = @distribution_prefix.chomp('/')
|
130
|
+
|
131
|
+
build_distribution_url
|
132
|
+
else
|
133
|
+
raise 'Unrecognised distribution url, only supporting s3://bucket/prefix urls'
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
137
|
+
def ComponentSources(sources_array)
|
138
|
+
@component_sources = sources_array
|
139
|
+
end
|
140
|
+
|
141
|
+
def LambdaFunctions(config_key)
|
142
|
+
@lambda_functions_keys << config_key
|
143
|
+
end
|
144
|
+
|
145
|
+
# Internal and interface functions
|
146
|
+
|
147
|
+
def loadComponents()
|
148
|
+
|
149
|
+
# empty config overrides to start with
|
150
|
+
@config_overrides = Hash[@components.collect { |c| [c.name, {}] }]
|
151
|
+
@named_components = Hash[@components.collect { |c| [c.name, c] }]
|
152
|
+
|
153
|
+
# populate overrides with master config defined overrides
|
154
|
+
load_configfile_component_config
|
155
|
+
|
156
|
+
# populate overrides with config defined explictily
|
157
|
+
load_explicit_component_config
|
158
|
+
|
159
|
+
# apply configuration exports
|
160
|
+
apply_config_overrides
|
161
|
+
apply_config_exports
|
162
|
+
|
163
|
+
|
164
|
+
# component exports may have overriden some of explicit / configfile configuration, reapply
|
165
|
+
load_configfile_component_config
|
166
|
+
load_explicit_component_config
|
167
|
+
|
168
|
+
# apply extension exports
|
169
|
+
load_extension_exports
|
170
|
+
|
171
|
+
|
172
|
+
# load components and extract parent stack parameters and mappings
|
173
|
+
@components.each { |component|
|
174
|
+
|
175
|
+
component.load @config_overrides[component.name]
|
176
|
+
# add all of it's stack parameters unless same template has been already processed
|
177
|
+
component
|
178
|
+
.component_loaded
|
179
|
+
.highlander_dsl
|
180
|
+
.parameters
|
181
|
+
.param_list.each do |param|
|
182
|
+
|
183
|
+
# add stack parameters
|
184
|
+
if param.class == Highlander::Dsl::StackParam
|
185
|
+
# sub-component stack param becomes top-level component param
|
186
|
+
param_name = param.is_global ? param.name : "#{component.name}#{param.name}"
|
187
|
+
stack_param = Highlander::Dsl::ComponentParam.new(
|
188
|
+
param_name,
|
189
|
+
param.type,
|
190
|
+
param.default_value,
|
191
|
+
param.no_echo
|
192
|
+
)
|
193
|
+
@parameters.addParam stack_param
|
194
|
+
end unless component.param_values.key? param.name
|
195
|
+
|
196
|
+
# for map parameters add maps
|
197
|
+
if param.class == Highlander::Dsl::MappingParam
|
198
|
+
if not param.mapProvider.nil?
|
199
|
+
maps = param.mapProvider.getMaps(component.component_loaded.config)
|
200
|
+
maps.each do |name, map|
|
201
|
+
if not @mappings.include? name
|
202
|
+
#1. add mapping name to model
|
203
|
+
@mappings << name
|
204
|
+
#2. add mapping to config to be rendered via cfndsl
|
205
|
+
@config['mappings'] = {} if @config['mappings'].nil?
|
206
|
+
@config['mappings'][name] = map
|
207
|
+
end
|
208
|
+
end unless maps.nil?
|
209
|
+
end
|
210
|
+
end
|
211
|
+
|
212
|
+
end
|
213
|
+
|
214
|
+
# late bind parameter values, once mappings and top level params are extracted
|
215
|
+
component.load_parameters
|
216
|
+
}
|
217
|
+
|
218
|
+
@dependson_components_templates.each do |template|
|
219
|
+
component = Highlander::Dsl::Component.new(self,
|
220
|
+
template,
|
221
|
+
template,
|
222
|
+
{},
|
223
|
+
@component_sources
|
224
|
+
)
|
225
|
+
component.load
|
226
|
+
@dependson_components << component
|
227
|
+
end
|
228
|
+
end
|
229
|
+
|
230
|
+
def load_extension_exports
|
231
|
+
@components.each do |c|
|
232
|
+
component = c.component_loaded
|
233
|
+
config = component.config
|
234
|
+
if ((config.key? 'lib_export') and (config['lib_export'].key? 'global'))
|
235
|
+
|
236
|
+
global_export_config = config['lib_export']['global']
|
237
|
+
if global_export_config.key? 'cfndsl'
|
238
|
+
global_export_config['cfndsl'].each do |exported_extension|
|
239
|
+
extension_file_path = "#{component.component_dir}/ext/cfndsl/#{exported_extension}.rb"
|
240
|
+
@components.each do |cr|
|
241
|
+
cr.component_loaded.cfndsl_ext_files << extension_file_path unless cr == c
|
242
|
+
end
|
243
|
+
end
|
244
|
+
end
|
245
|
+
|
246
|
+
end
|
247
|
+
end
|
248
|
+
end
|
249
|
+
|
250
|
+
def apply_config_overrides
|
251
|
+
@config_overrides.each { |component_name, component_override|
|
252
|
+
@named_components[component_name].component_loaded.config.extend(component_override)
|
253
|
+
}
|
254
|
+
end
|
255
|
+
|
256
|
+
def load_configfile_component_config
|
257
|
+
if (@config.key? 'components')
|
258
|
+
@config['components'].each { |component_name, component_config|
|
259
|
+
if component_config.key?('config')
|
260
|
+
@config_overrides[component_name].extend(component_config['config'])
|
261
|
+
end
|
262
|
+
}
|
263
|
+
end
|
264
|
+
end
|
265
|
+
|
266
|
+
def apply_config_exports
|
267
|
+
# first export from master to all children
|
268
|
+
if ((@config.key? 'config_export') and (@config['config_export']['global']))
|
269
|
+
@config['config_export']['global'].each { |global_export_key|
|
270
|
+
if @config.key? global_export_key
|
271
|
+
@config_overrides.each { |cname, co|
|
272
|
+
co[global_export_key] = @config[global_export_key]
|
273
|
+
}
|
274
|
+
end
|
275
|
+
}
|
276
|
+
end
|
277
|
+
|
278
|
+
@components.each { |component|
|
279
|
+
cl = component.component_loaded
|
280
|
+
if ((not cl.config.nil?) and (cl.config.key? 'config_export'))
|
281
|
+
|
282
|
+
# global config
|
283
|
+
if cl.config['config_export'].key? 'global'
|
284
|
+
cl.config['config_export']['global'].each { |global_export_key|
|
285
|
+
|
286
|
+
# global config is exported to parent and every component
|
287
|
+
if cl.config.key? global_export_key
|
288
|
+
|
289
|
+
# cname is for component name, co for component override
|
290
|
+
@config_overrides.each { |cname, co|
|
291
|
+
|
292
|
+
# if templates are different e.g don't export from vpc to vpc
|
293
|
+
config_receiver_component = @named_components[cname]
|
294
|
+
if config_receiver_component.template != component.template
|
295
|
+
if (not config_receiver_component.export_config.nil?) and (config_receiver_component.export_config.key? component.template)
|
296
|
+
allow_from_component_name = config_receiver_component.export_config[component.template]
|
297
|
+
if allow_from_component_name == component.name
|
298
|
+
puts("Exporting key #{global_export_key} from component #{component.name} to #{cname}")
|
299
|
+
co[global_export_key] = cl.config[global_export_key]
|
300
|
+
end
|
301
|
+
else
|
302
|
+
puts("Exporting key #{global_export_key} from component #{component.name} to #{cname}")
|
303
|
+
co[global_export_key] = cl.config[global_export_key]
|
304
|
+
end
|
305
|
+
end
|
306
|
+
}
|
307
|
+
|
308
|
+
|
309
|
+
else
|
310
|
+
STDERR.puts("Trying to export non-existent configuration key #{global_export_key}")
|
311
|
+
end
|
312
|
+
}
|
313
|
+
end
|
314
|
+
|
315
|
+
if cl.config['config_export'].key? 'component'
|
316
|
+
cl.config['config_export']['component'].each { |component_name, export_keys|
|
317
|
+
# check if there is configuration of export from this component
|
318
|
+
# and if there is export configuration for given component name
|
319
|
+
|
320
|
+
if (not component.export_config.nil?) and (component.export_config.key? component_name)
|
321
|
+
# if there is component with such name
|
322
|
+
if @config_overrides.key? component.export_config[component_name]
|
323
|
+
# override the config
|
324
|
+
real_component_name = component.export_config[component_name]
|
325
|
+
export_keys.each { |export_component_key|
|
326
|
+
puts("Exporting config for key=#{export_component_key} from #{component.name} to #{real_component_name}")
|
327
|
+
if not @config_overrides[real_component_name].key? export_component_key
|
328
|
+
@config_overrides[real_component_name][export_component_key] = {}
|
329
|
+
end
|
330
|
+
@config_overrides[real_component_name][export_component_key].extend(cl.config[export_component_key])
|
331
|
+
}
|
332
|
+
else
|
333
|
+
STDERR.puts("Trying to export configuration for non-existant component #{component.export_config[component_name]}")
|
334
|
+
end
|
335
|
+
elsif @config_overrides.key? component_name
|
336
|
+
export_keys.each { |export_component_key|
|
337
|
+
puts("Exporting config for key=#{export_component_key} from #{component.name} to #{component_name}")
|
338
|
+
if not @config_overrides[component_name].key? export_component_key
|
339
|
+
@config_overrides[component_name][export_component_key] = {}
|
340
|
+
end
|
341
|
+
@config_overrides[component_name][export_component_key].extend(cl.config[export_component_key])
|
342
|
+
}
|
343
|
+
else
|
344
|
+
STDERR.puts("Trying to export configuration for non-existant component #{component_name}")
|
345
|
+
end
|
346
|
+
}
|
347
|
+
end
|
348
|
+
# component config
|
349
|
+
# loop over keys
|
350
|
+
# check if there
|
351
|
+
end
|
352
|
+
}
|
353
|
+
end
|
354
|
+
|
355
|
+
def load_explicit_component_config
|
356
|
+
@component_configs.each { |component_name, component_config|
|
357
|
+
@config_overrides[component_name].extend(component_config)
|
358
|
+
}
|
359
|
+
end
|
360
|
+
|
361
|
+
def distribute_bucket=(value)
|
362
|
+
@distribution_bucket = value
|
363
|
+
build_distribution_url
|
364
|
+
end
|
365
|
+
|
366
|
+
def distribute_prefix=(value)
|
367
|
+
@distribution_prefix = value
|
368
|
+
build_distribution_url
|
369
|
+
end
|
370
|
+
|
371
|
+
def name=(value)
|
372
|
+
self.Name(value)
|
373
|
+
end
|
374
|
+
|
375
|
+
def build_distribution_url
|
376
|
+
if not (@distribution_bucket.nil? or @distribution_prefix.nil?)
|
377
|
+
@distribute_url = "https://#{@distribution_bucket}.s3.amazonaws.com/#{@distribution_prefix}"
|
378
|
+
@distribute_url = "#{@distribute_url}/#{@version}" unless @version.nil?
|
379
|
+
@components.each { |component|
|
380
|
+
component.distribute_bucket = @distribution_bucket unless @distribution_bucket.nil?
|
381
|
+
component.distribute_prefix = @distribution_prefix unless @distribution_prefix.nil?
|
382
|
+
component.version = @version unless @version.nil?
|
383
|
+
component.build_distribution_url
|
384
|
+
}
|
385
|
+
end
|
386
|
+
end
|
387
|
+
|
388
|
+
|
389
|
+
end
|
390
|
+
end
|
391
|
+
|
392
|
+
end
|
393
|
+
|
394
|
+
def HighlanderComponent(&block)
|
395
|
+
instance = Highlander::Dsl::Template.new
|
396
|
+
|
397
|
+
puts "Processing higlander component #{@name}\n\tLocation:#{@highlander_dsl_path}" +
|
398
|
+
"\n\tConfig:#{@config}"
|
399
|
+
|
400
|
+
component_config = @config
|
401
|
+
|
402
|
+
instance.config = @config
|
403
|
+
|
404
|
+
@mappings.each do |key, val|
|
405
|
+
instance.addMapping(key, val)
|
406
|
+
end
|
407
|
+
|
408
|
+
unless @version.nil?
|
409
|
+
instance.version = @version
|
410
|
+
end
|
411
|
+
|
412
|
+
unless @distribution_bucket.nil?
|
413
|
+
instance.DistributionBucket(@distribution_bucket)
|
414
|
+
end
|
415
|
+
unless @distribution_prefix.nil?
|
416
|
+
instance.DistributionPrefix(@distribution_prefix)
|
417
|
+
end
|
418
|
+
|
419
|
+
instance.instance_eval(&block)
|
420
|
+
if instance.name.nil?
|
421
|
+
instance.name = @name
|
422
|
+
end
|
423
|
+
|
424
|
+
# load sub-components
|
425
|
+
instance.loadComponents
|
426
|
+
|
427
|
+
return instance
|
428
|
+
end
|