lono 5.1.1 → 5.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: a36f1ee3d7076e1e93fa9a395c984978510b9961657de60b026cd4a666b46ab6
4
- data.tar.gz: 9d4104ceab9f1673057374aa86d31800d75ebe89652348a400b6bd481ccac444
3
+ metadata.gz: d79eafbad66de9522347e12c16fa2909ea03994986141858fee5e80e070bb7d5
4
+ data.tar.gz: be34b26768651c90b7a4435839d2850ba03473dae6c7a1bdb8a2eecd4158954f
5
5
  SHA512:
6
- metadata.gz: 40ad69f3970916114081b028085f5a55c65511793571466db2a7fa0229c804491742a5394106838204495432303090ae40b5476232bdcee8fdd7689d5282a180
7
- data.tar.gz: 34e2fd774d94f30b594d7ba602d1d6f0597bedb1127f0821f223f383109c85f38ee332cc05f196ab5834fafb9e01fd2134b9d008c5f7c9e32074c6f69f18b68b
6
+ metadata.gz: ce9534510931f8b2cf8ca93d8cd803b862ba8910f573efe373f2c0fed043a3fe1e11316351b23d664d75e8c90f42942abf4adb904a71bbf72b6e43f8d89b9ed0
7
+ data.tar.gz: e94c2080921f2dc4211fb14d7f35f9c30189fbd0a2310b7b5a8fc925cd0d1f4934dfc669787d0462e27acd15a8ec46e28b355a86b5a269da128f1660ba5e9c46
data/CHANGELOG.md CHANGED
@@ -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
+ ## [5.2.0]
7
+ - #5 lono seed command: Lono::Seed::Configs class interface
8
+ - add lono cfn cancel command
9
+ - content helper
10
+ - gracefully handle edge cases with lono s3 bucket
11
+ - cleanup classes and modules
12
+
6
13
  ## [5.1.1]
7
14
  - use cfn_camelizer as gem
8
15
 
@@ -4,7 +4,7 @@ module Lono::AppFile
4
4
  include Lono::Blueprint::Root
5
5
  extend Memoist
6
6
 
7
- def initialize(blueprint, options = {})
7
+ def initialize(blueprint, options={})
8
8
  @blueprint, @options = blueprint, options
9
9
  @template = @options[:template] || @blueprint
10
10
  Lono::ProjectChecker.check
@@ -39,7 +39,7 @@ module Lono::AwsServices
39
39
  end
40
40
 
41
41
  def rollback_complete?(stack)
42
- stack.stack_status == 'ROLLBACK_COMPLETE'
42
+ stack&.stack_status == 'ROLLBACK_COMPLETE'
43
43
  end
44
44
 
45
45
  def testing_update?
@@ -13,9 +13,11 @@ class Lono::Blueprint
13
13
  if blueprint_root
14
14
  Lono.blueprint_root = blueprint_root
15
15
  else
16
- puts "ERROR: Unable to find the blueprint #{blueprint}. " \
17
- "Are you sure it's in your Gemfile or in the blueprints folder "\
18
- "with the correct blueprint_name in .lono/config.yml?".color(:red)
16
+ puts <<~EOL.color(:red)
17
+ ERROR: Unable to find the blueprint #{blueprint}.
18
+ Are you sure its in your Gemfile or in the blueprints folder
19
+ with the correct blueprint_name in .meta/config.yml?
20
+ EOL
19
21
  List.available
20
22
  exit 1
21
23
  end
data/lib/lono/cfn/base.rb CHANGED
@@ -27,10 +27,6 @@ class Lono::Cfn
27
27
  @template_path = "#{Lono.config.output_path}/#{@blueprint}/templates/#{@template}.yml"
28
28
  end
29
29
 
30
- def switch_current(stack_name)
31
- Current.name!(stack_name)
32
- end
33
-
34
30
  def starting_message
35
31
  action = self.class.to_s.split('::').last
36
32
  puts "#{action} #{@stack_name.color(:green)} stack..."
