lono 4.2.7 → 5.0.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.
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
@@ -1,40 +1,44 @@
1
1
  require "yaml"
2
2
 
3
- class Lono::Cfn::Create < Lono::Cfn::Base
4
- # save_stack is the interface method
5
- def save_stack(params)
6
- create_stack(params)
7
- end
8
-
9
- # aws cloudformation create-stack --stack-name prod-hi-123456789 --parameters file://output/params/prod-hi-123456789.json --template-body file://output/prod-hi.json
10
- def create_stack(params)
11
- message = "Creating #{@stack_name.color(:green)} stack."
12
- if @options[:noop]
13
- puts "NOOP #{message}"
14
- return
3
+ class Lono::Cfn
4
+ class Create < Base
5
+ # save_stack is the interface method
6
+ def save_stack(params)
7
+ create_stack(params)
15
8
  end
16
9
 
17
- if stack_exists?(@stack_name)
18
- puts "Cannot create #{@stack_name.color(:green)} stack because it already exists.".color(:red)
19
- return
20
- end
10
+ # aws cloudformation create-stack --stack-name prod-hi-123456789 --parameters file://output/params/prod-hi-123456789.json --template-body file://output/prod-hi.json
11
+ def create_stack(params)
12
+ message = "Creating #{@stack_name.color(:green)} stack."
13
+ if @options[:noop]
14
+ puts "NOOP #{message}"
15
+ return
16
+ end
21
17
 
22
- unless File.exist?(@template_path)
23
- puts "Cannot create #{@stack_name.color(:green)} template not found: #{@template_path}."
24
- return
25
- end
18
+ delete_rollback_stack
26
19
 
27
- params = {
28
- stack_name: @stack_name,
29
- parameters: params,
30
- capabilities: capabilities, # ["CAPABILITY_IAM", "CAPABILITY_NAMED_IAM"]
31
- disable_rollback: !@options[:rollback],
32
- tags: tags,
33
- }
34
- set_template_body!(params)
20
+ if stack_exists?(@stack_name)
21
+ puts "Cannot create #{@stack_name.color(:green)} stack because it already exists.".color(:red)
22
+ return
23
+ end
35
24
 
36
- show_parameters(params, "cfn.create_stack")
37
- cfn.create_stack(params)
38
- puts message unless @options[:mute]
25
+ unless File.exist?(@template_path)
26
+ puts "Cannot create #{@stack_name.color(:green)} template not found: #{@template_path}."
27
+ return
28
+ end
29
+
30
+ params = {
31
+ stack_name: @stack_name,
32
+ parameters: params,
33
+ capabilities: capabilities, # ["CAPABILITY_IAM", "CAPABILITY_NAMED_IAM"]
34
+ disable_rollback: !@options[:rollback],
35
+ }
36
+ params[:tags] = tags unless tags.empty?
37
+ set_template_body!(params)
38
+
39
+ show_parameters(params, "cfn.create_stack")
40
+ cfn.create_stack(params) # TODO: COMMENT OUT FOR TESTING
41
+ puts message unless @options[:mute]
42
+ end
39
43
  end
40
- end
44
+ end
@@ -3,7 +3,7 @@ require "yaml"
3
3
  class Lono::Cfn
4
4
  class Current
5
5
  def initialize(options={})
6
- Lono::ProjectChecker.check_lono_project
6
+ Lono::ProjectChecker.check
7
7
  @options = options
8
8
  @file = ".lono/current"
9
9
  @path = "#{Lono.root}/#{@file}"
@@ -1,5 +1,5 @@
1
1
  class Lono::Cfn::Delete
2
- include Lono::Cfn::AwsService
2
+ include Lono::AwsServices
3
3
  include Lono::Cfn::Util
4
4
 
5
5
  def initialize(stack_name, options={})
@@ -30,7 +30,7 @@ class Lono::Cfn::Delete
30
30
  end
31
31
 
32
32
  def status
33
- @status ||= Lono::Cfn::Status.new(@stack_name)
33
+ @status ||= Cfn::Status.new(@stack_name)
34
34
  end
35
35
 
36
36
  def switch_current(stack_name)
