lono 4.1.0 → 4.2.0

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 (42) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +7 -0
  3. data/README.md +3 -1
  4. data/exe/lono +1 -1
  5. data/lib/lono.rb +17 -15
  6. data/lib/lono/cfn.rb +54 -24
  7. data/lib/lono/cfn/base.rb +95 -17
  8. data/lib/lono/cfn/create.rb +5 -29
  9. data/lib/lono/cfn/current.rb +95 -0
  10. data/lib/lono/cfn/delete.rb +15 -1
  11. data/lib/lono/cfn/preview.rb +5 -3
  12. data/lib/lono/cfn/status.rb +212 -0
  13. data/lib/lono/cfn/update.rb +6 -12
  14. data/lib/lono/cfn/util.rb +2 -2
  15. data/lib/lono/cli.rb +4 -6
  16. data/lib/lono/core.rb +23 -5
  17. data/lib/lono/default/settings.yml +1 -1
  18. data/lib/lono/file_uploader.rb +119 -0
  19. data/lib/lono/help/cfn/current.md +18 -0
  20. data/lib/lono/help/cfn/status.md +19 -0
  21. data/lib/lono/script/build.rb +2 -1
  22. data/lib/lono/script/upload.rb +1 -1
  23. data/lib/lono/template/helper.rb +8 -0
  24. data/lib/lono/template/upload.rb +13 -1
  25. data/lib/lono/upgrade.rb +16 -0
  26. data/lib/lono/{upgrade4.rb → upgrade/upgrade4.rb} +1 -1
  27. data/lib/lono/upgrade/upgrade42.rb +36 -0
  28. data/lib/lono/version.rb +1 -1
  29. data/lib/starter_projects/autoscaling/.gitignore +1 -0
  30. data/lib/starter_projects/autoscaling/README.md +1 -1
  31. data/lib/starter_projects/autoscaling/config/settings.yml +1 -1
  32. data/lib/starter_projects/ec2/.gitignore +1 -0
  33. data/lib/starter_projects/ec2/config/settings.yml +1 -1
  34. data/lib/starter_projects/skeleton/.gitignore +1 -0
  35. data/lib/starter_projects/skeleton/config/settings.yml +1 -1
  36. data/lono.gemspec +1 -0
  37. data/spec/fixtures/cfn/stack-events-complete.json +1080 -0
  38. data/spec/fixtures/cfn/stack-events-in-progress.json +1080 -0
  39. data/spec/fixtures/cfn/stack-events-update-rollback-complete.json +1086 -0
  40. data/spec/fixtures/lono_project/config/settings.yml +1 -1
  41. data/spec/lib/lono/cfn/status_spec.rb +77 -0
  42. metadata +33 -4
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 14ca2afc46780d2abc5bb0ecabaf53a685befb89abe63263fa02d847201582f4
4
- data.tar.gz: b3ccb40f3ecc4902b769651c67ef1a76dfb330c0d547c3da686e2913857b048a
3
+ metadata.gz: 2a5ca91b3f1e36849794c7dd3450bdad734b95105ac76d8b24bbf51886b22890
4
+ data.tar.gz: 05f32b9ee239b75b9fbc99fefee557352acffa35a39e812367f39247892e9e27
5
5
  SHA512:
6
- metadata.gz: 63bcc9ff8a025fba3666fb8bcd73fb1a7ffa5e9382dcdf2d407f4c7ea678fb63302887a3bddc8f527c13846100af26d91361f6a7f9bfc2583d4345635ab698de
7
- data.tar.gz: ac98507f3f1a706602662f47af7055b6b983c6c373d8c78f13706dab323fbf8a33d35b16d87234de9674ca7e2c5464d2dcfe1cbd475f6d1ba19b6539ba81a7a1
6
+ metadata.gz: e71a1fe6b43df90adc2d0fc91d9a506b2e6610ff8d72c9640366baf306720cb969da972af6711ee66b9c362103666dd0f44863918ee74a454694f23062344190
7
+ data.tar.gz: c2109dd8da019dbcba4ec958b49d90951a0aaa83e2b9d1259fcba89f8c4bda9cbb7bb6ad911473cc80c4c266f8a4214fbf81ddc3c816426530c9ff7286723df1
@@ -3,6 +3,13 @@
3
3
  All notable changes to this project will be documented in this file.