@@ -170,7 +166,7 @@ class Lono::Cfn
170
166
  def ensure_s3_bucket_exist
171
167
  bucket = Lono::S3::Bucket.new
172
168
  return if bucket.exist?
173
- bucket.create
169
+ bucket.deploy
174
170
  end
175
171
 
176
172
  def build_scripts
@@ -0,0 +1,36 @@
1
+ class Lono::Cfn
2
+ class Cancel
3
+ include Lono::AwsServices
4
+ include Util
5
+
6
+ def initialize(stack_name, options={})
7
+ @stack_name = switch_current(stack_name)
8
+ @options = options
9
+ end
10
+
11
+ def run
12
+ stack = find_stack(@stack_name)
13
+ unless stack
14
+ puts "The '#{@stack_name}' stack does not exist. Unable to cancel"
15
+ exit 1
16
+ end
17
+
18
+ puts "Canceling updates to #{@stack_name}."
19
+ puts "Current stack status: #{stack.stack_status}"
20
+ if stack.stack_status == "CREATE_IN_PROGRESS"
21
+ cfn.delete_stack(stack_name: @stack_name)
22
+ puts "Canceling stack creation."
23
+ elsif stack.stack_status == "UPDATE_IN_PROGRESS"
24
+ cfn.cancel_update_stack(stack_name: @stack_name)
25
+ puts "Canceling stack update."
26
+ status.wait if @options[:wait]
27
+ else
28
+ puts "The stack is not in a state to that is cancelable: #{stack.stack_status}"
29
+ end
30
+ end
31
+
32
+ def status
33
+ @status ||= Status.new(@stack_name)
34
+ end
35
+ end
36
+ end
@@ -1,39 +1,37 @@
1
- class Lono::Cfn::Delete
2
- include Lono::AwsServices
3
- include Lono::Cfn::Util
1
+ class Lono::Cfn
2
+ class Delete
3
+ include Lono::AwsServices
4
+ include Util
4
5
 
5
- def initialize(stack_name, options={})
6
- @stack_name = switch_current(stack_name)
7
- @options = options
8
- end
9
-
10
- def run
11
- message = "Deleted #{@stack_name} stack."
12
- if @options[:noop]
13
- puts "NOOP #{message}"
14
- else
15
- are_you_sure?(@stack_name, :delete)
6
+ def initialize(stack_name, options={})
7
+ @stack_name = switch_current(stack_name)
8
+ @options = options
9
+ end
16
10
 
17
- if stack_exists?(@stack_name)
18
- cfn.delete_stack(stack_name: @stack_name)
19
- puts message
11
+ def run
12
+ message = "Deleted #{@stack_name} stack."
13
+ if @options[:noop]
14
+ puts "NOOP #{message}"
20
15
  else
21
- puts "#{@stack_name.inspect} stack does not exist".color(:red)
22
- end
23
- end
16
+ are_you_sure?(@stack_name, :delete)
24
17
 
25
- return unless @options[:wait]
26
- start_time = Time.now
27
- status.wait unless @options[:noop]
28
- took = Time.now - start_time
29
- puts "Time took for stack deletion: #{status.pretty_time(took).color(:green)}."
30
- end
18
+ if stack_exists?(@stack_name)
19
+ cfn.delete_stack(stack_name: @stack_name)
20
+ puts message
21
+ else
22
+ puts "#{@stack_name.inspect} stack does not exist".color(:red)
23
+ end
24
+ end
31
25
 
32
- def status
33
- @status ||= Cfn::Status.new(@stack_name)
34
- end
26
+ return unless @options[:wait]
27
+ start_time = Time.now
28
+ status.wait unless @options[:noop]
29
+ took = Time.now - start_time
30
+ puts "Time took for stack deletion: #{status.pretty_time(took).color(:green)}."
31
+ end
35
32
 
36
- def switch_current(stack_name)
37
- Lono::Cfn::Current.name!(stack_name)
33
+ def status
34
+ @status ||= Status.new(@stack_name)
35
+ end
38
36
  end
