cfhighlander 0.2.1.alpha.43 → 0.2.1
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 +4 -4
- data/README.md +79 -153
- data/bin/cfhighlander +1 -1
- data/bin/{cfhighlander.rb → highlander.rb} +22 -27
- data/cfndsl_ext/sg.rb +2 -29
- data/hl_ext/mapping_helper.rb +4 -6
- data/lib/{cfhighlander.compiler.rb → highlander.compiler.rb} +18 -26
- data/lib/{cfhighlander.dsl.base.rb → highlander.dsl.base.rb} +2 -2
- data/lib/{cfhighlander.dsl.subcomponent.rb → highlander.dsl.component.rb} +71 -83
- data/lib/highlander.dsl.params.rb +113 -0
- data/lib/{cfhighlander.dsl.template.rb → highlander.dsl.rb} +62 -91
- data/lib/highlander.factory.rb +359 -0
- data/lib/{cfhighlander.helper.rb → highlander.helper.rb} +2 -2
- data/lib/{cfhighlander.mapproviders.rb → highlander.mapproviders.rb} +1 -1
- data/lib/{cfhighlander.publisher.rb → highlander.publisher.rb} +3 -3
- data/lib/{cfhighlander.validator.rb → highlander.validator.rb} +1 -1
- data/lib/util/zip.util.rb +1 -1
- data/templates/cfndsl.component.template.erb +1 -4
- metadata +15 -38
- data/lib/cfhighlander.dsl.params.rb +0 -108
- data/lib/cfhighlander.factory.rb +0 -45
- data/lib/cfhighlander.factory.templatefinder.rb +0 -248
- data/lib/cfhighlander.model.component.rb +0 -177
- data/lib/cfhighlander.model.templatemeta.rb +0 -25
@@ -2,26 +2,26 @@
|
|
2
2
|
|
3
3
|
extensions_folder = "#{File.dirname(__FILE__)}/../hl_ext"
|
4
4
|
|
5
|
-
Dir["#{extensions_folder}/*.rb"].each {|f|
|
5
|
+
Dir["#{extensions_folder}/*.rb"].each { |f|
|
6
6
|
require f
|
7
7
|
}
|
8
8
|
|
9
9
|
# require libraries
|
10
10
|
|
11
|
-
require_relative './
|
12
|
-
require_relative './
|
13
|
-
require_relative './
|
11
|
+
require_relative './highlander.dsl.base'
|
12
|
+
require_relative './highlander.dsl.params'
|
13
|
+
require_relative './highlander.dsl.component'
|
14
14
|
|
15
|
-
module
|
15
|
+
module Highlander
|
16
16
|
|
17
17
|
module Dsl
|
18
18
|
|
19
|
-
class
|
19
|
+
class Template < DslBase
|
20
20
|
|
21
21
|
attr_accessor :mappings,
|
22
22
|
:parameters,
|
23
23
|
:name,
|
24
|
-
:
|
24
|
+
:components,
|
25
25
|
:version,
|
26
26
|
:distribute_url,
|
27
27
|
:distribution_bucket,
|
@@ -32,7 +32,7 @@ module Cfhighlander
|
|
32
32
|
|
33
33
|
def initialize
|
34
34
|
@mappings = []
|
35
|
-
@
|
35
|
+
@components = []
|
36
36
|
@config = { 'mappings' => {}, 'component_version' => 'latest' }
|
37
37
|
@component_configs = {}
|
38
38
|
@version = 'latest'
|
@@ -54,12 +54,8 @@ module Cfhighlander
|
|
54
54
|
end
|
55
55
|
|
56
56
|
def Name(name)
|
57
|
-
|
58
|
-
|
59
|
-
if (not @config.key? 'nested_component')
|
60
|
-
@name = name
|
61
|
-
@config['component_name'] = name
|
62
|
-
end
|
57
|
+
@name = name
|
58
|
+
@config['component_name'] = name
|
63
59
|
end
|
64
60
|
|
65
61
|
def Description(description)
|
@@ -74,7 +70,7 @@ module Cfhighlander
|
|
74
70
|
|
75
71
|
def DynamicMappings(providerName)
|
76
72
|
maps = mappings_provider_maps(providerName, self.config)
|
77
|
-
maps.each {|name, map| addMapping(name, map)} unless maps.nil?
|
73
|
+
maps.each { |name, map| addMapping(name, map) } unless maps.nil?
|
78
74
|
end
|
79
75
|
|
80
76
|
def DependsOn(template)
|
@@ -82,23 +78,11 @@ module Cfhighlander
|
|
82
78
|
end
|
83
79
|
|
84
80
|
|
85
|
-
def Component(
|
86
|
-
|
87
|
-
param_values: {},
|
88
|
-
config: {},
|
89
|
-
export_config: {}, &block)
|
90
|
-
puts "INFO: Requested subcomponent #{name} with template #{template}"
|
91
|
-
if ((not template_arg.nil?) and template.nil?)
|
92
|
-
template = template_arg
|
93
|
-
elsif (template_arg.nil? and template.nil?)
|
94
|
-
raise 'Component must be defined with template name at minimum,' +
|
95
|
-
' passed as first argument, or template: named arguent'
|
96
|
-
end
|
97
|
-
|
98
|
-
name = template if name.nil?
|
81
|
+
def Component(name:, template:, param_values: {}, config: {}, export_config: {}, &block)
|
82
|
+
puts "Initialize #{name} with template #{template}"
|
99
83
|
|
100
84
|
# load component
|
101
|
-
component =
|
85
|
+
component = Highlander::Dsl::Component.new(self,
|
102
86
|
name,
|
103
87
|
template,
|
104
88
|
param_values,
|
@@ -106,12 +90,11 @@ module Cfhighlander
|
|
106
90
|
config,
|
107
91
|
export_config
|
108
92
|
)
|
109
|
-
component.instance_eval(&block) unless block.nil?
|
110
93
|
component.distribute_bucket = @distribution_bucket unless @distribution_bucket.nil?
|
111
94
|
component.distribute_prefix = @distribution_prefix unless @distribution_prefix.nil?
|
112
95
|
component.version = @version unless @version.nil?
|
113
96
|
@component_configs[name] = config
|
114
|
-
@
|
97
|
+
@components << component
|
115
98
|
end
|
116
99
|
|
117
100
|
def ComponentVersion(version)
|
@@ -164,8 +147,8 @@ module Cfhighlander
|
|
164
147
|
def loadComponents()
|
165
148
|
|
166
149
|
# empty config overrides to start with
|
167
|
-
@config_overrides = Hash[@
|
168
|
-
@named_components = Hash[@
|
150
|
+
@config_overrides = Hash[@components.collect { |c| [c.name, {}] }]
|
151
|
+
@named_components = Hash[@components.collect { |c| [c.name, c] }]
|
169
152
|
|
170
153
|
# populate overrides with master config defined overrides
|
171
154
|
load_configfile_component_config
|
@@ -187,7 +170,7 @@ module Cfhighlander
|
|
187
170
|
|
188
171
|
|
189
172
|
# load components and extract parent stack parameters and mappings
|
190
|
-
@
|
173
|
+
@components.each { |component|
|
191
174
|
|
192
175
|
component.load @config_overrides[component.name]
|
193
176
|
# add all of it's stack parameters unless same template has been already processed
|
@@ -197,8 +180,21 @@ module Cfhighlander
|
|
197
180
|
.parameters
|
198
181
|
.param_list.each do |param|
|
199
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
|
+
|
200
196
|
# for map parameters add maps
|
201
|
-
if param.class ==
|
197
|
+
if param.class == Highlander::Dsl::MappingParam
|
202
198
|
if not param.mapProvider.nil?
|
203
199
|
maps = param.mapProvider.getMaps(component.component_loaded.config)
|
204
200
|
maps.each do |name, map|
|
@@ -215,24 +211,12 @@ module Cfhighlander
|
|
215
211
|
|
216
212
|
end
|
217
213
|
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
# in 2nd pass, load parameters
|
222
|
-
# 2nd pass is required as all of cfndsl models need to be populated
|
223
|
-
available_outputs = {}
|
224
|
-
@subcomponents.each do |c|
|
225
|
-
c.component_loaded.outputs.each do |out|
|
226
|
-
available_outputs[out.name] = out
|
227
|
-
end
|
228
|
-
end
|
229
|
-
|
230
|
-
@subcomponents.each do |component|
|
231
|
-
component.resolve_parameter_values available_outputs
|
232
|
-
end
|
214
|
+
# late bind parameter values, once mappings and top level params are extracted
|
215
|
+
component.load_parameters
|
216
|
+
}
|
233
217
|
|
234
218
|
@dependson_components_templates.each do |template|
|
235
|
-
component =
|
219
|
+
component = Highlander::Dsl::Component.new(self,
|
236
220
|
template,
|
237
221
|
template,
|
238
222
|
{},
|
@@ -244,7 +228,7 @@ module Cfhighlander
|
|
244
228
|
end
|
245
229
|
|
246
230
|
def load_extension_exports
|
247
|
-
@
|
231
|
+
@components.each do |c|
|
248
232
|
component = c.component_loaded
|
249
233
|
config = component.config
|
250
234
|
if ((config.key? 'lib_export') and (config['lib_export'].key? 'global'))
|
@@ -253,7 +237,7 @@ module Cfhighlander
|
|
253
237
|
if global_export_config.key? 'cfndsl'
|
254
238
|
global_export_config['cfndsl'].each do |exported_extension|
|
255
239
|
extension_file_path = "#{component.component_dir}/ext/cfndsl/#{exported_extension}.rb"
|
256
|
-
@
|
240
|
+
@components.each do |cr|
|
257
241
|
cr.component_loaded.cfndsl_ext_files << extension_file_path unless cr == c
|
258
242
|
end
|
259
243
|
end
|
@@ -264,20 +248,16 @@ module Cfhighlander
|
|
264
248
|
end
|
265
249
|
|
266
250
|
def apply_config_overrides
|
267
|
-
@config_overrides.each {|component_name, component_override|
|
251
|
+
@config_overrides.each { |component_name, component_override|
|
268
252
|
@named_components[component_name].component_loaded.config.extend(component_override)
|
269
253
|
}
|
270
254
|
end
|
271
255
|
|
272
256
|
def load_configfile_component_config
|
273
257
|
if (@config.key? 'components')
|
274
|
-
@config['components'].each {|component_name, component_config|
|
258
|
+
@config['components'].each { |component_name, component_config|
|
275
259
|
if component_config.key?('config')
|
276
|
-
|
277
|
-
@config_overrides[component_name].extend(component_config['config'])
|
278
|
-
else
|
279
|
-
STDERR.puts("WARN: Overriding config for non-existing component #{component_name}")
|
280
|
-
end
|
260
|
+
@config_overrides[component_name].extend(component_config['config'])
|
281
261
|
end
|
282
262
|
}
|
283
263
|
end
|
@@ -286,28 +266,28 @@ module Cfhighlander
|
|
286
266
|
def apply_config_exports
|
287
267
|
# first export from master to all children
|
288
268
|
if ((@config.key? 'config_export') and (@config['config_export']['global']))
|
289
|
-
@config['config_export']['global'].each {|global_export_key|
|
269
|
+
@config['config_export']['global'].each { |global_export_key|
|
290
270
|
if @config.key? global_export_key
|
291
|
-
@config_overrides.each {|cname, co|
|
271
|
+
@config_overrides.each { |cname, co|
|
292
272
|
co[global_export_key] = @config[global_export_key]
|
293
273
|
}
|
294
274
|
end
|
295
275
|
}
|
296
276
|
end
|
297
277
|
|
298
|
-
@
|
278
|
+
@components.each { |component|
|
299
279
|
cl = component.component_loaded
|
300
280
|
if ((not cl.config.nil?) and (cl.config.key? 'config_export'))
|
301
281
|
|
302
282
|
# global config
|
303
283
|
if cl.config['config_export'].key? 'global'
|
304
|
-
cl.config['config_export']['global'].each {|global_export_key|
|
284
|
+
cl.config['config_export']['global'].each { |global_export_key|
|
305
285
|
|
306
286
|
# global config is exported to parent and every component
|
307
287
|
if cl.config.key? global_export_key
|
308
288
|
|
309
289
|
# cname is for component name, co for component override
|
310
|
-
@config_overrides.each {|cname, co|
|
290
|
+
@config_overrides.each { |cname, co|
|
311
291
|
|
312
292
|
# if templates are different e.g don't export from vpc to vpc
|
313
293
|
config_receiver_component = @named_components[cname]
|
@@ -315,11 +295,11 @@ module Cfhighlander
|
|
315
295
|
if (not config_receiver_component.export_config.nil?) and (config_receiver_component.export_config.key? component.template)
|
316
296
|
allow_from_component_name = config_receiver_component.export_config[component.template]
|
317
297
|
if allow_from_component_name == component.name
|
318
|
-
puts("
|
298
|
+
puts("Exporting key #{global_export_key} from component #{component.name} to #{cname}")
|
319
299
|
co[global_export_key] = cl.config[global_export_key]
|
320
300
|
end
|
321
301
|
else
|
322
|
-
puts("
|
302
|
+
puts("Exporting key #{global_export_key} from component #{component.name} to #{cname}")
|
323
303
|
co[global_export_key] = cl.config[global_export_key]
|
324
304
|
end
|
325
305
|
end
|
@@ -333,7 +313,7 @@ module Cfhighlander
|
|
333
313
|
end
|
334
314
|
|
335
315
|
if cl.config['config_export'].key? 'component'
|
336
|
-
cl.config['config_export']['component'].each {|component_name, export_keys|
|
316
|
+
cl.config['config_export']['component'].each { |component_name, export_keys|
|
337
317
|
# check if there is configuration of export from this component
|
338
318
|
# and if there is export configuration for given component name
|
339
319
|
|
@@ -342,7 +322,7 @@ module Cfhighlander
|
|
342
322
|
if @config_overrides.key? component.export_config[component_name]
|
343
323
|
# override the config
|
344
324
|
real_component_name = component.export_config[component_name]
|
345
|
-
export_keys.each {|export_component_key|
|
325
|
+
export_keys.each { |export_component_key|
|
346
326
|
puts("Exporting config for key=#{export_component_key} from #{component.name} to #{real_component_name}")
|
347
327
|
if not @config_overrides[real_component_name].key? export_component_key
|
348
328
|
@config_overrides[real_component_name][export_component_key] = {}
|
@@ -353,7 +333,7 @@ module Cfhighlander
|
|
353
333
|
STDERR.puts("Trying to export configuration for non-existant component #{component.export_config[component_name]}")
|
354
334
|
end
|
355
335
|
elsif @config_overrides.key? component_name
|
356
|
-
export_keys.each {|export_component_key|
|
336
|
+
export_keys.each { |export_component_key|
|
357
337
|
puts("Exporting config for key=#{export_component_key} from #{component.name} to #{component_name}")
|
358
338
|
if not @config_overrides[component_name].key? export_component_key
|
359
339
|
@config_overrides[component_name][export_component_key] = {}
|
@@ -373,7 +353,7 @@ module Cfhighlander
|
|
373
353
|
end
|
374
354
|
|
375
355
|
def load_explicit_component_config
|
376
|
-
@component_configs.each {|component_name, component_config|
|
356
|
+
@component_configs.each { |component_name, component_config|
|
377
357
|
@config_overrides[component_name].extend(component_config)
|
378
358
|
}
|
379
359
|
end
|
@@ -388,15 +368,15 @@ module Cfhighlander
|
|
388
368
|
build_distribution_url
|
389
369
|
end
|
390
370
|
|
391
|
-
|
392
|
-
|
393
|
-
|
371
|
+
def name=(value)
|
372
|
+
self.Name(value)
|
373
|
+
end
|
394
374
|
|
395
375
|
def build_distribution_url
|
396
376
|
if not (@distribution_bucket.nil? or @distribution_prefix.nil?)
|
397
377
|
@distribute_url = "https://#{@distribution_bucket}.s3.amazonaws.com/#{@distribution_prefix}"
|
398
378
|
@distribute_url = "#{@distribute_url}/#{@version}" unless @version.nil?
|
399
|
-
@
|
379
|
+
@components.each { |component|
|
400
380
|
component.distribute_bucket = @distribution_bucket unless @distribution_bucket.nil?
|
401
381
|
component.distribute_prefix = @distribution_prefix unless @distribution_prefix.nil?
|
402
382
|
component.version = @version unless @version.nil?
|
@@ -411,12 +391,13 @@ module Cfhighlander
|
|
411
391
|
|
412
392
|
end
|
413
393
|
|
414
|
-
def
|
415
|
-
instance =
|
394
|
+
def HighlanderComponent(&block)
|
395
|
+
instance = Highlander::Dsl::Template.new
|
416
396
|
|
417
397
|
puts "Processing higlander component #{@name}\n\tLocation:#{@highlander_dsl_path}" +
|
418
398
|
"\n\tConfig:#{@config}"
|
419
399
|
|
400
|
+
component_config = @config
|
420
401
|
|
421
402
|
instance.config = @config
|
422
403
|
|
@@ -426,7 +407,6 @@ def CfhighlanderTemplate(&block)
|
|
426
407
|
|
427
408
|
unless @version.nil?
|
428
409
|
instance.version = @version
|
429
|
-
instance.config['component_version'] = @version
|
430
410
|
end
|
431
411
|
|
432
412
|
unless @distribution_bucket.nil?
|
@@ -436,22 +416,13 @@ def CfhighlanderTemplate(&block)
|
|
436
416
|
instance.DistributionPrefix(@distribution_prefix)
|
437
417
|
end
|
438
418
|
|
439
|
-
instance.name = @template.template_name
|
440
419
|
instance.instance_eval(&block)
|
441
|
-
|
420
|
+
if instance.name.nil?
|
421
|
+
instance.name = @name
|
422
|
+
end
|
442
423
|
|
443
424
|
# load sub-components
|
444
425
|
instance.loadComponents
|
445
426
|
|
446
427
|
return instance
|
447
428
|
end
|
448
|
-
|
449
|
-
def CfhighlanderComponent(&block)
|
450
|
-
STDERR.puts("DEPRECATED: #{@template.template_name}: use CfhighlanderTemplate instead of CfhighlanderComponent")
|
451
|
-
CfhighlanderTemplate(&block)
|
452
|
-
end
|
453
|
-
|
454
|
-
def HighlanderComponent(&block)
|
455
|
-
STDERR.puts("DEPRECATED: #{@template.template_name}: use CfhighlanderTemplate instead of HighlanderComponent")
|
456
|
-
CfhighlanderTemplate(&block)
|
457
|
-
end
|
@@ -0,0 +1,359 @@
|
|
1
|
+
require_relative './highlander.dsl'
|
2
|
+
require 'fileutils'
|
3
|
+
require 'git'
|
4
|
+
|
5
|
+
LOCAL_HIGHLANDER_CACHE_LOCATION = "#{ENV['HOME']}/.highlander/components"
|
6
|
+
|
7
|
+
module Highlander
|
8
|
+
|
9
|
+
module Factory
|
10
|
+
|
11
|
+
class Component
|
12
|
+
|
13
|
+
attr_accessor :component_dir,
|
14
|
+
:config,
|
15
|
+
:highlander_dsl_path,
|
16
|
+
:cfndsl_path,
|
17
|
+
:highlander_dsl,
|
18
|
+
:cfndsl_content,
|
19
|
+
:mappings,
|
20
|
+
:name,
|
21
|
+
:version,
|
22
|
+
:distribution_bucket,
|
23
|
+
:distribution_prefix,
|
24
|
+
:component_files,
|
25
|
+
:cfndsl_ext_files,
|
26
|
+
:lambda_src_files
|
27
|
+
|
28
|
+
def initialize(component_name, component_dir)
|
29
|
+
@name = component_name
|
30
|
+
@component_dir = component_dir
|
31
|
+
@mappings = {}
|
32
|
+
@version = nil
|
33
|
+
@distribution_bucket = nil
|
34
|
+
@distribution_prefix = nil
|
35
|
+
@component_files = []
|
36
|
+
@cfndsl_ext_files = []
|
37
|
+
@lambda_src_files = []
|
38
|
+
end
|
39
|
+
|
40
|
+
def load_config()
|
41
|
+
@config = {} if @config.nil?
|
42
|
+
Dir["#{@component_dir}/*.config.yaml"].each do |config_file|
|
43
|
+
partial_config = YAML.load(File.read(config_file))
|
44
|
+
unless partial_config.nil?
|
45
|
+
@config.extend(partial_config)
|
46
|
+
@component_files << config_file
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
|
52
|
+
def loadDepandantExt()
|
53
|
+
@highlander_dsl.dependson_components.each do |requirement|
|
54
|
+
requirement.component_loaded.cfndsl_ext_files.each do |file|
|
55
|
+
cfndsl_ext_files << file
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
# @param [Hash] config_override
|
61
|
+
def load(config_override = nil)
|
62
|
+
if @component_dir.start_with? 'http'
|
63
|
+
raise StandardError, 'http(s) sources not supported yet'
|
64
|
+
end
|
65
|
+
|
66
|
+
|
67
|
+
@highlander_dsl_path = "#{@component_dir}/#{@name}.highlander.rb"
|
68
|
+
@cfndsl_path = "#{@component_dir}/#{@name}.cfndsl.rb"
|
69
|
+
candidate_config_path = "#{@component_dir}/#{@name}.config.yaml"
|
70
|
+
candidate_mappings_path = "#{@component_dir}/*.mappings.yaml"
|
71
|
+
candidate_dynamic_mappings_path = "#{@component_dir}/#{@name}.mappings.rb"
|
72
|
+
|
73
|
+
@cfndsl_ext_files += Dir["#{@component_dir}/ext/cfndsl/*.rb"]
|
74
|
+
@lambda_src_files += Dir["#{@component_dir}/lambdas/**/*"].find_all {|p| not File.directory? p}
|
75
|
+
@component_files += @cfndsl_ext_files
|
76
|
+
@component_files += @lambda_src_files
|
77
|
+
|
78
|
+
@config = {} if @config.nil?
|
79
|
+
|
80
|
+
@config.extend config_override unless config_override.nil?
|
81
|
+
@config['component_version'] = @version unless @version.nil?
|
82
|
+
# allow override of components
|
83
|
+
# config_override.each do |key, value|
|
84
|
+
# @config[key] = value
|
85
|
+
# end unless config_override.nil?
|
86
|
+
|
87
|
+
Dir[candidate_mappings_path].each do |mapping_file|
|
88
|
+
mappings = YAML.load(File.read(mapping_file))
|
89
|
+
@component_files << mapping_file
|
90
|
+
mappings.each do |name, map|
|
91
|
+
@mappings[name] = map
|
92
|
+
end unless mappings.nil?
|
93
|
+
end
|
94
|
+
|
95
|
+
if File.exist? candidate_dynamic_mappings_path
|
96
|
+
require candidate_dynamic_mappings_path
|
97
|
+
@component_files << candidate_dynamic_mappings_path
|
98
|
+
end
|
99
|
+
|
100
|
+
# 1st pass - parse the file
|
101
|
+
@component_files << @highlander_dsl_path
|
102
|
+
@highlander_dsl = eval(File.read(@highlander_dsl_path), binding)
|
103
|
+
|
104
|
+
# set version if not defined
|
105
|
+
@highlander_dsl.ComponentVersion(@version) unless @version.nil?
|
106
|
+
|
107
|
+
|
108
|
+
# Handle name and description defaults if they are not specified
|
109
|
+
# in template itself
|
110
|
+
if @highlander_dsl.name.nil?
|
111
|
+
@highlander_dsl.name = @name
|
112
|
+
end
|
113
|
+
|
114
|
+
if @highlander_dsl.description.nil?
|
115
|
+
@highlander_dsl.Description("#{@highlander_dsl.name} - #{@highlander_dsl.version}")
|
116
|
+
end
|
117
|
+
|
118
|
+
# set (override) distribution options
|
119
|
+
@highlander_dsl.DistributionBucket(@distribution_bucket) unless @distribution_bucket.nil?
|
120
|
+
@highlander_dsl.DistributionPrefix(@distribution_prefix) unless @distribution_prefix.nil?
|
121
|
+
|
122
|
+
if File.exist? @cfndsl_path
|
123
|
+
@component_files << @cfndsl_path
|
124
|
+
@cfndsl_content = File.read(@cfndsl_path)
|
125
|
+
@cfndsl_content.strip!
|
126
|
+
# if there is CloudFormation do [content] end extract only contents
|
127
|
+
### Regex \s is whitespace
|
128
|
+
match_data = /^CloudFormation do\s(.*)end\s?$/m.match(@cfndsl_content)
|
129
|
+
if not match_data.nil?
|
130
|
+
@cfndsl_content = match_data[1]
|
131
|
+
end
|
132
|
+
|
133
|
+
else
|
134
|
+
@cfndsl_content = ''
|
135
|
+
end
|
136
|
+
|
137
|
+
loadDepandantExt()
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
141
|
+
class ComponentFactory
|
142
|
+
|
143
|
+
attr_accessor :component_sources
|
144
|
+
|
145
|
+
|
146
|
+
def initialize(component_sources = [])
|
147
|
+
## First look in local $PWD/components folder
|
148
|
+
## Then search for cached $HOME/.highlander/components
|
149
|
+
## Then search in sources given by dsl
|
150
|
+
default_locations = [
|
151
|
+
LOCAL_HIGHLANDER_CACHE_LOCATION,
|
152
|
+
File.expand_path('components'),
|
153
|
+
File.expand_path('.')
|
154
|
+
]
|
155
|
+
default_locations.each do |predefined_path|
|
156
|
+
component_sources.unshift(predefined_path)
|
157
|
+
end
|
158
|
+
|
159
|
+
@component_sources = component_sources
|
160
|
+
end
|
161
|
+
|
162
|
+
def findComponentDefault(component_name, component_version)
|
163
|
+
default_lookup_url = 'https://github.com/theonestack'
|
164
|
+
default_lookup_url = ENV['HIGHLANDER_DEFAULT_COMPONENT_GIT_LOOKUP'] if ENV.key? 'HIGHLANDER_DEFAULT_COMPONENT_GIT_LOOKUP'
|
165
|
+
|
166
|
+
git_url = "#{default_lookup_url}/hl-component-#{component_name}"
|
167
|
+
|
168
|
+
if component_version.nil? or component_version.empty? or component_version == 'latest'
|
169
|
+
branch = 'master'
|
170
|
+
else
|
171
|
+
branch = component_version
|
172
|
+
end
|
173
|
+
local_path = "#{LOCAL_HIGHLANDER_CACHE_LOCATION}/#{component_name}/#{component_version}"
|
174
|
+
return findComponentGit(local_path, component_name, component_version, git_url, branch)
|
175
|
+
|
176
|
+
end
|
177
|
+
|
178
|
+
def findComponentGit(local_path, component_name, component_version, git_url, branch)
|
179
|
+
begin
|
180
|
+
local_path = "#{local_path}/" unless local_path.end_with? '/'
|
181
|
+
# if this is snapshot, clean local cache
|
182
|
+
if branch.end_with? '.snapshot'
|
183
|
+
branch = branch.gsub('.snapshot', '')
|
184
|
+
FileUtils.rmtree local_path if File.exist? local_path and File.directory? local_path
|
185
|
+
end
|
186
|
+
|
187
|
+
# if local cache exists, return from cache
|
188
|
+
if not Dir.glob("#{local_path}*.highlander.rb").empty?
|
189
|
+
# if cache exists, just return from cache
|
190
|
+
component_name = Dir.glob("#{local_path}*.highlander.rb")[0].gsub(local_path, '').gsub('.highlander.rb','')
|
191
|
+
return component_name, local_path
|
192
|
+
end
|
193
|
+
|
194
|
+
# shallow clone
|
195
|
+
puts "Trying to load #{component_name}/#{component_version} from #{git_url}##{branch} ... "
|
196
|
+
clone_opts = { depth: 1 }
|
197
|
+
clone_opts[:branch] = branch if not (branch.nil? or branch.empty?)
|
198
|
+
Git.clone git_url, local_path, clone_opts
|
199
|
+
puts "\t .. cached in #{local_path}\n"
|
200
|
+
# return from cache once it's cloned
|
201
|
+
return findComponentGit(local_path, component_name, component_version, git_url, branch)
|
202
|
+
rescue Exception => e
|
203
|
+
STDERR.puts "Failed to resolve component #{component_name}@#{component_version} from #{git_url}"
|
204
|
+
STDERR.puts e
|
205
|
+
return nil
|
206
|
+
end
|
207
|
+
end
|
208
|
+
|
209
|
+
def findComponentS3(s3_location, component_name, component_version)
|
210
|
+
parts = s3_location.split('/')
|
211
|
+
bucket = parts[2]
|
212
|
+
prefix = parts[3]
|
213
|
+
s3_key = "#{prefix}/#{component_name}/#{component_version}/#{component_name}.highlander.rb"
|
214
|
+
s3_prefix = "#{prefix}/#{component_name}/#{component_version}/"
|
215
|
+
local_destination = "#{LOCAL_HIGHLANDER_CACHE_LOCATION}/#{component_name}/#{component_version}"
|
216
|
+
begin
|
217
|
+
s3 = Aws::S3::Client.new({ region: s3_bucket_region(bucket) })
|
218
|
+
FileUtils.mkdir_p local_destination unless Dir.exist? local_destination
|
219
|
+
|
220
|
+
hl_content = s3.get_object({ bucket: bucket,
|
221
|
+
key: s3_key,
|
222
|
+
response_target: "#{local_destination}/#{component_name}.highlander.rb"
|
223
|
+
})
|
224
|
+
# if code execution got so far we consider file exists and download it locally
|
225
|
+
component_files = s3.list_objects_v2({ bucket: bucket, prefix: s3_prefix })
|
226
|
+
component_files.contents.each {|s3_object|
|
227
|
+
file_name = s3_object.key.gsub(s3_prefix, '')
|
228
|
+
destination_file = "#{local_destination}/#{file_name}"
|
229
|
+
destination_dir = File.dirname(destination_file)
|
230
|
+
print "Caching #{file_name} of #{component_name}@#{component_version} in #{destination_dir} ... "
|
231
|
+
|
232
|
+
FileUtils.mkpath(destination_dir) unless File.exists?(destination_dir)
|
233
|
+
s3.get_object({ bucket: bucket, key: s3_object.key, response_target: destination_file })
|
234
|
+
print " [OK] \n"
|
235
|
+
}
|
236
|
+
return local_destination
|
237
|
+
rescue => e
|
238
|
+
# this handles both nonexisting key and bucket
|
239
|
+
puts("#{component_name} not found in s3://#{bucket}/#{prefix}")
|
240
|
+
STDERR.puts(e.to_s) unless e.message.include? 'does not exist'
|
241
|
+
return nil
|
242
|
+
end
|
243
|
+
end
|
244
|
+
|
245
|
+
def findComponentGitTemplate(component_name, component_version)
|
246
|
+
if component_name.include? '#'
|
247
|
+
parts = component_name.split('#')
|
248
|
+
component_name = parts[0]
|
249
|
+
component_version = parts[1]
|
250
|
+
end
|
251
|
+
|
252
|
+
# avoid any nres
|
253
|
+
component_version = '' if component_version.nil?
|
254
|
+
|
255
|
+
# if empty or latest branch is empty
|
256
|
+
if component_version.empty? or component_version == 'latest' or component_version == 'latest.snapshot'
|
257
|
+
branch = ''
|
258
|
+
else
|
259
|
+
# otherwise component version is actual branch
|
260
|
+
branch = component_version
|
261
|
+
end
|
262
|
+
|
263
|
+
|
264
|
+
git_url = nil
|
265
|
+
if component_name.start_with? 'git:'
|
266
|
+
git_url = component_name.gsub('git:', '')
|
267
|
+
elsif component_name.start_with? 'github:'
|
268
|
+
git_url = "https://github.com/#{component_name.gsub('github:', '')}"
|
269
|
+
elsif component_name.start_with? 'github.com:'
|
270
|
+
git_url = "https://github.com/#{component_name.gsub('github.com:', '')}"
|
271
|
+
end
|
272
|
+
|
273
|
+
local_path = "#{LOCAL_HIGHLANDER_CACHE_LOCATION}/#{component_name}/#{component_version}"
|
274
|
+
|
275
|
+
if not git_url.nil?
|
276
|
+
component_name, location = findComponentGit(local_path, component_name, component_version, git_url, branch)
|
277
|
+
if location.nil?
|
278
|
+
raise "Could not resolve component #{component_name}@#{component_version}"
|
279
|
+
else
|
280
|
+
return component_name, location
|
281
|
+
end
|
282
|
+
end
|
283
|
+
|
284
|
+
return nil
|
285
|
+
end
|
286
|
+
|
287
|
+
# Find component and given list of sources
|
288
|
+
# @return [Highlander::Factory::Component]
|
289
|
+
def findComponent(component_name, component_version = nil)
|
290
|
+
|
291
|
+
component_version_s = component_version.nil? ? 'latest' : component_version
|
292
|
+
component_version = nil if component_version == 'latest'
|
293
|
+
|
294
|
+
if component_name.include? '@' and (not component_name.start_with? 'git')
|
295
|
+
parts = component_name.split('@')
|
296
|
+
component_name = parts[0]
|
297
|
+
component_version = parts[1]
|
298
|
+
end
|
299
|
+
|
300
|
+
# if component specified as git location
|
301
|
+
new_name, candidate_git = findComponentGitTemplate(component_name, component_version_s)
|
302
|
+
return buildComponent(new_name, candidate_git) unless candidate_git.nil?
|
303
|
+
|
304
|
+
# if not git but has .snapshot lookup in default
|
305
|
+
if (not component_version.nil?) and component_version.end_with? '.snapshot'
|
306
|
+
new_name, default_candidate = findComponentDefault(component_name, component_version_s)
|
307
|
+
return buildComponent(new_name, default_candidate) unless default_candidate.nil?
|
308
|
+
end
|
309
|
+
|
310
|
+
# try in all of the component source
|
311
|
+
@component_sources.each do |source|
|
312
|
+
component_full_name = "#{component_name}@#{component_version.nil? ? 'latest' : component_version}"
|
313
|
+
# TODO handle http(s) sources and their download to local
|
314
|
+
if source.start_with?('http')
|
315
|
+
raise StandardError, 'http(s) sources not supported yet'
|
316
|
+
elsif source.start_with?('s3://')
|
317
|
+
# s3 candidate
|
318
|
+
|
319
|
+
s3_candidate = findComponentS3(source, component_name, component_version_s)
|
320
|
+
if not s3_candidate.nil?
|
321
|
+
# at this point all component files are download to local file system and consumed from there
|
322
|
+
return buildComponent(component_name, s3_candidate)
|
323
|
+
end
|
324
|
+
|
325
|
+
else
|
326
|
+
# file system candidate
|
327
|
+
candidate = "#{source}/#{component_name}"
|
328
|
+
candidate = "#{candidate}/#{component_version}" unless component_version.nil?
|
329
|
+
candidate_hl_path = "#{candidate}/#{component_name}.highlander.rb"
|
330
|
+
candidate2_hl_path = "#{source}/#{component_name}.highlander.rb"
|
331
|
+
puts "Trying to load #{component_full_name} from #{candidate} ... "
|
332
|
+
if File.exist?(candidate_hl_path)
|
333
|
+
return buildComponent(component_name, candidate)
|
334
|
+
end
|
335
|
+
puts "Trying to load #{component_full_name} from #{source} ... "
|
336
|
+
if File.exist?(candidate2_hl_path)
|
337
|
+
return buildComponent(component_name, source)
|
338
|
+
end unless component_version_s != 'latest'
|
339
|
+
end
|
340
|
+
end
|
341
|
+
|
342
|
+
# try default component source on github
|
343
|
+
component_name, default_candidate = findComponentDefault(component_name, component_version_s)
|
344
|
+
return buildComponent(component_name, default_candidate) unless default_candidate.nil?
|
345
|
+
|
346
|
+
raise StandardError, "highlander template #{component_name}@#{component_version_s} not located" +
|
347
|
+
" in sources #{@component_sources}"
|
348
|
+
end
|
349
|
+
|
350
|
+
def buildComponent(component_name, component_dir)
|
351
|
+
component = Component.new(component_name, component_dir)
|
352
|
+
component.load_config
|
353
|
+
return component
|
354
|
+
end
|
355
|
+
|
356
|
+
end
|
357
|
+
end
|
358
|
+
|
359
|
+
end
|