lono 5.1.1 → 5.2.0

Sign up to get free protection for your applications and to get access to all the features.
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)