39
- end
37
+ end
data/lib/lono/cfn/diff.rb CHANGED
@@ -1,48 +1,50 @@
1
- class Lono::Cfn::Diff < Lono::Cfn::Base
2
- include Lono::AwsServices
1
+ class Lono::Cfn
2
+ class Diff < Base
3
+ include Lono::AwsServices
3
4
 
4
- def run
5
- unless stack_exists?(@stack_name)
6
- puts "WARN: Cannot create a diff for the stack because the #{@stack_name} does not exists.".color(:yellow)
7
- return
8
- end
5
+ def run
6
+ unless stack_exists?(@stack_name)
7
+ puts "WARN: Cannot create a diff for the stack because the #{@stack_name} does not exists.".color(:yellow)
8
+ return
9
+ end
9
10
 
10
- if @options[:noop]
11
- puts "NOOP Generating CloudFormation source code diff..."
12
- else
13
- generate_all # from Base superclass. Generates the output lono teplates
14
- puts "Generating CloudFormation source code diff..."
15
- download_existing_cfn_template
16
- show_changes
11
+ if @options[:noop]
12
+ puts "NOOP Generating CloudFormation source code diff..."
13
+ else
14
+ generate_all # from Base superclass. Generates the output lono teplates
15
+ puts "Generating CloudFormation source code diff..."
16
+ download_existing_cfn_template
17
+ show_changes
18
+ end
17
19
  end
18
- end
19
20
 
20
- def download_existing_cfn_template
21
- resp = cfn.get_template(
22
- stack_name: @stack_name,
23
- template_stage: "Original"
24
- )
25
- resp.template_body
26
- IO.write(existing_template_path, resp.template_body)
27
- end
21
+ def download_existing_cfn_template
22
+ resp = cfn.get_template(
23
+ stack_name: @stack_name,
24
+ template_stage: "Original"
25
+ )
26
+ resp.template_body
27
+ IO.write(existing_template_path, resp.template_body)
28
+ end
28
29
 
29
- def show_changes
30
- command = "#{diff_viewer} #{existing_template_path} #{new_cfn_template}"
31
- puts "Running: #{command}"
32
- system(command)
33
- end
30
+ def show_changes
31
+ command = "#{diff_viewer} #{existing_template_path} #{new_cfn_template}"
32
+ puts "Running: #{command}"
33
+ system(command)
34
+ end
34
35
 
35
- # for clarity
36
- def new_cfn_template
37
- @template_path
38
- end
36
+ # for clarity
37
+ def new_cfn_template
38
+ @template_path
39
+ end
39
40
 
40
- def diff_viewer
41
- return ENV['LONO_DIFF'] if ENV['LONO_DIFF']
42
- system("type colordiff > /dev/null") ? "colordiff" : "diff"
43
- end
41
+ def diff_viewer
42
+ return ENV['LONO_DIFF'] if ENV['LONO_DIFF']
43
+ system("type colordiff > /dev/null") ? "colordiff" : "diff"
44
+ end
44
45
 
45
- def existing_template_path
46
- "/tmp/existing_cfn_template.yml"
46
+ def existing_template_path
47
+ "/tmp/existing_cfn_template.yml"
48
+ end
47
49
  end
48
50
  end
@@ -1,31 +1,33 @@
1
1
  require 'json'
2
2
 
3
- class Lono::Cfn::Download < Lono::Cfn::Base
4
- def run
5
- puts "Download existing template to: #{download_path}"
6
- return if @options[:noop]
7
- download_template
8
- end
3
+ class Lono::Cfn
4
+ class Download < Base
5
+ def run
6
+ puts "Download existing template to: #{download_path}"
7
+ return if @options[:noop]
8
+ download_template
9
+ end
9
10
 