@@ -0,0 +1,11 @@
1
+ class Lono::Cfn
2
+ class Deploy < Base
3
+ def save_stack(params)
4
+ if stack_exists?(@stack_name)
5
+ Update.new(@stack_name, @options).update_stack(params)
6
+ else
7
+ Create.new(@stack_name, @options).create_stack(params)
8
+ end
9
+ end
10
+ end
11
+ end
@@ -1,5 +1,5 @@
1
1
  class Lono::Cfn::Diff < Lono::Cfn::Base
2
- include Lono::Cfn::AwsService
2
+ include Lono::AwsServices
3
3
 
4
4
  def run
5
5
  unless stack_exists?(@stack_name)
@@ -27,8 +27,8 @@ class Lono::Cfn::Preview < Lono::Cfn::Base
27
27
  stack_name: @stack_name,
28
28
  parameters: params,
29
29
  capabilities: capabilities, # ["CAPABILITY_IAM", "CAPABILITY_NAMED_IAM"],
30
- tags: tags,
31
30
  }
31
+ params[:tags] = tags unless tags.empty?
32
32
  set_template_body!(params)
33
33
  show_parameters(params, "cfn.create_change_set")
34
34
  begin
@@ -74,9 +74,9 @@ class Lono::Cfn::Preview < Lono::Cfn::Base
74
74
  display_change(change)
75
75
  end
76
76
  when "FAILED"
77
- puts "Fail to create a CloudFormation preview for '#{@stack_name}' stack update. Reason:".color(:red)
77
+ puts "WARN: Fail to create a CloudFormation preview for '#{@stack_name}' stack update. Reason:".color(:yellow)
78
78
  puts change_set.status_reason
79
- quit(1)
79
+ quit(0)
80
80
  else
81
81
  raise "hell: never come here"
82
82
  end
@@ -0,0 +1,26 @@
1
+ class Lono::Cfn
2
+ class Rollback
3
+ extend Memoist
4
+ include Lono::AwsServices
5
+
6
+ def initialize(stack_name)
7
+ @stack_name = stack_name
8
+ end
9
+
10
+ def delete_stack
11
+ stack = find_stack(@stack_name)
12
+ if stack && rollback_complete?(stack)
13
+ puts "Existing stack in ROLLBACK_COMPLETE state. Deleting stack before continuing."
14
+ cfn.delete_stack(stack_name: @stack_name)
15
+ status.wait
16
+ status.reset
17
+ true
18
+ end
19
+ end
20
+
21
+ def status
22
+ Cfn::Status.new(@stack_name)
23
+ end
24
+ memoize :status
25
+ end
26
+ end
@@ -1,213 +1,12 @@
1
1
  class Lono::Cfn
2
- class Status
3
- include AwsService
4
-
5
- attr_reader :events
2
+ class Status < ::Cfn::Status
6
3
  def initialize(stack_name, options={})
4
+ super
7
5
  @stack_name = switch_current(stack_name)
8
- @options = options
9
- reset
10
- end
11
-
12
- # used for the lono cfn status command
13
- def run
14
- unless stack_exists?(@stack_name)
15
- puts "The stack #{@stack_name.color(:green)} does not exist."
16
- return
17
- end
18
-
19
- resp = cfn.describe_stacks(stack_name: @stack_name)
20
- stack = resp.stacks.first
21
-
22
- puts "The current status for the stack #{@stack_name.color(:green)} is #{stack.stack_status.color(:green)}"
23
- if stack.stack_status =~ /_IN_PROGRESS$/
24
- puts "Stack events (tailing):"
25
- # tail all events until done
26
- @hide_time_took = true
27
- wait
28
- else
29
- puts "Stack events:"
30
- # show the last events that was user initiated
31
- refresh_events
32
- show_events(true)
33
- end
34
6
  end
35
7
 
36
8
  def switch_current(stack_name)
37
9
  Lono::Cfn::Current.name!(stack_name)
38
10
  end
