lono 4.2.7 → 5.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (219) hide show
  1. checksums.yaml +4 -4
  2. data/.cody/README.md +6 -0
  3. data/.cody/acceptance.sh +30 -0
  4. data/.cody/buildspec.yml +21 -0
  5. data/.cody/demo.rb +38 -0
  6. data/.cody/project.rb +12 -0
  7. data/.cody/role.rb +1 -0
  8. data/.gitignore +2 -0
  9. data/.gitmodules +6 -3
  10. data/.travis.yml +7 -0
  11. data/CHANGELOG.md +10 -0
  12. data/Gemfile +0 -1
  13. data/LICENSE.txt +1 -22
  14. data/README.md +46 -55
  15. data/lib/lono.rb +20 -27
  16. data/lib/lono/app_file.rb +5 -0
  17. data/lib/lono/app_file/base.rb +19 -0
  18. data/lib/lono/app_file/build.rb +78 -0
  19. data/lib/lono/app_file/registry.rb +14 -0
  20. data/lib/lono/app_file/registry/item.rb +46 -0
  21. data/lib/lono/app_file/upload.rb +39 -0
  22. data/lib/lono/autoloader.rb +22 -0
  23. data/lib/lono/aws_services.rb +46 -0
  24. data/lib/lono/aws_services/util.rb +49 -0
  25. data/lib/lono/blueprint.rb +113 -0
  26. data/lib/lono/blueprint/find.rb +90 -0
  27. data/lib/lono/blueprint/helper.rb +18 -0
  28. data/lib/lono/blueprint/info.rb +10 -0
  29. data/lib/lono/blueprint/list.rb +14 -0
  30. data/lib/lono/blueprint/root.rb +43 -0
  31. data/lib/lono/cfn.rb +31 -19
  32. data/lib/lono/cfn/aws_service.rb +16 -0
  33. data/lib/lono/cfn/base.rb +244 -261
  34. data/lib/lono/cfn/create.rb +36 -32
  35. data/lib/lono/cfn/current.rb +1 -1
  36. data/lib/lono/cfn/delete.rb +2 -2
  37. data/lib/lono/cfn/deploy.rb +11 -0
  38. data/lib/lono/cfn/diff.rb +1 -1
  39. data/lib/lono/cfn/preview.rb +3 -3
  40. data/lib/lono/cfn/rollback.rb +26 -0
  41. data/lib/lono/cfn/status.rb +2 -203
  42. data/lib/lono/cfn/suffix.rb +67 -0
  43. data/lib/lono/cfn/update.rb +61 -53
  44. data/lib/lono/cli.rb +42 -23
  45. data/lib/lono/completer.rb +0 -2
  46. data/lib/lono/configure.rb +37 -0
  47. data/lib/lono/configure/aws_services.rb +18 -0
  48. data/lib/lono/configure/base.rb +94 -0
  49. data/lib/lono/configure/helpers.rb +128 -0
  50. data/lib/lono/conventions.rb +11 -0
  51. data/lib/lono/core.rb +42 -12
  52. data/lib/lono/core/config.rb +5 -4
  53. data/lib/lono/default/settings.yml +0 -11
  54. data/lib/lono/file_uploader.rb +9 -4
  55. data/lib/lono/help.rb +1 -2
  56. data/lib/lono/help/blueprint.md +46 -0
  57. data/lib/lono/help/cfn.md +5 -4
  58. data/lib/lono/help/cfn/create.md +14 -9
  59. data/lib/lono/help/cfn/deploy.md +92 -0
  60. data/lib/lono/help/cfn/diff.md +0 -1
  61. data/lib/lono/help/cfn/update.md +16 -15
  62. data/lib/lono/help/completion.md +3 -3
  63. data/lib/lono/help/generate.md +0 -1
  64. data/lib/lono/help/new.md +40 -34
  65. data/lib/lono/help/param.md +1 -1
  66. data/lib/lono/help/param/generate.md +1 -1
  67. data/lib/lono/help/template.md +2 -2
  68. data/lib/lono/help/xgraph.md +1 -1
  69. data/lib/lono/inspector.rb +1 -1
  70. data/lib/lono/inspector/base.rb +26 -10
  71. data/lib/lono/inspector/graph.rb +7 -3
  72. data/lib/lono/inspector/summary.rb +15 -3
  73. data/lib/lono/md5.rb +46 -0
  74. data/lib/lono/new.rb +40 -28
  75. data/lib/lono/new/helper.rb +2 -3
  76. data/lib/lono/param.rb +12 -11
  77. data/lib/lono/param/generator.rb +96 -42
  78. data/lib/lono/project_checker.rb +27 -8
  79. data/lib/lono/s3.rb +23 -0
  80. data/lib/lono/s3/bucket.rb +123 -0
  81. data/lib/lono/script.rb +4 -8
  82. data/lib/lono/script/base.rb +7 -2
  83. data/lib/lono/script/build.rb +7 -8
  84. data/lib/lono/script/upload.rb +4 -20
  85. data/lib/lono/sequence.rb +19 -16
  86. data/lib/lono/setting.rb +19 -27
  87. data/lib/lono/template.rb +22 -26
  88. data/lib/lono/template/base.rb +13 -0
  89. data/lib/lono/template/context.rb +4 -56
  90. data/lib/lono/template/context/loader.rb +70 -0
  91. data/lib/lono/template/dsl.rb +15 -151
  92. data/lib/lono/template/dsl/builder.rb +60 -0
  93. data/lib/lono/template/dsl/builder/base.rb +14 -0
  94. data/lib/lono/template/dsl/builder/condition.rb +26 -0
  95. data/lib/lono/template/dsl/builder/fn.rb +114 -0
  96. data/lib/lono/template/dsl/builder/helper.rb +64 -0
  97. data/lib/lono/template/dsl/builder/mapping.rb +24 -0
  98. data/lib/lono/template/dsl/builder/output.rb +37 -0
  99. data/lib/lono/template/dsl/builder/parameter.rb +39 -0
  100. data/lib/lono/template/dsl/builder/resource.rb +38 -0
  101. data/lib/lono/template/dsl/builder/section.rb +12 -0
  102. data/lib/lono/template/dsl/builder/syntax.rb +58 -0
  103. data/lib/lono/template/erb.rb +82 -0
  104. data/lib/lono/template/evaluate.rb +39 -0
  105. data/lib/lono/template/generator.rb +29 -0
  106. data/lib/lono/template/helper.rb +7 -29
  107. data/lib/lono/template/post_processor.rb +69 -0
  108. data/lib/lono/template/template.rb +4 -9
  109. data/lib/lono/template/upload.rb +103 -133
  110. data/lib/lono/template/util.rb +48 -0
  111. data/lib/lono/upgrade.rb +5 -3
  112. data/lib/lono/upgrade/upgrade5.rb +55 -0
  113. data/lib/lono/user_data.rb +4 -4
  114. data/lib/lono/version.rb +1 -1
  115. data/lib/templates/blueprint/%blueprint_name%.gemspec.tt +44 -0
  116. data/lib/templates/blueprint/.gitignore +14 -0
  117. data/lib/templates/blueprint/.lono/config.yml.tt +3 -0
  118. data/lib/templates/blueprint/.meta/config.yml.tt +3 -0
  119. data/lib/templates/blueprint/CHANGELOG.md +7 -0
  120. data/lib/templates/blueprint/Gemfile +4 -0
  121. data/lib/templates/blueprint/README.md +37 -0
  122. data/lib/templates/blueprint/Rakefile +6 -0
  123. data/lib/templates/blueprint/setup/configs.rb +54 -0
  124. data/lib/templates/blueprint_configs/configs/%blueprint_name%/params/base.txt +2 -0
  125. data/lib/{starter_projects/skeleton/app/definitions/base.rb → templates/blueprint_configs/configs/%blueprint_name%/params/development.txt} +0 -0
  126. data/lib/templates/blueprint_configs/configs/%blueprint_name%/variables/base.rb +2 -0
  127. data/lib/templates/blueprint_configs/configs/%blueprint_name%/variables/development.rb +0 -0
  128. data/lib/templates/blueprint_types/dsl/app/templates/%blueprint_name%.rb +37 -0
  129. data/lib/templates/blueprint_types/dsl/app/user_data/bootstrap.sh +2 -0
  130. data/lib/templates/blueprint_types/erb/app/definitions/base.rb.tt +1 -0
  131. data/lib/templates/blueprint_types/erb/app/templates/%blueprint_name%.yml +8 -0
  132. data/lib/{starter_projects/autoscaling → templates/skeleton}/.gitignore +1 -0
  133. data/lib/templates/skeleton/Gemfile +3 -0
  134. data/lib/{starter_projects/autoscaling → templates/skeleton}/Guardfile +2 -2
  135. data/lib/templates/skeleton/README.md +58 -0
  136. data/lib/templates/skeleton/configs/settings.yml +17 -0
  137. data/lib/templates/upgrade5/blueprints/main/.lono/config.yml +3 -0
  138. data/lib/templates/upgrade5/blueprints/main/.meta/config.yml +3 -0
  139. data/lono.gemspec +12 -8
  140. data/vendor/cfn-status/CHANGELOG.md +10 -0
  141. data/vendor/cfn-status/Gemfile +4 -0
  142. data/vendor/cfn-status/LICENSE.txt +21 -0
  143. data/vendor/cfn-status/README.md +56 -0
  144. data/vendor/cfn-status/Rakefile +6 -0
  145. data/vendor/cfn-status/bin/console +14 -0
  146. data/vendor/cfn-status/bin/setup +8 -0
  147. data/vendor/cfn-status/cfn-status.gemspec +30 -0
  148. data/vendor/cfn-status/lib/cfn-status.rb +1 -0
  149. data/vendor/cfn-status/lib/cfn/aws_service.rb +51 -0
  150. data/vendor/cfn-status/lib/cfn/status.rb +219 -0
  151. data/vendor/cfn-status/lib/cfn/status/version.rb +5 -0
  152. data/vendor/cfn-status/spec/cfn/status_spec.rb +81 -0
  153. data/vendor/cfn-status/spec/fixtures/cfn/stack-events-complete.json +1080 -0
  154. data/vendor/cfn-status/spec/fixtures/cfn/stack-events-in-progress.json +1080 -0
  155. data/vendor/cfn-status/spec/fixtures/cfn/stack-events-update-rollback-complete.json +1086 -0
  156. data/vendor/cfn-status/spec/spec_helper.rb +14 -0
  157. data/vendor/cfn_camelizer/CHANGELOG.md +20 -0
  158. data/vendor/cfn_camelizer/Gemfile +4 -0
  159. data/vendor/cfn_camelizer/LICENSE.txt +21 -0
  160. data/vendor/cfn_camelizer/README.md +40 -0
  161. data/vendor/cfn_camelizer/Rakefile +6 -0
  162. data/vendor/cfn_camelizer/bin/console +14 -0
  163. data/vendor/cfn_camelizer/bin/setup +8 -0
  164. data/vendor/cfn_camelizer/cfn_camelizer.gemspec +32 -0
  165. data/vendor/cfn_camelizer/lib/camelizer.yml +37 -0
  166. data/vendor/cfn_camelizer/lib/cfn_camelizer.rb +94 -0
  167. data/vendor/cfn_camelizer/lib/cfn_camelizer/version.rb +3 -0
  168. data/vendor/cfn_camelizer/spec/cfn_camelizer_spec.rb +86 -0
  169. data/vendor/cfn_camelizer/spec/spec_helper.rb +14 -0
  170. metadata +189 -62
  171. data/.circleci/bin/commit_docs.sh +0 -26
  172. data/.circleci/config.yml +0 -72
  173. data/bin/release +0 -9
  174. data/lib/lono/help/import.md +0 -54
  175. data/lib/lono/importer.rb +0 -134
  176. data/lib/lono/new/message.rb +0 -35
  177. data/lib/starter_projects/autoscaling/Gemfile +0 -3
  178. data/lib/starter_projects/autoscaling/README.md +0 -118
  179. data/lib/starter_projects/autoscaling/app/definitions/base.rb +0 -2
  180. data/lib/starter_projects/autoscaling/app/templates/autoscaling.yml +0 -682
  181. data/lib/starter_projects/autoscaling/config/params/base/autoscaling.txt +0 -6
  182. data/lib/starter_projects/autoscaling/config/settings.yml +0 -33
  183. data/lib/starter_projects/ec2/.gitignore +0 -2
  184. data/lib/starter_projects/ec2/Gemfile +0 -3
  185. data/lib/starter_projects/ec2/Guardfile +0 -12
  186. data/lib/starter_projects/ec2/README.md +0 -86
  187. data/lib/starter_projects/ec2/app/definitions/base.rb +0 -2
  188. data/lib/starter_projects/ec2/app/definitions/development.rb +0 -1
  189. data/lib/starter_projects/ec2/app/definitions/production.rb +0 -1
  190. data/lib/starter_projects/ec2/app/helpers/my_custom_helper.rb +0 -17
  191. data/lib/starter_projects/ec2/app/partials/user_data/bootstrap.sh +0 -4
  192. data/lib/starter_projects/ec2/app/templates/example.yml +0 -430
  193. data/lib/starter_projects/ec2/config/params/base/example.txt +0 -2
  194. data/lib/starter_projects/ec2/config/params/development/example.txt +0 -3
  195. data/lib/starter_projects/ec2/config/params/production/example.txt +0 -2
  196. data/lib/starter_projects/ec2/config/settings.yml +0 -33
  197. data/lib/starter_projects/ec2/config/variables/base.rb +0 -3
  198. data/lib/starter_projects/ec2/config/variables/development.rb +0 -2
  199. data/lib/starter_projects/ec2/config/variables/production.rb +0 -2
  200. data/lib/starter_projects/ec2/welcome.txt +0 -8
  201. data/lib/starter_projects/skeleton/.gitignore +0 -2
  202. data/lib/starter_projects/skeleton/Gemfile +0 -3
  203. data/lib/starter_projects/skeleton/Guardfile +0 -12
  204. data/lib/starter_projects/skeleton/README.md +0 -53
  205. data/lib/starter_projects/skeleton/config/settings.yml +0 -33
  206. data/lib/starter_projects/skeleton/welcome.txt +0 -7
  207. data/vendor/plissken/Gemfile +0 -14
  208. data/vendor/plissken/LICENSE.txt +0 -20
  209. data/vendor/plissken/README.md +0 -46
  210. data/vendor/plissken/Rakefile +0 -56
  211. data/vendor/plissken/VERSION +0 -1
  212. data/vendor/plissken/lib/plissken.rb +0 -1
  213. data/vendor/plissken/lib/plissken/ext/hash/to_snake_keys.rb +0 -45
  214. data/vendor/plissken/plissken.gemspec +0 -61
  215. data/vendor/plissken/spec/lib/to_snake_keys_spec.rb +0 -177
  216. data/vendor/plissken/spec/spec_helper.rb +0 -90
  217. data/vendor/plissken/test/helper.rb +0 -20
  218. data/vendor/plissken/test/plissken/ext/hash/to_snake_keys_test.rb +0 -184
  219. 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