10
- def download_template
11
- resp = cfn.get_template(
12
- stack_name: @stack_name,
13
- template_stage: "Original"
14
- )
15
- body = convert_to_yaml(resp.template_body)
16
- IO.write(download_path, body)
17
- end
11
+ def download_template
12
+ resp = cfn.get_template(
13
+ stack_name: @stack_name,
14
+ template_stage: "Original"
15
+ )
16
+ body = convert_to_yaml(resp.template_body)
17
+ IO.write(download_path, body)
18
+ end
18
19
 
19
- def convert_to_yaml(body)
20
- json?(body) ? YAML.dump(JSON.parse(body)) : body
21
- end
20
+ def convert_to_yaml(body)
21
+ json?(body) ? YAML.dump(JSON.parse(body)) : body
22
+ end
22
23
 
23
- def json?(body)
24
- !!JSON.parse(body) rescue false
25
- end
24
+ def json?(body)
25
+ !!JSON.parse(body) rescue false
26
+ end
26
27
 
27
- def download_path
28
- name = @options[:name] || @stack_name
29
- "/tmp/#{name}.yml"
28
+ def download_path
29
+ name = @options[:name] || @stack_name
30
+ "/tmp/#{name}.yml"
31
+ end
30
32
  end
31
33
  end
@@ -1,149 +1,151 @@
1
- class Lono::Cfn::Preview < Lono::Cfn::Base
2
- # Override run from Base superclass, the run method is different enough with Preview
3
- def run
4
- if @options[:noop]
5
- puts "NOOP CloudFormation preview for #{@stack_name} update"
6
- else
7
- params = generate_all
8
- success = preview_change_set(params)
9
- delete_change_set if success && !@options[:keep] # Clean up and delete the change set
1
+ class Lono::Cfn
2
+ class Preview < Base
3
+ # Override run from Base superclass, the run method is different enough with Preview
4
+ def run
5
+ if @options[:noop]
6
+ puts "NOOP CloudFormation preview for #{@stack_name} update"
7
+ else
8
+ params = generate_all
9
+ success = preview_change_set(params)
10
+ delete_change_set if success && !@options[:keep] # Clean up and delete the change set
11
+ end
10
12
  end
11
- end
12
-
13
- def preview_change_set(params)
14
- success = create_change_set(params)
15
- display_change_set if success
16
- end
17
13
 
18
- def create_change_set(params)
19
- unless stack_exists?(@stack_name)
20
- puts "WARN: Cannot create a change set for the stack because the #{@stack_name} does not exists.".color(:yellow)
21
- return false
14
+ def preview_change_set(params)
15
+ success = create_change_set(params)
16
+ display_change_set if success
22
17
  end
23
- exit_unless_updatable!(stack_status(@stack_name))
24
18
 
25
- params = {
26
- change_set_name: change_set_name,
27
- stack_name: @stack_name,
28
- parameters: params,
29
- capabilities: capabilities, # ["CAPABILITY_IAM", "CAPABILITY_NAMED_IAM"],
30
- }
31
- params[:tags] = tags unless tags.empty?
32
- set_template_body!(params)
33
- show_parameters(params, "cfn.create_change_set")
34
- begin
35
- cfn.create_change_set(params)
36
- rescue Aws::CloudFormation::Errors::ValidationError => e
37
- handle_error(e)
19
+ def create_change_set(params)
20
+ unless stack_exists?(@stack_name)
21
+ puts "WARN: Cannot create a change set for the stack because the #{@stack_name} does not exists.".color(:yellow)
22
+ return false
23
+ end
24
+ exit_unless_updatable!(stack_status(@stack_name))
25
+
26
+ params = {
27
+ change_set_name: change_set_name,
28
+ stack_name: @stack_name,
29
+ parameters: params,
30
+ capabilities: capabilities, # ["CAPABILITY_IAM", "CAPABILITY_NAMED_IAM"],
31
+ }
32
+ params[:tags] = tags unless tags.empty?
33
+ set_template_body!(params)
34
+ show_parameters(params, "cfn.create_change_set")
35
+ begin
36
+ cfn.create_change_set(params)
37
+ rescue Aws::CloudFormation::Errors::ValidationError => e
38
+ handle_error(e)
39
+ end
40
+ true
38
41
  end