39
-
40
- def reset
41
- @events = [] # constantly replaced with recent events
42
- @last_shown_event_id = nil
43
- @stack_deletion_completed = nil
44
- end
45
-
46
- # check for /(_COMPLETE|_FAILED)$/ status
47
- def wait
48
- puts "Waiting for stack to complete"
49
- start_time = Time.now
50
-
51
- refresh_events
52
- until completed || @stack_deletion_completed
53
- show_events
54
- end
55
- show_events(true) # show the final event
56
-
57
- if @stack_deletion_completed
58
- puts "Stack #{@stack_name} deleted."
59
- return
60
- end
61
-
62
- if last_event_status =~ /_FAILED/
63
- puts "Stack failed: #{last_event_status}".color(:red)
64
- puts "Stack reason #{@events[0]["resource_status_reason"]}".color(:red)
65
- elsif last_event_status =~ /_ROLLBACK_/
66
- puts "Stack rolled back: #{last_event_status}".color(:red)
67
- else # success
68
- puts "Stack success status: #{last_event_status}".color(:green)
69
- end
70
-
71
- # Never gets here when deleting a stack because the describe stack returns nothing
72
- # once the stack is deleted. Gets here for stack create and update though.
73
- return if @hide_time_took # set in run
74
- took = Time.now - start_time
75
- puts "Time took for stack deployment: #{pretty_time(took).color(:green)}."
76
- end
77
-
78
- def completed
79
- last_event_status =~ /(_COMPLETE|_FAILED)$/ &&
80
- @events[0]["logical_resource_id"] == @stack_name &&
81
- @events[0]["resource_type"] == "AWS::CloudFormation::Stack"
82
- end
83
-
84
- def last_event_status
85
- @events[0]["resource_status"]
86
- end
87
-
88
- # Only shows new events
89
- def show_events(final=false)
90
- if @last_shown_event_id.nil?
91
- i = find_index(:start)
92
- print_events(i)
93
- else
94
- i = find_index(:last_shown)
95
- # puts "last_shown index #{i}"
96
- print_events(i-1) unless i == 0
97
- end
98
-
99
- return if final
100
- sleep 5 unless ENV['TEST']
101
- refresh_events
102
- end
103
-
104
- def print_events(i)
105
- @events[0..i].reverse.each do |e|
106
- print_event(e)
107
- end
108
- @last_shown_event_id = @events[0]["event_id"]
109
- # puts "@last_shown_event_id #{@last_shown_event_id.inspect}"
110
- end
111
-
112
- def print_event(e)
113
- message = [
114
- event_time(e["timestamp"]),
115
- e["resource_status"],
116
- e["resource_type"],
117
- e["logical_resource_id"],
118
- e["resource_status_reason"]
119
- ].join(" ")
120
- message = message.color(:red) if e["resource_status"] =~ /_FAILED/
121
- puts message
122
- end
123
-
124
- # https://stackoverflow.com/questions/18000432/rails-12-hour-am-pm-range-for-a-day
125
- def event_time(timestamp)
126
- Time.parse(timestamp.to_s).localtime.strftime("%I:%M:%S%p")
127
- end
128
-
129
- # refreshes the loaded events in memory
130
- def refresh_events
131
- resp = cfn.describe_stack_events(stack_name: @stack_name)
132
- @events = resp["stack_events"]
133
- rescue Aws::CloudFormation::Errors::ValidationError => e
134
- if e.message =~ /Stack .* does not exis/
135
- @stack_deletion_completed = true
136
- else
137
- raise
138
- end
139
- end
140
-
141
- def find_index(name)
142
- send("#{name}_index")
143
- end
144
-
145
- def start_index
146
- @events.find_index do |event|
147
- event["resource_type"] == "AWS::CloudFormation::Stack" &&
148
- event["resource_status_reason"] == "User Initiated"
149
- end
150
- end
151
-
152
- def last_shown_index
153
- @events.find_index do |event|
154
- event["event_id"] == @last_shown_event_id
155
- end
156
- end
157
-
158
- def success?
159
- resource_status = @events[0]["resource_status"]
160
- %w[CREATE_COMPLETE UPDATE_COMPLETE].include?(resource_status)
161
- end
162
-
163
- def update_rollback?
164
- @events[0]["resource_status"] == "UPDATE_ROLLBACK_COMPLETE"
165
- end
166
-
167
- def find_update_failed_event
168
- i = @events.find_index do |event|
169
- event["resource_type"] == "AWS::CloudFormation::Stack" &&
170
- event["resource_status_reason"] == "User Initiated"
171
- end
172
-
173
- @events[0..i].reverse.find do |e|
174
- e["resource_status"] == "UPDATE_FAILED"
175
- end
176
- end
177
-
178
- def rollback_error_message
179
- return unless update_rollback?
180
-
181
- event = find_update_failed_event
182
- return unless event
183
-
184
- reason = event["resource_status_reason"]
185
- messages_map.each do |pattern, message|
186
- if reason =~ pattern
187
- return message
188
- end
189
- end
190
-
191
- reason # default message is original reason if not found in messages map
192
- end
193
-
194
- def messages_map
195
- {
196
- /CloudFormation cannot update a stack when a custom-named resource requires replacing/ => "A workaround is to run ufo again with STATIC_NAME=0 and to switch to dynamic names for resources. Then run ufo again with STATIC_NAME=1 to get back to statically name resources. Note, there are caveats with the workaround.",
197
- /cannot be associated with more than one load balancer/ => "There's was an issue updating the stack. Target groups can only be associated with one load balancer at a time. The workaround for this is to use UFO_FORCE_TARGET_GROUP=1 and run the command again. This will force the recreation of the target group resource.",
198
- /SetSubnets is not supported for load balancers of type/ => "Changing subnets for Network Load Balancers is currently not supported. You can try workarouding this with UFO_FORCE_ELB=1 and run the command again. This will force the recreation of the elb resource."
199
- }
200
- end
201
-
202
- # http://stackoverflow.com/questions/4175733/convert-duration-to-hoursminutesseconds-or-similar-in-rails-3-or-ruby
203
- def pretty_time(total_seconds)
204
- minutes = (total_seconds / 60) % 60
205
- seconds = total_seconds % 60
206
- if total_seconds < 60
207
- "#{seconds.to_i}s"
208
- else
209
- "#{minutes.to_i}m #{seconds.to_i}s"
210
- end
211
- end
212
11
  end