@@ -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 = "#{template_name}.yml"
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
- allow_no_file: true
57
+ allow_not_exists: true
73
58
  }.merge(@options)
74
- generator = Lono::Param::Generator.new(param_name, generator_options)
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 DSL methods are: source and variables
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
- # Taking care to name instance variables with _ in front because we load the
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
@@ -3,150 +3,120 @@ require 'json'
3
3
  require 'base64'
4
4
  require 'digest'
5
5
 
6
- class Lono::Template::Upload
7
- include Lono::Template::AwsService
8
-
9
- def initialize(options={})
10
- @options = options
11
- @checksums = {}
12
- @prefix = "#{folder_key}/#{Lono.env}/templates" # s3://s3-bucket/folder/development/templates
13
- end
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
- def run
16
- ensure_s3_setup!
17
- load_checksums!
21
+ def run
22
+ load_checksums!
18
23
 
19
- say "Uploading CloudFormation templates..."
20
- paths = Dir.glob("#{Lono.config.output_path}/templates/**/*")
21
- paths.select { |p| File.file?(p) }.each do |path|
22
- upload(path)
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
- # Read existing files on s3 to grab their md5 checksum.
28
- # We do this so we can see if we should avoid re-uploading the s3 child template
29
- # entirely. If we upload a new child template that does not change AWS CloudFormation
30
- # is not smart enough to know that it not has changed. I think all AWS CloudFormation
31
- # does is check if the file's timestamp.
32
- #
33
- # Thought this would result in better AWS Change Set info but AWS still reports child
34
- # stacks being changed even though they should not be reported. Leaving this s3 checksum
35
- # in for now.
36
- def load_checksums!
37
- return if @options[:noop]
38
-
39
- resp = s3.list_objects(bucket: s3_bucket, prefix: @prefix)
40
- resp.contents.each do |object|
41
- # key does not include the bucket name
42
- # full path = s3://my-bucket/s3_folder/templates/production/my-template.yml
43
- # key = s3_folder/templates/production/my-template.yml
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
- def upload(path)
57
- pretty_path = path.sub(/^\.\//, '')
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
- resp = s3.put_object(
69
- body: IO.read(path),
70
- bucket: s3_bucket,
71
- key: key,
72
- storage_class: "REDUCED_REDUNDANCY"
73
- ) unless @options[:noop]
74
-
75
- # Example output:
76
- # Uploaded: output/templates/docker.yml to s3://boltops-dev/s3_folder/templates/development/docker.yml
77
- # Uploaded: output/templates/ecs/private.yml to s3://boltops-dev/s3_folder/templates/development/ecs/private.yml
78
- message = "Uploaded: #{pretty_path} to #{s3_full_path}".color(:green)
79
- message = "NOOP: #{message}" if @options[:noop]
80
- say message
81
- end
82
-
83
- # @checksums map has a key format: s3_folder/templates/development/docker.yml
84
- #
85
- # path = ./output/templates/docker.yml
86
- # s3_folder = s3://boltops-dev/s3_folder/templates/development/docker.yml
87
- def remote_checksum(path)
88
- # first convert the local path to the path format that is stored in @checksums keys
89
- # ./output/templates/docker.yml => s3_folder/templates/development/docker.yml
90
- pretty_path = path.sub(/^\.\//, '')
91
- key = "#{@prefix}/#{pretty_path.sub(%r{output/templates/},'')}"
92
- @checksums[key]
93
- end
94
-
95
- # https://s3.amazonaws.com/mybucket/s3_folder/templates/production/parent.yml
96
- def s3_https_url(template_path)
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
- # The folder_key is the s3_folder setting with the s3 bucket.
124
- #
125
- # Example:
126
- # s3_bucket('s3://mybucket/templates/storage/path')
127
- # => templates/storage/path
128
- def folder_key
129
- return nil if @options[:noop] # to get spec passing
130
- return nil unless s3_folder
131
- s3_folder.sub('s3://','').split('/')[1..-1].join('/')
132
- end
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
- def s3_folder
135
- settings = Lono::Setting.new
136
- settings.s3_folder
137
- end
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
- # nice warning if the s3 path not found
140
- def ensure_s3_setup!
141
- return if @options[:noop]
142
- return if s3_folder
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
- say "Unable to upload templates to s3 because you have not configured the s3_folder option in lono settings.yml.".color(:red)
145
- say "Please configure settings.yml with s3_folder. For more help: http://lono.cloud/docs/settings/".color(:red)
146
- exit 1
147
- end
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
- def say(message)
150
- puts message unless @options[:quiet]
118
+ def say(message)
119
+ puts message unless @options[:quiet]
120
+ end
151
121
  end
152
- end
122
+ end