39
- true
40
- end
41
42
 
42
- # Example errors:
43
- # "Template error: variable names in Fn::Sub syntax must contain only alphanumeric characters, underscores, periods, and colons"
44
- def handle_error(e)
45
- raise if ENV['FULL_BACKTRACE']
43
+ # Example errors:
44
+ # "Template error: variable names in Fn::Sub syntax must contain only alphanumeric characters, underscores, periods, and colons"
45
+ def handle_error(e)
46
+ raise if ENV['FULL_BACKTRACE']
46
47
 
47
- if e.message =~ /^Parameters: / || e.message =~ /^Template error: /
48
- puts "Error creating CloudFormation preview because invalid CloudFormation parameters. Full error message:".color(:red)
49
- puts e.message
50
- puts "For full backtrace run command again with FULL_BACKTRACE=1"
51
- quit(1)
52
- else
53
- raise
48
+ if e.message =~ /^Parameters: / || e.message =~ /^Template error: /
49
+ puts "Error creating CloudFormation preview because invalid CloudFormation parameters. Full error message:".color(:red)
50
+ puts e.message
51
+ puts "For full backtrace run command again with FULL_BACKTRACE=1"
52
+ quit(1)
53
+ else
54
+ raise
55
+ end
54
56
  end
55
- end
56
57
 
57
- def display_change_set
58
- print "Generating CloudFormation Change Set for preview.."
59
- change_set = describe_change_set
60
- until change_set_finished?(change_set) do
58
+ def display_change_set
59
+ print "Generating CloudFormation Change Set for preview.."
61
60
  change_set = describe_change_set
62
- sleep 1
63
- print '.'
64
- end
65
- puts
66
-
67
- case change_set.status
68
- when "CREATE_COMPLETE"
69
- puts "CloudFormation preview for '#{@stack_name}' stack update. Changes:"
70
- changes = change_set.changes.sort_by do |change|
71
- change["resource_change"]["action"]
61
+ until change_set_finished?(change_set) do
62
+ change_set = describe_change_set
63
+ sleep 1
64
+ print '.'
72
65
  end
73
- changes.each do |change|
74
- display_change(change)
66
+ puts
67
+
68
+ case change_set.status
69
+ when "CREATE_COMPLETE"
70
+ puts "CloudFormation preview for '#{@stack_name}' stack update. Changes:"
71
+ changes = change_set.changes.sort_by do |change|
72
+ change["resource_change"]["action"]
73
+ end
74
+ changes.each do |change|
75
+ display_change(change)
76
+ end
77
+ when "FAILED"
78
+ puts "WARN: Fail to create a CloudFormation preview for '#{@stack_name}' stack update. Reason:".color(:yellow)
79
+ puts change_set.status_reason
80
+ quit(0)
81
+ else
82
+ raise "hell: never come here"
75
83
  end
76
- when "FAILED"
77
- puts "WARN: Fail to create a CloudFormation preview for '#{@stack_name}' stack update. Reason:".color(:yellow)
78
- puts change_set.status_reason
79
- quit(0)
80
- else
81
- raise "hell: never come here"
82
84
  end
83
- end
84
85
 
85
- def delete_change_set
86
- cfn.delete_change_set(
87
- change_set_name: change_set_name,
88
- stack_name: @stack_name
89
- )
90
- end
91
-
92
- def execute_change_set
93
- cfn.execute_change_set(
94
- change_set_name: change_set_name,
95
- stack_name: @stack_name
96
- )
97
- end
86
+ def delete_change_set
87
+ cfn.delete_change_set(
88
+ change_set_name: change_set_name,
89
+ stack_name: @stack_name
90
+ )
91
+ end
98
92
 
99
- # generates a change set name
100
- def change_set_name
101
- @change_set_name ||= "changeset-#{Time.now.strftime("%Y%d%m%H%M%S")}"
102
- end
93
+ def execute_change_set
94
+ cfn.execute_change_set(
95
+ change_set_name: change_set_name,
96
+ stack_name: @stack_name
97
+ )
98
+ end
103
99
 