213
12
  end
@@ -0,0 +1,67 @@
1
+ class Lono::Cfn
2
+ module Suffix
3
+ # Appends a short suffix at the end of a stack name.
4
+ # Lono internally strips this same suffix for the template name.
5
+ # Makes it convenient for the development flow.
6
+ #
7
+ # lono cfn current --suffix 1
8
+ # lono cfn create demo => demo-1
9
+ # lono cfn update demo-1
10
+ #
11
+ # Instead of typing:
12
+ #
13
+ # lono cfn create demo-1 --template demo
14
+ # lono cfn update demo-1 --template demo
15
+ #
16
+ # The suffix can be specified at the CLI but can also be saved as a
17
+ # preference.
18
+ #
19
+ # A random suffix can be specified with random. Example:
20
+ #
21
+ # lono cfn current --suffix random
22
+ # lono cfn create demo => demo-[RANDOM], example: demo-abc
23
+ # lono cfn update demo-abc
24
+ #
25
+ # It is not a default setting because it might confuse new lono users.
26
+ @@append_suffix = nil
27
+ def append_suffix(stack_name)
28
+ return @@append_suffix if @@append_suffix
29
+ return stack_name unless allow_suffix?
30
+
31
+ suffix ||= stack_name_suffix == 'random' ? random_suffix : stack_name_suffix
32
+ @@append_suffix = [stack_name, suffix].compact.join('-')
33
+ end
34
+
35
+ def remove_suffix(stack_name)
36
+ return stack_name unless allow_suffix?
37
+ return stack_name unless stack_name_suffix
38
+
39
+ if stack_name_suffix == 'random'
40
+ stack_name.sub(/-(\w{3})$/,'') # strip the random suffix at the end
41
+ elsif stack_name_suffix
42
+ pattern = Regexp.new("-#{stack_name_suffix}$",'')
43
+ stack_name.sub(pattern, '') # strip suffix
44
+ else
45
+ stack_name
46
+ end
47
+ end
48
+
49
+ def allow_suffix?
50
+ %w[Lono::Cfn::Create Lono::Cfn::Deploy].include?(self.class.to_s)
51
+ end
52
+
53
+ # only generate random suffix for Create class
54
+ def random_suffix
55
+ return nil unless allow_suffix?
56
+ (0...3).map { (65 + rand(26)).chr }.join.downcase # Ex: jhx
57
+ end
58
+
59
+ def stack_name_suffix
60
+ if @options[:suffix] && !@options[:suffix].nil?
61
+ return @options[:suffix] # CLI option takes highest precedence
62
+ end
63
+
64
+ Lono.suffix # core.rb accounts for LONO_SUFFIX env variable, current, and settings
65
+ end
66
+ end
67
+ end