lono 4.2.7 → 5.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.cody/README.md +6 -0
- data/.cody/acceptance.sh +30 -0
- data/.cody/buildspec.yml +21 -0
- data/.cody/demo.rb +38 -0
- data/.cody/project.rb +12 -0
- data/.cody/role.rb +1 -0
- data/.gitignore +2 -0
- data/.gitmodules +6 -3
- data/.travis.yml +7 -0
- data/CHANGELOG.md +10 -0
- data/Gemfile +0 -1
- data/LICENSE.txt +1 -22
- data/README.md +46 -55
- data/lib/lono.rb +20 -27
- data/lib/lono/app_file.rb +5 -0
- data/lib/lono/app_file/base.rb +19 -0
- data/lib/lono/app_file/build.rb +78 -0
- data/lib/lono/app_file/registry.rb +14 -0
- data/lib/lono/app_file/registry/item.rb +46 -0
- data/lib/lono/app_file/upload.rb +39 -0
- data/lib/lono/autoloader.rb +22 -0
- data/lib/lono/aws_services.rb +46 -0
- data/lib/lono/aws_services/util.rb +49 -0
- data/lib/lono/blueprint.rb +113 -0
- data/lib/lono/blueprint/find.rb +90 -0
- data/lib/lono/blueprint/helper.rb +18 -0
- data/lib/lono/blueprint/info.rb +10 -0
- data/lib/lono/blueprint/list.rb +14 -0
- data/lib/lono/blueprint/root.rb +43 -0
- data/lib/lono/cfn.rb +31 -19
- data/lib/lono/cfn/aws_service.rb +16 -0
- data/lib/lono/cfn/base.rb +244 -261
- data/lib/lono/cfn/create.rb +36 -32
- data/lib/lono/cfn/current.rb +1 -1
- data/lib/lono/cfn/delete.rb +2 -2
- data/lib/lono/cfn/deploy.rb +11 -0
- data/lib/lono/cfn/diff.rb +1 -1
- data/lib/lono/cfn/preview.rb +3 -3
- data/lib/lono/cfn/rollback.rb +26 -0
- data/lib/lono/cfn/status.rb +2 -203
- data/lib/lono/cfn/suffix.rb +67 -0
- data/lib/lono/cfn/update.rb +61 -53
- data/lib/lono/cli.rb +42 -23
- data/lib/lono/completer.rb +0 -2
- data/lib/lono/configure.rb +37 -0
- data/lib/lono/configure/aws_services.rb +18 -0
- data/lib/lono/configure/base.rb +94 -0
- data/lib/lono/configure/helpers.rb +128 -0
- data/lib/lono/conventions.rb +11 -0
- data/lib/lono/core.rb +42 -12
- data/lib/lono/core/config.rb +5 -4
- data/lib/lono/default/settings.yml +0 -11
- data/lib/lono/file_uploader.rb +9 -4
- data/lib/lono/help.rb +1 -2
- data/lib/lono/help/blueprint.md +46 -0
- data/lib/lono/help/cfn.md +5 -4
- data/lib/lono/help/cfn/create.md +14 -9
- data/lib/lono/help/cfn/deploy.md +92 -0
- data/lib/lono/help/cfn/diff.md +0 -1
- data/lib/lono/help/cfn/update.md +16 -15
- data/lib/lono/help/completion.md +3 -3
- data/lib/lono/help/generate.md +0 -1
- data/lib/lono/help/new.md +40 -34
- data/lib/lono/help/param.md +1 -1
- data/lib/lono/help/param/generate.md +1 -1
- data/lib/lono/help/template.md +2 -2
- data/lib/lono/help/xgraph.md +1 -1
- data/lib/lono/inspector.rb +1 -1
- data/lib/lono/inspector/base.rb +26 -10
- data/lib/lono/inspector/graph.rb +7 -3
- data/lib/lono/inspector/summary.rb +15 -3
- data/lib/lono/md5.rb +46 -0
- data/lib/lono/new.rb +40 -28
- data/lib/lono/new/helper.rb +2 -3
- data/lib/lono/param.rb +12 -11
- data/lib/lono/param/generator.rb +96 -42
- data/lib/lono/project_checker.rb +27 -8
- data/lib/lono/s3.rb +23 -0
- data/lib/lono/s3/bucket.rb +123 -0
- data/lib/lono/script.rb +4 -8
- data/lib/lono/script/base.rb +7 -2
- data/lib/lono/script/build.rb +7 -8
- data/lib/lono/script/upload.rb +4 -20
- data/lib/lono/sequence.rb +19 -16
- data/lib/lono/setting.rb +19 -27
- data/lib/lono/template.rb +22 -26
- data/lib/lono/template/base.rb +13 -0
- data/lib/lono/template/context.rb +4 -56
- data/lib/lono/template/context/loader.rb +70 -0
- data/lib/lono/template/dsl.rb +15 -151
- data/lib/lono/template/dsl/builder.rb +60 -0
- data/lib/lono/template/dsl/builder/base.rb +14 -0
- data/lib/lono/template/dsl/builder/condition.rb +26 -0
- data/lib/lono/template/dsl/builder/fn.rb +114 -0
- data/lib/lono/template/dsl/builder/helper.rb +64 -0
- data/lib/lono/template/dsl/builder/mapping.rb +24 -0
- data/lib/lono/template/dsl/builder/output.rb +37 -0
- data/lib/lono/template/dsl/builder/parameter.rb +39 -0
- data/lib/lono/template/dsl/builder/resource.rb +38 -0
- data/lib/lono/template/dsl/builder/section.rb +12 -0
- data/lib/lono/template/dsl/builder/syntax.rb +58 -0
- data/lib/lono/template/erb.rb +82 -0
- data/lib/lono/template/evaluate.rb +39 -0
- data/lib/lono/template/generator.rb +29 -0
- data/lib/lono/template/helper.rb +7 -29
- data/lib/lono/template/post_processor.rb +69 -0
- data/lib/lono/template/template.rb +4 -9
- data/lib/lono/template/upload.rb +103 -133
- data/lib/lono/template/util.rb +48 -0
- data/lib/lono/upgrade.rb +5 -3
- data/lib/lono/upgrade/upgrade5.rb +55 -0
- data/lib/lono/user_data.rb +4 -4
- data/lib/lono/version.rb +1 -1
- data/lib/templates/blueprint/%blueprint_name%.gemspec.tt +44 -0
- data/lib/templates/blueprint/.gitignore +14 -0
- data/lib/templates/blueprint/.lono/config.yml.tt +3 -0
- data/lib/templates/blueprint/.meta/config.yml.tt +3 -0
- data/lib/templates/blueprint/CHANGELOG.md +7 -0
- data/lib/templates/blueprint/Gemfile +4 -0
- data/lib/templates/blueprint/README.md +37 -0
- data/lib/templates/blueprint/Rakefile +6 -0
- data/lib/templates/blueprint/setup/configs.rb +54 -0
- data/lib/templates/blueprint_configs/configs/%blueprint_name%/params/base.txt +2 -0
- data/lib/{starter_projects/skeleton/app/definitions/base.rb → templates/blueprint_configs/configs/%blueprint_name%/params/development.txt} +0 -0
- data/lib/templates/blueprint_configs/configs/%blueprint_name%/variables/base.rb +2 -0
- data/lib/templates/blueprint_configs/configs/%blueprint_name%/variables/development.rb +0 -0
- data/lib/templates/blueprint_types/dsl/app/templates/%blueprint_name%.rb +37 -0
- data/lib/templates/blueprint_types/dsl/app/user_data/bootstrap.sh +2 -0
- data/lib/templates/blueprint_types/erb/app/definitions/base.rb.tt +1 -0
- data/lib/templates/blueprint_types/erb/app/templates/%blueprint_name%.yml +8 -0
- data/lib/{starter_projects/autoscaling → templates/skeleton}/.gitignore +1 -0
- data/lib/templates/skeleton/Gemfile +3 -0
- data/lib/{starter_projects/autoscaling → templates/skeleton}/Guardfile +2 -2
- data/lib/templates/skeleton/README.md +58 -0
- data/lib/templates/skeleton/configs/settings.yml +17 -0
- data/lib/templates/upgrade5/blueprints/main/.lono/config.yml +3 -0
- data/lib/templates/upgrade5/blueprints/main/.meta/config.yml +3 -0
- data/lono.gemspec +12 -8
- data/vendor/cfn-status/CHANGELOG.md +10 -0
- data/vendor/cfn-status/Gemfile +4 -0
- data/vendor/cfn-status/LICENSE.txt +21 -0
- data/vendor/cfn-status/README.md +56 -0
- data/vendor/cfn-status/Rakefile +6 -0
- data/vendor/cfn-status/bin/console +14 -0
- data/vendor/cfn-status/bin/setup +8 -0
- data/vendor/cfn-status/cfn-status.gemspec +30 -0
- data/vendor/cfn-status/lib/cfn-status.rb +1 -0
- data/vendor/cfn-status/lib/cfn/aws_service.rb +51 -0
- data/vendor/cfn-status/lib/cfn/status.rb +219 -0
- data/vendor/cfn-status/lib/cfn/status/version.rb +5 -0
- data/vendor/cfn-status/spec/cfn/status_spec.rb +81 -0
- data/vendor/cfn-status/spec/fixtures/cfn/stack-events-complete.json +1080 -0
- data/vendor/cfn-status/spec/fixtures/cfn/stack-events-in-progress.json +1080 -0
- data/vendor/cfn-status/spec/fixtures/cfn/stack-events-update-rollback-complete.json +1086 -0
- data/vendor/cfn-status/spec/spec_helper.rb +14 -0
- data/vendor/cfn_camelizer/CHANGELOG.md +20 -0
- data/vendor/cfn_camelizer/Gemfile +4 -0
- data/vendor/cfn_camelizer/LICENSE.txt +21 -0
- data/vendor/cfn_camelizer/README.md +40 -0
- data/vendor/cfn_camelizer/Rakefile +6 -0
- data/vendor/cfn_camelizer/bin/console +14 -0
- data/vendor/cfn_camelizer/bin/setup +8 -0
- data/vendor/cfn_camelizer/cfn_camelizer.gemspec +32 -0
- data/vendor/cfn_camelizer/lib/camelizer.yml +37 -0
- data/vendor/cfn_camelizer/lib/cfn_camelizer.rb +94 -0
- data/vendor/cfn_camelizer/lib/cfn_camelizer/version.rb +3 -0
- data/vendor/cfn_camelizer/spec/cfn_camelizer_spec.rb +86 -0
- data/vendor/cfn_camelizer/spec/spec_helper.rb +14 -0
- metadata +189 -62
- data/.circleci/bin/commit_docs.sh +0 -26
- data/.circleci/config.yml +0 -72
- data/bin/release +0 -9
- data/lib/lono/help/import.md +0 -54
- data/lib/lono/importer.rb +0 -134
- data/lib/lono/new/message.rb +0 -35
- data/lib/starter_projects/autoscaling/Gemfile +0 -3
- data/lib/starter_projects/autoscaling/README.md +0 -118
- data/lib/starter_projects/autoscaling/app/definitions/base.rb +0 -2
- data/lib/starter_projects/autoscaling/app/templates/autoscaling.yml +0 -682
- data/lib/starter_projects/autoscaling/config/params/base/autoscaling.txt +0 -6
- data/lib/starter_projects/autoscaling/config/settings.yml +0 -33
- data/lib/starter_projects/ec2/.gitignore +0 -2
- data/lib/starter_projects/ec2/Gemfile +0 -3
- data/lib/starter_projects/ec2/Guardfile +0 -12
- data/lib/starter_projects/ec2/README.md +0 -86
- data/lib/starter_projects/ec2/app/definitions/base.rb +0 -2
- data/lib/starter_projects/ec2/app/definitions/development.rb +0 -1
- data/lib/starter_projects/ec2/app/definitions/production.rb +0 -1
- data/lib/starter_projects/ec2/app/helpers/my_custom_helper.rb +0 -17
- data/lib/starter_projects/ec2/app/partials/user_data/bootstrap.sh +0 -4
- data/lib/starter_projects/ec2/app/templates/example.yml +0 -430
- data/lib/starter_projects/ec2/config/params/base/example.txt +0 -2
- data/lib/starter_projects/ec2/config/params/development/example.txt +0 -3
- data/lib/starter_projects/ec2/config/params/production/example.txt +0 -2
- data/lib/starter_projects/ec2/config/settings.yml +0 -33
- data/lib/starter_projects/ec2/config/variables/base.rb +0 -3
- data/lib/starter_projects/ec2/config/variables/development.rb +0 -2
- data/lib/starter_projects/ec2/config/variables/production.rb +0 -2
- data/lib/starter_projects/ec2/welcome.txt +0 -8
- data/lib/starter_projects/skeleton/.gitignore +0 -2
- data/lib/starter_projects/skeleton/Gemfile +0 -3
- data/lib/starter_projects/skeleton/Guardfile +0 -12
- data/lib/starter_projects/skeleton/README.md +0 -53
- data/lib/starter_projects/skeleton/config/settings.yml +0 -33
- data/lib/starter_projects/skeleton/welcome.txt +0 -7
- data/vendor/plissken/Gemfile +0 -14
- data/vendor/plissken/LICENSE.txt +0 -20
- data/vendor/plissken/README.md +0 -46
- data/vendor/plissken/Rakefile +0 -56
- data/vendor/plissken/VERSION +0 -1
- data/vendor/plissken/lib/plissken.rb +0 -1
- data/vendor/plissken/lib/plissken/ext/hash/to_snake_keys.rb +0 -45
- data/vendor/plissken/plissken.gemspec +0 -61
- data/vendor/plissken/spec/lib/to_snake_keys_spec.rb +0 -177
- data/vendor/plissken/spec/spec_helper.rb +0 -90
- data/vendor/plissken/test/helper.rb +0 -20
- data/vendor/plissken/test/plissken/ext/hash/to_snake_keys_test.rb +0 -184
- data/vendor/plissken/test/test_plissken.rb +0 -2
@@ -0,0 +1,82 @@
|
|
1
|
+
class Lono::Template
|
2
|
+
class Erb < Base
|
3
|
+
include Evaluate
|
4
|
+
include Util
|
5
|
+
|
6
|
+
def initialize(blueprint, options={})
|
7
|
+
super
|
8
|
+
@templates = []
|
9
|
+
@results = {}
|
10
|
+
end
|
11
|
+
|
12
|
+
def run(options={})
|
13
|
+
evaluate_templates
|
14
|
+
build_templates
|
15
|
+
write_output
|
16
|
+
end
|
17
|
+
|
18
|
+
# Instance eval's the template declarations in app/definitions in this order:
|
19
|
+
#
|
20
|
+
# app/definitions/base.rb
|
21
|
+
# app/definitions/base - all files in folder
|
22
|
+
# app/definitions/[Lono.env].rb
|
23
|
+
# app/definitions/[Lono.env] - all files in folder
|
24
|
+
#
|
25
|
+
# So Lono.env specific template declarations override base template declarations.
|
26
|
+
def evaluate_templates
|
27
|
+
evaluate_template("base")
|
28
|
+
evaluate_folder("base")
|
29
|
+
evaluate_template(Lono.env)
|
30
|
+
evaluate_folder(Lono.env)
|
31
|
+
end
|
32
|
+
|
33
|
+
def evaluate_template(name)
|
34
|
+
path = "#{Lono.config.definitions_path}/#{name}.rb"
|
35
|
+
evaluate_template_path(path)
|
36
|
+
end
|
37
|
+
|
38
|
+
def evaluate_folder(folder)
|
39
|
+
paths = Dir.glob("#{Lono.config.definitions_path}/#{folder}/**/*")
|
40
|
+
paths.select{ |e| File.file?(e) }.each do |path|
|
41
|
+
evaluate_template_path(path)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def template(name, &block)
|
46
|
+
@templates << {name: name, block: block}
|
47
|
+
end
|
48
|
+
|
49
|
+
def build_templates
|
50
|
+
@templates.each do |t|
|
51
|
+
@results[t[:name]] = Lono::Template::Template.new(@blueprint, t[:name], t[:block], @options).build
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
def write_output
|
56
|
+
output_path = "#{Lono.config.output_path}/#{@blueprint}/templates"
|
57
|
+
FileUtils.rm_rf(Lono.config.output_path) if @options[:clean] # removes entire output folder. params and templates
|
58
|
+
FileUtils.mkdir_p(output_path)
|
59
|
+
puts "Generating CloudFormation templates for blueprint #{@blueprint.color(:green)}:" unless @options[:quiet]
|
60
|
+
@results.each do |name,text|
|
61
|
+
path = "#{output_path}/#{name}".sub(/^\.\//,'') # strip leading '.'
|
62
|
+
path += ".yml"
|
63
|
+
unless @options[:quiet]
|
64
|
+
pretty_path = path.sub("#{Lono.root}/",'')
|
65
|
+
puts " #{pretty_path}"
|
66
|
+
end
|
67
|
+
ensure_parent_dir(path)
|
68
|
+
text = commented(text)
|
69
|
+
IO.write(path, text) # write file first so validate method is simpler
|
70
|
+
validate_yaml(path)
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
def commented(text)
|
75
|
+
comment =<<~EOS
|
76
|
+
# This file was generated with lono. Do not edit directly, the changes will be lost.
|
77
|
+
# More info: http://lono.cloud
|
78
|
+
EOS
|
79
|
+
"#{comment}#{text}"
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
class Lono::Template
|
2
|
+
module Evaluate
|
3
|
+
def evaluate_template_path(path)
|
4
|
+
return unless File.exist?(path)
|
5
|
+
|
6
|
+
begin
|
7
|
+
instance_eval(File.read(path), path)
|
8
|
+
rescue Exception => e
|
9
|
+
template_evaluation_error(e)
|
10
|
+
puts "\nFull error:"
|
11
|
+
raise
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
# Prints out a user friendly task_definition error message
|
16
|
+
def template_evaluation_error(e)
|
17
|
+
error_info = e.backtrace.first
|
18
|
+
path, line_no, _ = error_info.split(':')
|
19
|
+
line_no = line_no.to_i
|
20
|
+
puts "Error evaluating #{path}:".color(:red)
|
21
|
+
puts e.message
|
22
|
+
puts "Here's the line in #{path} with the error:\n\n"
|
23
|
+
|
24
|
+
contents = IO.read(path)
|
25
|
+
content_lines = contents.split("\n")
|
26
|
+
context = 5 # lines of context
|
27
|
+
top, bottom = [line_no-context-1, 0].max, line_no+context-1
|
28
|
+
spacing = content_lines.size.to_s.size
|
29
|
+
content_lines[top..bottom].each_with_index do |line_content, index|
|
30
|
+
line_number = top+index+1
|
31
|
+
if line_number == line_no
|
32
|
+
printf("%#{spacing}d %s\n".color(:red), line_number, line_content)
|
33
|
+
else
|
34
|
+
printf("%#{spacing}d %s\n", line_number, line_content)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
require "yaml"
|
2
|
+
|
3
|
+
class Lono::Template
|
4
|
+
class Generator
|
5
|
+
include Lono::Blueprint::Root
|
6
|
+
|
7
|
+
def initialize(blueprint, options={})
|
8
|
+
@blueprint, @options = blueprint, options
|
9
|
+
@template = @options[:template] || @blueprint
|
10
|
+
Lono::ProjectChecker.check
|
11
|
+
set_blueprint_root(@blueprint)
|
12
|
+
end
|
13
|
+
|
14
|
+
def run
|
15
|
+
# Examples:
|
16
|
+
# Erb.new(b, options.clone).run
|
17
|
+
# Dsl.new(b, options.clone).run
|
18
|
+
generator_class = "Lono::Template::#{template_type.classify}"
|
19
|
+
generator_class = Object.const_get(generator_class)
|
20
|
+
generator_class.new(@blueprint, @options.clone).run
|
21
|
+
end
|
22
|
+
|
23
|
+
def template_type
|
24
|
+
meta_config = "#{Lono.blueprint_root}/.meta/config.yml"
|
25
|
+
data = YAML.load_file(meta_config)
|
26
|
+
data["template_type"] || "dsl"
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
data/lib/lono/template/helper.rb
CHANGED
@@ -5,12 +5,10 @@ require "aws-sdk-core"
|
|
5
5
|
#
|
6
6
|
# @options gets passed into:
|
7
7
|
#
|
8
|
-
# Lono::Template::Context.new(@options)
|
8
|
+
# Lono::Template::Context.new(blueprint, @options)
|
9
9
|
module Lono::Template::Helper
|
10
10
|
# Bash code that is meant to included in user-data
|
11
11
|
def extract_scripts(options={})
|
12
|
-
check_s3_folder_settings!
|
13
|
-
|
14
12
|
settings = setting.data["extract_scripts"] || {}
|
15
13
|
options = settings.merge(options)
|
16
14
|
# defaults also here in case they are removed from settings
|
@@ -38,40 +36,28 @@ aws s3 cp #{scripts_s3_path} #{to}/
|
|
38
36
|
BASH_CODE
|
39
37
|
end
|
40
38
|
|
41
|
-
def check_s3_folder_settings!
|
42
|
-
return if setting.s3_folder
|
43
|
-
|
44
|
-
puts "Helper method called that requires the s3_folder to be set at:"
|
45
|
-
lines = caller.reject { |l| l =~ %r{lib/lono} } # hide internal lono trace
|
46
|
-
puts " #{lines[0]}"
|
47
|
-
|
48
|
-
puts "Please configure your settings.yml with an s3_folder.".color(:red)
|
49
|
-
puts "Detected AWS_PROFILE #{ENV['AWS_PROFILE'].inspect}"
|
50
|
-
exit 1
|
51
|
-
end
|
52
|
-
|
53
39
|
def scripts_name
|
54
40
|
File.basename(scripts_s3_path)
|
55
41
|
end
|
56
42
|
|
57
43
|
def scripts_s3_path
|
58
|
-
upload = Lono::Script::Upload.new
|
44
|
+
upload = Lono::Script::Upload.new(@blueprint)
|
59
45
|
upload.s3_dest
|
60
46
|
end
|
61
47
|
|
62
48
|
def template_s3_path(template_name)
|
63
|
-
check_s3_folder_settings!
|
64
49
|
# high jacking Upload for useful s3_https_url method
|
65
|
-
template_path = "
|
66
|
-
upload = Lono::Template::Upload.new(@options)
|
50
|
+
template_path = "output/#{@blueprint}/templates/#{template_name}.yml"
|
51
|
+
upload = Lono::Template::Upload.new(@blueprint, @options)
|
67
52
|
upload.s3_https_url(template_path)
|
68
53
|
end
|
69
54
|
|
70
55
|
def template_params(param_name)
|
71
56
|
generator_options = {
|
72
|
-
|
57
|
+
allow_not_exists: true
|
73
58
|
}.merge(@options)
|
74
|
-
|
59
|
+
generator_options["param"] = param_name
|
60
|
+
generator = Lono::Param::Generator.new(@blueprint, generator_options)
|
75
61
|
# do not generate because lono cfn calling logic already generated it we only need the values
|
76
62
|
params = generator.params # Returns Array in underscore keys format
|
77
63
|
# convert Array to simplified hash structure
|
@@ -122,14 +108,6 @@ BASH_CODE
|
|
122
108
|
path && File.exist?(path)
|
123
109
|
end
|
124
110
|
|
125
|
-
def file_s3_key(name)
|
126
|
-
s3_folder = setting.s3_folder
|
127
|
-
return nil unless s3_folder
|
128
|
-
|
129
|
-
uploader = Lono::FileUploader.new
|
130
|
-
uploader.md5_key("#{Lono.root}/app/files/#{name}")
|
131
|
-
end
|
132
|
-
|
133
111
|
def current_region
|
134
112
|
region = Aws.config[:region]
|
135
113
|
region ||= ENV['AWS_REGION']
|
@@ -0,0 +1,69 @@
|
|
1
|
+
class Lono::Template
|
2
|
+
class PostProcessor
|
3
|
+
include Lono::Blueprint::Root
|
4
|
+
extend Memoist
|
5
|
+
|
6
|
+
def initialize(blueprint, options={})
|
7
|
+
@blueprint, @options = blueprint, options
|
8
|
+
@template = @options[:template] || @blueprint
|
9
|
+
Lono::ProjectChecker.check
|
10
|
+
set_blueprint_root(@blueprint)
|
11
|
+
end
|
12
|
+
|
13
|
+
def run
|
14
|
+
replacements.each do |placeholder, replacement|
|
15
|
+
update_template!(template)
|
16
|
+
end
|
17
|
+
write_template!
|
18
|
+
end
|
19
|
+
|
20
|
+
def write_template!
|
21
|
+
IO.write(template_path, YAML.dump(template)) # unless ENV['TEST'] # additional safeguard for testing
|
22
|
+
end
|
23
|
+
|
24
|
+
def replacements
|
25
|
+
map = {}
|
26
|
+
registry_items.each do |item|
|
27
|
+
if item.directory? || item.file?
|
28
|
+
replacement = item.s3_path
|
29
|
+
else
|
30
|
+
puts "WARN: PostProcessor replacements Cannot find file: #{item.path}"
|
31
|
+
next
|
32
|
+
end
|
33
|
+
|
34
|
+
placeholder = "file://app/files/#{item.name}"
|
35
|
+
map[placeholder] = replacement
|
36
|
+
end
|
37
|
+
map
|
38
|
+
end
|
39
|
+
|
40
|
+
def update_template!(hash)
|
41
|
+
hash.each do |k, v|
|
42
|
+
if v.is_a?(String)
|
43
|
+
if v =~ %r{^file://}
|
44
|
+
v.replace(replacements[v]) # replace the placeholder
|
45
|
+
end
|
46
|
+
elsif v.is_a?(Hash)
|
47
|
+
update_template!(v) # recurse
|
48
|
+
elsif v.is_a?(Array)
|
49
|
+
v.each { |x| update_template!(x) if x.is_a?(Hash) }
|
50
|
+
end
|
51
|
+
end
|
52
|
+
hash
|
53
|
+
end
|
54
|
+
|
55
|
+
# Useful for specs
|
56
|
+
def registry_items
|
57
|
+
Lono::AppFile::Registry.items
|
58
|
+
end
|
59
|
+
|
60
|
+
def template
|
61
|
+
YAML.load_file(template_path)
|
62
|
+
end
|
63
|
+
memoize :template
|
64
|
+
|
65
|
+
def template_path
|
66
|
+
"#{Lono.config.output_path}/#{@blueprint}/templates/#{@template}.yml"
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
@@ -5,7 +5,7 @@ require 'base64'
|
|
5
5
|
class Lono::Template::Template
|
6
6
|
include ERB::Util
|
7
7
|
|
8
|
-
# Main template
|
8
|
+
# Main template Erb methods are: source and variables
|
9
9
|
#
|
10
10
|
# template "example-2" do
|
11
11
|
# source "example"
|
@@ -13,13 +13,8 @@ class Lono::Template::Template
|
|
13
13
|
# end
|
14
14
|
#
|
15
15
|
attr_reader :name
|
16
|
-
def initialize(name, block=nil, options={})
|
17
|
-
|
18
|
-
# variables from config/variables and those instance variables can clobber these
|
19
|
-
# instance variables
|
20
|
-
@name = name
|
21
|
-
@block = block
|
22
|
-
@options = options
|
16
|
+
def initialize(blueprint, name, block=nil, options={})
|
17
|
+
@blueprint, @name, @block, @options = blueprint, name, block, options
|
23
18
|
@source_path = default_source_path(name)
|
24
19
|
end
|
25
20
|
|
@@ -54,6 +49,6 @@ class Lono::Template::Template
|
|
54
49
|
# Context for ERB rendering.
|
55
50
|
# This is where we control what references get passed to the ERB rendering.
|
56
51
|
def context
|
57
|
-
@context ||= Lono::Template::Context.new(@options)
|
52
|
+
@context ||= Lono::Template::Context.new(@blueprint, @options)
|
58
53
|
end
|
59
54
|
end
|
data/lib/lono/template/upload.rb
CHANGED
@@ -3,150 +3,120 @@ require 'json'
|
|
3
3
|
require 'base64'
|
4
4
|
require 'digest'
|
5
5
|
|
6
|
-
class Lono::Template
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
6
|
+
class Lono::Template
|
7
|
+
class Upload
|
8
|
+
include Lono::Blueprint::Root
|
9
|
+
include Lono::AwsServices
|
10
|
+
|
11
|
+
def initialize(blueprint, options={})
|
12
|
+
@blueprint, @options = blueprint, options
|
13
|
+
@template = @options[:template] || @blueprint
|
14
|
+
Lono::ProjectChecker.check
|
15
|
+
set_blueprint_root(@blueprint)
|
16
|
+
|
17
|
+
@checksums = {}
|
18
|
+
@prefix = Lono.env # s3://s3-bucket/development
|
19
|
+
end
|
14
20
|
|
15
|
-
|
16
|
-
|
17
|
-
load_checksums!
|
21
|
+
def run
|
22
|
+
load_checksums!
|
18
23
|
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
24
|
+
say "Uploading CloudFormation templates..."
|
25
|
+
paths = Dir.glob("#{Lono.config.output_path}/#{@blueprint}/templates/**/*")
|
26
|
+
paths.select { |p| File.file?(p) }.each do |path|
|
27
|
+
upload(path)
|
28
|
+
end
|
29
|
+
say "Templates uploaded to s3."
|
23
30
|
end
|
24
|
-
say "Templates uploaded to s3."
|
25
|
-
end
|
26
31
|
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
# etag is the checksum as long as the file is not a multi-part file upload
|
45
|
-
# it has extra double quotes wrapped around it.
|
46
|
-
# etag = "\"9cb437490cee2cc96101baf326e5ca81\""
|
47
|
-
@checksums[object.key] = strip_surrounding_quotes(object.etag)
|
32
|
+
# Read existing files on s3 to grab their md5 checksum.
|
33
|
+
# We do this so we can see if we should avoid re-uploading the s3 child template
|
34
|
+
# entirely. If we upload a new child template that does not change AWS CloudFormation
|
35
|
+
# is not smart enough to know that it not has changed. I think all AWS CloudFormation
|
36
|
+
# does is check if the file's timestamp.
|
37
|
+
#
|
38
|
+
# Thought this would result in better AWS Change Set info but AWS still reports child
|
39
|
+
# stacks being changed even though they should not be reported. Leaving this s3 checksum
|
40
|
+
# in for now.
|
41
|
+
def load_checksums!
|
42
|
+
return if @options[:noop]
|
43
|
+
|
44
|
+
resp = s3.list_objects(bucket: s3_bucket, prefix: @prefix)
|
45
|
+
resp.contents.each do |object|
|
46
|
+
@checksums[object.key] = strip_surrounding_quotes(object.etag)
|
47
|
+
end
|
48
|
+
@checksums
|
48
49
|
end
|
49
|
-
@checksums
|
50
|
-
end
|
51
|
-
|
52
|
-
def strip_surrounding_quotes(string)
|
53
|
-
string.sub(/^"/,'').sub(/"$/,'')
|
54
|
-
end
|
55
50
|
|
56
|
-
|
57
|
-
|
58
|
-
key = "#{@prefix}/#{pretty_path.sub(%r{output/templates/},'')}"
|
59
|
-
s3_full_path = "s3://#{s3_bucket}/#{key}"
|
60
|
-
|
61
|
-
local_checksum = Digest::MD5.hexdigest(IO.read(path))
|
62
|
-
remote_checksum = remote_checksum(path)
|
63
|
-
if local_checksum == remote_checksum
|
64
|
-
say("Not modified: #{pretty_path} to #{s3_full_path}".color(:yellow)) unless @options[:noop]
|
65
|
-
return # do not upload unless the checksum has changed
|
51
|
+
def strip_surrounding_quotes(string)
|
52
|
+
string.sub(/^"/,'').sub(/"$/,'')
|
66
53
|
end
|
67
54
|
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
ensure_s3_setup!
|
98
|
-
"https://s3.amazonaws.com/#{s3_bucket}/#{@prefix}/#{template_path}"
|
99
|
-
end
|
100
|
-
|
101
|
-
# used for cfn/base.rb def set_template_body!(params)
|
102
|
-
def s3_presigned_url(template_output_path)
|
103
|
-
template_path = template_output_path.sub('output/templates/','')
|
104
|
-
key = "#{@prefix}/#{template_path}"
|
105
|
-
s3_presigner.presigned_url(:get_object, bucket: s3_bucket, key: key)
|
106
|
-
end
|
107
|
-
|
108
|
-
def s3_presigner
|
109
|
-
@signer ||= Aws::S3::Presigner.new
|
110
|
-
end
|
111
|
-
|
112
|
-
# Parse the s3_folder setting and remove the folder portion to leave the
|
113
|
-
# "s3_bucket" portion
|
114
|
-
# Example:
|
115
|
-
# s3_bucket('s3://mybucket/templates/storage/path')
|
116
|
-
# => mybucket
|
117
|
-
def s3_bucket
|
118
|
-
return nil if @options[:noop] # to get spec passing
|
119
|
-
return nil unless s3_folder
|
120
|
-
s3_folder.sub('s3://','').split('/').first
|
121
|
-
end
|
55
|
+
def upload(path)
|
56
|
+
return if @options[:noop]
|
57
|
+
|
58
|
+
path = path.sub("#{Lono.root}/",'')
|
59
|
+
pretty_path = path.sub(/^\.\//, '')
|
60
|
+
key = "#{@prefix}/#{pretty_path.sub(%r{output/templates/},'')}"
|
61
|
+
s3_full_path = "s3://#{s3_bucket}/#{key}"
|
62
|
+
|
63
|
+
local_checksum = Digest::MD5.hexdigest(IO.read(path))
|
64
|
+
remote_checksum = remote_checksum(path)
|
65
|
+
if local_checksum == remote_checksum
|
66
|
+
say("Not modified: #{pretty_path} to #{s3_full_path}".color(:yellow)) unless @options[:noop]
|
67
|
+
return # do not upload unless the checksum has changed
|
68
|
+
end
|
69
|
+
|
70
|
+
resp = s3.put_object(
|
71
|
+
body: IO.read(path),
|
72
|
+
bucket: s3_bucket,
|
73
|
+
key: key,
|
74
|
+
storage_class: "REDUCED_REDUNDANCY"
|
75
|
+
) unless @options[:noop]
|
76
|
+
|
77
|
+
# Example output:
|
78
|
+
# Uploaded: output/templates/docker.yml to s3://boltops-dev/s3_folder/templates/development/docker.yml
|
79
|
+
# Uploaded: output/templates/ecs/private.yml to s3://boltops-dev/s3_folder/templates/development/ecs/private.yml
|
80
|
+
message = "Uploaded: #{pretty_path} to #{s3_full_path}".color(:green)
|
81
|
+
message = "NOOP: #{message}" if @options[:noop]
|
82
|
+
say message
|
83
|
+
end
|
122
84
|
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
85
|
+
# @checksums map has a key format: s3_folder/templates/development/docker.yml
|
86
|
+
#
|
87
|
+
# path = ./output/templates/docker.yml
|
88
|
+
# s3_folder = s3://boltops-dev/s3_folder/templates/development/docker.yml
|
89
|
+
def remote_checksum(path)
|
90
|
+
# first convert the local path to the path format that is stored in @checksums keys
|
91
|
+
# ./output/templates/docker.yml => s3_folder/templates/development/docker.yml
|
92
|
+
pretty_path = path.sub(/^\.\//, '')
|
93
|
+
key = "#{@prefix}/#{pretty_path.sub(%r{output/templates/},'')}"
|
94
|
+
@checksums[key]
|
95
|
+
end
|
133
96
|
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
97
|
+
# https://s3.amazonaws.com/mybucket/s3_folder/templates/production/parent.yml
|
98
|
+
def s3_https_url(template_path)
|
99
|
+
"https://s3.amazonaws.com/#{s3_bucket}/#{@prefix}/#{template_path}"
|
100
|
+
end
|
138
101
|
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
102
|
+
# used for cfn/base.rb def set_template_body!(params)
|
103
|
+
def s3_presigned_url(template_output_path)
|
104
|
+
template_path = template_output_path.sub('output/templates/','')
|
105
|
+
key = "#{@prefix}/#{template_path}"
|
106
|
+
s3_presigner.presigned_url(:get_object, bucket: s3_bucket, key: key)
|
107
|
+
end
|
143
108
|
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
109
|
+
# Parse the s3_folder setting and remove the folder portion to leave the
|
110
|
+
# "s3_bucket" portion
|
111
|
+
# Example:
|
112
|
+
# s3_bucket('s3://mybucket/templates/storage/path')
|
113
|
+
# => mybucket
|
114
|
+
def s3_bucket
|
115
|
+
Lono::S3::Bucket.name
|
116
|
+
end
|
148
117
|
|
149
|
-
|
150
|
-
|
118
|
+
def say(message)
|
119
|
+
puts message unless @options[:quiet]
|
120
|
+
end
|
151
121
|
end
|
152
|
-
end
|
122
|
+
end
|