104
- private
105
- # Private: formats a Aws::CloudFormation::Types::Change in pretty human readable form
106
- #
107
- # change - Aws::CloudFormation::Types::Change
108
- #
109
- # Examples
110
- #
111
- # display_change(change)
112
- # => Remove AWS::Route53::RecordSet: DnsRecord testsubdomain.sub.tongueroo.com
113
- #
114
- # Returns nil
115
- #
116
- # change.to_h
117
- # {:type=>"Resource",
118
- # :resource_change=>
119
- # {:action=>"Remove",
120
- # :logical_resource_id=>"DnsRecord",
121
- # :physical_resource_id=>"testsubdomain.sub.tongueroo.com",
122
- # :resource_type=>"AWS::Route53::RecordSet",
123
- # :scope=>[],
124
- # :details=>[]}}
125
- def display_change(change)
126
- message = if change.type == "Resource"
127
- c = change.resource_change
128
- "#{c.action} #{c.resource_type}: #{c.logical_resource_id} #{c.physical_resource_id}"
129
- else
130
- change.to_h
100
+ # generates a change set name
101
+ def change_set_name
102
+ @change_set_name ||= "changeset-#{Time.now.strftime("%Y%d%m%H%M%S")}"
131
103
  end
132
104
 
133
- colors = { Remove: :red, Add: :green, Modify: :yellow }
134
- action = change.resource_change.action.to_sym
135
- message = message.color(colors[action]) if colors.has_key?(action)
136
- puts message
137
- end
105
+ private
106
+ # Private: formats a Aws::CloudFormation::Types::Change in pretty human readable form
107
+ #
108
+ # change - Aws::CloudFormation::Types::Change
109
+ #
110
+ # Examples
111
+ #
112
+ # display_change(change)
113
+ # => Remove AWS::Route53::RecordSet: DnsRecord testsubdomain.sub.tongueroo.com
114
+ #
115
+ # Returns nil
116
+ #
117
+ # change.to_h
118
+ # {:type=>"Resource",
119
+ # :resource_change=>
120
+ # {:action=>"Remove",
121
+ # :logical_resource_id=>"DnsRecord",
122
+ # :physical_resource_id=>"testsubdomain.sub.tongueroo.com",
123
+ # :resource_type=>"AWS::Route53::RecordSet",
124
+ # :scope=>[],
125
+ # :details=>[]}}
126
+ def display_change(change)
127
+ message = if change.type == "Resource"
128
+ c = change.resource_change
129
+ "#{c.action} #{c.resource_type}: #{c.logical_resource_id} #{c.physical_resource_id}"
130
+ else
131
+ change.to_h
132
+ end
138
133
 
139
- def change_set_finished?(change_set)
140
- change_set.status =~ /_COMPLETE/ || change_set.status == "FAILED"
141
- end
134
+ colors = { Remove: :red, Add: :green, Modify: :yellow }
135
+ action = change.resource_change.action.to_sym
136
+ message = message.color(colors[action]) if colors.has_key?(action)
137
+ puts message
138
+ end
142
139
 
143
- def describe_change_set
144
- cfn.describe_change_set(
145
- change_set_name: change_set_name,
146
- stack_name: @stack_name
147
- )
140
+ def change_set_finished?(change_set)
141
+ change_set.status =~ /_COMPLETE/ || change_set.status == "FAILED"
142
+ end
143
+
144
+ def describe_change_set
145
+ cfn.describe_change_set(
146
+ change_set_name: change_set_name,
147
+ stack_name: @stack_name
148
+ )
149
+ end
148
150
  end
149
151
  end
@@ -1,5 +1,7 @@
1
1
  class Lono::Cfn
2
2
  class Status < ::Cfn::Status
3
+ include Util
4
+
3
5
  def initialize(stack_name, options={})
4
6
  super
5
7
  @stack_name = switch_current(stack_name)