4
4
  This project *tries* to adhere to [Semantic Versioning](http://semver.org/), even before v1.0.
5
5
 
6
+ ## [4.2.0]
7
+ - lono current
8
+ - lono cfn status
9
+ - app/files support with file_s3_key helper
10
+ - Display status of stack deployment and wait for completion
11
+ - fix iam retry logic for cfn update
12
+
6
13
  ## [4.1.0]
7
14
  - Merge pull request #36 from tongueroo/cli_markdown
8
15
  - fix current_region helper in variables, add s3_region setting
data/README.md CHANGED
@@ -25,7 +25,9 @@ See [lono.cloud](http://lono.cloud) for full lono documentation.
25
25
 
26
26
  ## Important
27
27
 
28
- If you are on version 3, you can run `lono upgrade4` within your project to upgrade it to version 4. Refer to the [CHANGELOG](CHANGELOG.md).
28
+ If you are on version 3, you can run `lono upgrade v3to4` within your project to upgrade it to version 4. Refer to the [CHANGELOG](CHANGELOG.md).
29
+
30
+ If you are on version 4.0 or 4.1 and need to uppgrade to 4.2. You can run `lono upgrade v4to4_2` within your project to upgrade it to version 4.2. Refer to the [CHANGELOG](CHANGELOG.md).
29
31
 
30
32
  ## Blog Posts
31
33
 
data/exe/lono CHANGED
@@ -3,7 +3,7 @@
3
3
  # Trap ^C
4
4
  Signal.trap("INT") {
5
5
  puts "\nCtrl-C detected. Exiting..."
6
- sleep 1
6
+ sleep 0.1
7
7
  exit
8
8
  }
9
9
 
@@ -5,6 +5,7 @@ require 'json'
5
5
  require 'pp'
6
6
  require 'render_me_pretty'
7
7
  require 'yaml'
8
+ require 'memoist'
8
9
 
9
10
  # vendor because need https://github.com/futurechimp/plissken/pull/6 to be merged
10
11
  $:.unshift(File.expand_path("../../vendor/plissken/lib", __FILE__))
@@ -12,27 +13,28 @@ require "plissken"
12
13
 
13
14
  $:.unshift(File.expand_path('../', __FILE__))
14
15
  module Lono
15
- autoload :VERSION, 'lono/version'
16
- autoload :Env, 'lono/env'
17
- autoload :Help, 'lono/help'
18
- autoload :ProjectChecker, 'lono/project_checker'
19
- autoload :Command, 'lono/command'
20
- autoload :CLI, 'lono/cli'
21
- autoload :New, 'lono/new'
22
- autoload :Sequence, 'lono/sequence'
23
- autoload :Template, 'lono/template'
24
16
  autoload :Cfn, 'lono/cfn'
25
- autoload :Param, 'lono/param'
26
17
  autoload :Clean, 'lono/clean'
27
- autoload :Setting, 'lono/setting'
28
- autoload :Importer, 'lono/importer'
29
- autoload :Inspector, 'lono/inspector'
30
- autoload :Completion, 'lono/completion'
18
+ autoload :CLI, 'lono/cli'
19
+ autoload :Command, 'lono/command'
31
20
  autoload :Completer, 'lono/completer'
21
+ autoload :Completion, 'lono/completion'
32
22
  autoload :Core, 'lono/core'
33
- autoload :Upgrade4, 'lono/upgrade4'
23
+ autoload :Env, 'lono/env'
24
+ autoload :FileUploader, 'lono/file_uploader'
25
+ autoload :Help, 'lono/help'
26
+ autoload :Importer, 'lono/importer'
27
+ autoload :Inspector, 'lono/inspector'
28
+ autoload :New, 'lono/new'
29
+ autoload :Param, 'lono/param'
30
+ autoload :ProjectChecker, 'lono/project_checker'
34
31
  autoload :Script, 'lono/script'
32
+ autoload :Sequence, 'lono/sequence'
33
+ autoload :Setting, 'lono/setting'
34
+ autoload :Template, 'lono/template'
35
+ autoload :Upgrade, 'lono/upgrade'
35
36
  autoload :UserData, 'lono/user_data'
37
+ autoload :VERSION, 'lono/version'
36
38
 
37
39
  extend Core
38
40
  end
@@ -2,32 +2,40 @@ require "thor"
2
2
 
3
3
  class Lono::Cfn < Lono::Command
4
4
  autoload :AwsService, 'lono/cfn/aws_service'
5
- autoload :Util, 'lono/cfn/util'
6
- autoload :CLI, 'lono/cfn/cli'
7
5
  autoload :Base, 'lono/cfn/base'
6
+ autoload :CLI, 'lono/cfn/cli'
8
7
  autoload :Create, 'lono/cfn/create'
9
- autoload :Update, 'lono/cfn/update'
8
+ autoload :Current, 'lono/cfn/current'
10
9
  autoload :Delete, 'lono/cfn/delete'
11
- autoload :Preview, 'lono/cfn/preview'
12
10
  autoload :Diff, 'lono/cfn/diff'
13
11
  autoload :Download, 'lono/cfn/download'
12
+ autoload :Preview, 'lono/cfn/preview'
13
+ autoload :Status, 'lono/cfn/status'
14
+ autoload :Update, 'lono/cfn/update'
15
+ autoload :Util, 'lono/cfn/util'
14
16
 
15
17
  class_option :verbose, type: :boolean
16
18
  class_option :noop, type: :boolean
17
19
 
18
- # common to create and update
19
- class_option :template, desc: "override convention and specify the template file to use"
20
- class_option :param, desc: "override convention and specify the param file to use"
21
- class_option :lono, type: :boolean, desc: "invoke lono to generate CloudFormation templates", default: true
22
- class_option :capabilities, type: :array, desc: "iam capabilities. Ex: CAPABILITY_IAM, CAPABILITY_NAMED_IAM"
23
- class_option :iam, type: :boolean, desc: "Shortcut for common IAM capabilities: CAPABILITY_IAM, CAPABILITY_NAMED_IAM"
24
- class_option :rollback, type: :boolean, desc: "rollback", default: true
20
+ base_options = Proc.new do
21
+ # common to create and update
22
+ option :template, desc: "override convention and specify the template file to use"
23
+ option :param, desc: "override convention and specify the param file to use"
24
+ option :lono, type: :boolean, desc: "invoke lono to generate CloudFormation templates", default: true
25
+ option :capabilities, type: :array, desc: "iam capabilities. Ex: CAPABILITY_IAM, CAPABILITY_NAMED_IAM"
26
+ option :iam, type: :boolean, desc: "Shortcut for common IAM capabilities: CAPABILITY_IAM, CAPABILITY_NAMED_IAM"
27
+ option :rollback, type: :boolean, desc: "rollback", default: true
28
+ end
29
+ wait_option = Proc.new do
30
+ option :wait, type: :boolean, desc: "Wait for stack operation to complete.", default: true
31
+ end
25
32
 
26
33
  desc "create STACK", "Create a CloudFormation stack using the generated template."
27
- option :randomize_stack_name, type: :boolean, desc: "tack on random string at the end of the stack name", default: nil
34
+ base_options.call
35
+ wait_option.call
28
36
  long_desc Lono::Help.text("cfn/create")
29
- def create(name)
30
- Create.new(name, options).run
37
+ def create(stack_name)
38
+ Create.new(stack_name, options).run
31
39
  end
32
40
 
33
41
  desc "update STACK", "Update a CloudFormation stack using the generated template."
@@ -36,36 +44,58 @@ class Lono::Cfn < Lono::Command
36
44
  option :diff, type: :boolean, default: true, desc: "Show diff of the source code template changes before continuing."
37
45
  option :preview, type: :boolean, default: true, desc: "Show preview of the stack changes before continuing."
38
46
  option :sure, type: :boolean, desc: "Skips are you sure prompt"
39
- def update(name)
40
- Update.new(name, options).run
47
+ base_options.call
48
+ wait_option.call
49
+ def update(stack_name=:current)
50
+ Update.new(stack_name, options).run
41
51
  end
42
52
 
43
53
  desc "delete STACK", "Delete a CloudFormation stack."
44
54
  long_desc Lono::Help.text("cfn/delete")
45
55
  option :sure, type: :boolean, desc: "Skips are you sure prompt"
46
- def delete(name)
47
- Delete.new(name, options).run
56
+ base_options.call
57
+ wait_option.call
58
+ def delete(stack_name=:current)
59
+ Delete.new(stack_name, options).run
48
60
  end
49
61
 
50
62
  desc "preview STACK", "Preview a CloudFormation stack update. This is similar to terraform's plan or puppet's dry-run mode."
51
63
  long_desc Lono::Help.text("cfn/preview")
52
64
  option :keep, type: :boolean, desc: "keep the changeset instead of deleting it afterwards"
53
65
  option :diff, type: :boolean, default: true, desc: "Show diff of the source code template changes also."
54
- def preview(name)
55
- Diff.new(name, options).run if options[:diff]
56
- Preview.new(name, options).run
66
+ base_options.call
67
+ def preview(stack_name=:current)
68
+ Diff.new(stack_name, options).run if options[:diff]
69
+ Preview.new(stack_name, options).run
57
70
  end
58
71
 
59
72
  desc "diff STACK", "Diff newly generated template vs existing template."
60
73
  long_desc Lono::Help.text("cfn/diff")
61
- def diff(name)
62
- Diff.new(name, options).run
74
+ base_options.call
75
+ def diff(stack_name=:current)
76
+ Diff.new(stack_name, options).run
63
77
  end
64
78
 
65
79
  desc "download STACK", "Download CloudFormation template from existing stack."
66
80
  long_desc Lono::Help.text("cfn/download")
67
81
  option :name, desc: "Name you want to save the template as. Default: existing stack name."
68
- def download(stack_name)
82
+ base_options.call
83
+ def download(stack_name=:current)
69
84
  Download.new(stack_name, options).run
70
85
  end
86
+
87
+ desc "current", "Current stack that you're working with."
88
+ long_desc Lono::Help.text("cfn/current")
89
+ option :rm, type: :boolean, desc: "Remove all current settings. Removes `.lono/current`"
90
+ option :name, desc: "Current stack name."
91
+ option :suffix, desc: "Current suffix for stack name."
92
+ def current
93
+ Current.new(options).run
94
+ end
95
+
96
+ desc "status", "Shows the current status for the stack."
97
+ long_desc Lono::Help.text("cfn/status")
98
+ def status(stack_name=:current)
99
+ Status.new(stack_name, options).run
100
+ end
71
101
  end
@@ -4,14 +4,13 @@ class Lono::Cfn::Base
4
4
  include Lono::Cfn::AwsService
5
5
  include Lono::Cfn::Util
6
6
 
7
- attr_reader :randomize_stack_name
8
7
  def initialize(stack_name, options={})
9
- @randomize_stack_name = options[:randomize_stack_name]
10
- @stack_name = randomize(stack_name)
11
- @options = options
8
+ @options = options # options must be set first because @option used in append_suffix
9
+ stack_name = switch_current(stack_name)
10
+ @stack_name = append_suffix(stack_name)
12
11
  Lono::ProjectChecker.check unless options[:lono] # already ran checker in lono generate
13
12
 
14
- @template_name = options[:template] || derandomize(@stack_name)
13
+ @template_name = options[:template] || remove_suffix(@stack_name)
15
14
  @param_name = options[:param] || @template_name
16
15
  @template_path = get_source_path(@template_name, :template)
17
16
  @param_path = get_source_path(@param_name, :param)
@@ -19,7 +18,18 @@ class Lono::Cfn::Base
19
18
  puts "Using parameters: #{@param_path}" unless @options[:mute_using]
20
19
  end
21
20
 
21
+ def switch_current(stack_name)
22
+ Lono::Cfn::Current.name!(stack_name)
23
+ end
24
+
25
+ def starting_message
26
+ action = self.class.to_s.split('::').last
27
+ action = action[0..-2] + 'ing' # create => creating
28
+ puts "#{action} #{@stack_name.colorize(:green)} stack..."
29
+ end
30
+
22
31
  def run
32
+ starting_message
23
33
  params = generate_all
24
34
  begin
25
35
  save_stack(params) # defined in the sub class
@@ -35,6 +45,13 @@ class Lono::Cfn::Base
35
45
  exit 1
36
46
  end
37
47
  end
48
+
49
+ return unless @options[:wait]
50
+ status.wait
51
+ end
52
+
53
+ def status
54
+ @status ||= Lono::Cfn::Status.new(@stack_name)
38
55
  end
39
56
 
40
57
  def prompt_for_iam(capabilities)
@@ -55,6 +72,7 @@ class Lono::Cfn::Base
55
72
  generate_templates
56
73
  unless @options[:noop]
57
74
  upload_scripts
75
+ upload_files
58
76
  upload_templates
59
77
  end
60
78
  end
@@ -82,6 +100,11 @@ class Lono::Cfn::Base
82
100
  Lono::Script::Upload.new.run
83
101
  end
84
102
 
103
+ def upload_files
104
+ return unless s3_folder
105
+ Lono::FileUploader.new.upload_all
106
+ end
107
+
85
108
  def generate_params(options={})
86
109
  generator_options = {
87
110
  path: @param_path,
@@ -172,28 +195,61 @@ class Lono::Cfn::Base
172
195
  exit signal
173
196
  end
174
197
 
175
- # Do nothing unless in Create class
176
- def randomize(stack_name)
177
- stack_name
198
+ # Appends a short suffix at the end of a stack name.
199
+ # Lono internally strips this same suffix for the template name.
200
+ # Makes it convenient for the development flow.
201
+ #
202
+ # lono cfn current --suffix 1
203
+ # lono cfn create demo => demo-1
204
+ # lono cfn update demo-1
205
+ #
206
+ # Instead of typing:
207
+ #
208
+ # lono cfn create demo-1 --template demo
209
+ # lono cfn update demo-1 --template demo
210
+ #
211
+ # The suffix can be specified at the CLI but can also be saved as a
212
+ # preference.
213
+ #
214
+ # A random suffix can be specified with random. Example:
215
+ #
216
+ # lono cfn current --suffix random
217
+ # lono cfn create demo => demo-[RANDOM], example: demo-abc
218
+ # lono cfn update demo-abc
219
+ #
220
+ # It is not a default setting because it might confuse new lono users.
221
+ def append_suffix(stack_name)
222
+ suffix = Lono.suffix == 'random' ? random_suffix : Lono.suffix
223
+ [stack_name, suffix].compact.join('-')
178
224
  end
179
225
 
180
- # Strip the random string at end of the template name
181
- def derandomize(template_name)
182
- if randomize_stack_name?
183
- template_name.sub(/-(\w{3})$/,'') # strip the random part at the end
226
+ def remove_suffix(stack_name)
227
+ return stack_name unless Lono.suffix
228
+
229
+ if stack_name_suffix == 'random'
230
+ stack_name.sub(/-(\w{3})$/,'') # strip the random suffix at the end
231
+ elsif stack_name_suffix
232
+ pattern = Regexp.new("-#{stack_name_suffix}$",'')
233
+ stack_name.sub(pattern, '') # strip suffix
184
234
  else
185
- template_name
235
+ stack_name
186
236
  end
187
237
  end
188
238
 
189
- def randomize_stack_name?
190
- if !randomize_stack_name.nil?
191
- return randomize_stack_name # CLI option takes highest precedence
239
+ # only generate random suffix for Lono::Cfn::Create class
240
+ def random_suffix
241
+ return nil unless self.class.name.to_s =~ /Create/
242
+ (0...3).map { (65 + rand(26)).chr }.join.downcase # Ex: jhx
243
+ end
244
+
245
+ def stack_name_suffix
246
+ if @options[:suffix] && !@options[:suffix].nil?
247
+ return @options[:suffix] # CLI option takes highest precedence
192
248
  end
193
249
 
194
250
  # otherwise use the settings preference
195
251
  settings = Lono::Setting.new
196
- settings.data['randomize_stack_name']
252
+ settings.data['stack_name_suffix']
197
253
  end
198
254
 
199
255
  def capabilities
@@ -215,4 +271,26 @@ class Lono::Cfn::Base
215
271
  setting = Lono::Setting.new
216
272
  setting.s3_folder
217
273
  end
274
+
275
+ # Either set the templmate_body or template_url attribute based on
276
+ # if template was uploaded to s3.
277
+ # Nice to reference s3 url because the max size of the template body is
278
+ # greater if the template body is on s3. Limits:
279
+ #
280
+ # template_body: 51,200 bytes
281
+ # template_url: 460,800 bytes
282
+ #
283
+ # Reference: https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/cloudformation-limits.html
284
+ def set_template_body!(params)
285
+ # if s3_folder is set this means s3 upload is enabled
286
+ if s3_folder # s3_folder defined in cfn/base.rb
287
+ upload = Lono::Template::Upload.new
288
+ url = upload.s3_presigned_url(@template_path)
289
+ params[:template_url] = url
290
+ else
291
+ params[:template_body] = IO.read(@template_path)
292
+ end
293
+
294
+ params
295
+ end
218
296
  end
@@ -8,56 +8,32 @@ class Lono::Cfn::Create < Lono::Cfn::Base
8
8
 
9
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
10
  def create_stack(params)
11
- message = "Creating #{@stack_name} stack."
11
+ message = "Creating #{@stack_name.colorize(:green)} stack."
12
12
  if @options[:noop]
13
13
  puts "NOOP #{message}"
14
14
  return
15
15
  end
16
16
 
17
17
  if stack_exists?(@stack_name)
18
- puts "Cannot create '#{@stack_name}' stack because it already exists.".colorize(:red)
18
+ puts "Cannot create #{@stack_name.colorize(:green)} stack because it already exists.".colorize(:red)
19
19
  return
20
20
  end
21
21
 
22
22
  unless File.exist?(@template_path)
23
- puts "Cannot create '#{@stack_name}' template not found: #{@template_path}."
23
+ puts "Cannot create #{@stack_name.colorize(:green)} template not found: #{@template_path}."
24
24
  return
25
25
  end
26
26
 
27
- template_body = IO.read(@template_path)
28
27
  params = {
29
28
  stack_name: @stack_name,
30
- template_body: template_body,
31
29
  parameters: params,
32
30
  capabilities: capabilities, # ["CAPABILITY_IAM", "CAPABILITY_NAMED_IAM"]
33
31
  disable_rollback: !@options[:rollback],
34
32
  }
33
+ set_template_body!(params)
34
+
35
35
  show_parameters(params, "cfn.create_stack")
36
36
  cfn.create_stack(params)
37
37
  puts message unless @options[:mute]
38
38
  end
39
-
40
- # Appends a short random string at the end of a stack name.
41
- # Later we will strip this same random string from the template name.
42
- # Very makes it convenient. We can just type:
43
- #
44
- # lono cfn create main --randomize-stack-name
45
- #
46
- # instead of:
47
- #
48
- # lono cfn create main-[RANDOM] --template main
49
- #
50
- # The randomize_stack_name can be specified at the CLI but can also be saved as a
51
- # preference.
52
- #
53
- # It is not a default setting because it might confuse new lono users.
54
- def randomize(stack_name)
55
- if randomize_stack_name?
56
- random = (0...3).map { (65 + rand(26)).chr }.join.downcase # Ex: jhx
57
- [stack_name, random].join('-')
58
- else
59
- stack_name
60
- end
61
- end
62
-
63
39
  end