lono 5.2.8 → 5.3.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 +4 -4
- data/CHANGELOG.md +7 -0
- data/README.md +2 -0
- data/lib/lono/cfn.rb +9 -13
- data/lib/lono/cfn/preview.rb +2 -149
- data/lib/lono/cfn/preview/changeset.rb +154 -0
- data/lib/lono/cfn/{diff.rb → preview/codediff.rb} +6 -14
- data/lib/lono/cfn/preview/diff_viewer.rb +19 -0
- data/lib/lono/cfn/preview/param.rb +73 -0
- data/lib/lono/cfn/update.rb +15 -8
- data/lib/lono/inspector.rb +1 -1
- data/lib/lono/inspector/base.rb +30 -36
- data/lib/lono/inspector/graph.rb +100 -99
- data/lib/lono/inspector/summary.rb +48 -59
- data/lib/lono/output_template.rb +35 -0
- data/lib/lono/param/generator.rb +38 -9
- data/lib/lono/seed/base.rb +5 -3
- data/lib/lono/template/context.rb +2 -0
- data/lib/lono/template/context/helpers.rb +14 -0
- data/lib/lono/template/context/ssm_fetcher.rb +23 -0
- data/lib/lono/template/dsl/builder/parameter.rb +4 -4
- data/lib/lono/template/dsl/builder/resource.rb +10 -5
- data/lib/lono/template/dsl/builder/resource/property_mover.rb +19 -0
- data/lib/lono/version.rb +1 -1
- data/lono.gemspec +1 -0
- metadata +24 -4
- data/lib/lono/help/cfn/diff.md +0 -24
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 805088c405e44e3e7b228f5d03a893af2a99c2ce990615bb89b906c0c2bb56ee
|
4
|
+
data.tar.gz: fff83f7bdae3c28fed272a489e3170d09f803d35a05e943b98db33c89e5d7a9e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: bd70ed81d8e4495dff371cd2ec66b519b1002325dac0d17d094a31127ea4e9d186a00001200391f36b9dcece8f85b25f085abeb09c49eedc1f269be457113ad0
|
7
|
+
data.tar.gz: 9bb60f3efa20a1c06a0597656f0729e1723380c2af6b20f673f28f4b08fe2ac941876e3252f405864bd488b989b5d7436ce3dad50b65bb059bf51371751b0290
|
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.3.0]
|
7
|
+
- #8 param preview feature. 3rd type of preview.
|
8
|
+
- #9 ssm helper support in configs
|
9
|
+
- Simplify param lookup with direct lookup logic.
|
10
|
+
- Allow params files to have different extensions. Both.txt and .sh work are auto-inferred conventionally.
|
11
|
+
- Allow condition and depends_on to be a properties level and auto-moved to the attributes level.
|
12
|
+
|
6
13
|
## [5.2.8]
|
7
14
|
- add mfa support for normal IAM user
|
8
15
|
|
data/README.md
CHANGED
@@ -8,6 +8,8 @@
|
|
8
8
|
[](https://circleci.com/gh/tongueroo/lono)
|
9
9
|
[](https://boltops.com?utm_source=badge&utm_medium=badge&utm_campaign=lono)
|
10
10
|
|
11
|
+
[](https://www.boltops.com)
|
12
|
+
|
11
13
|
Lono is a powerful CloudFormation framework. Lono handles the entire CloudFormation lifecycle. It builds, manages and deploys CloudFormation templates.
|
12
14
|
|
13
15
|
* Lono generates CloudFormation templates based on a [DSL](http://lono.cloud/docs/dsl/).
|
data/lib/lono/cfn.rb
CHANGED
@@ -22,8 +22,9 @@ module Lono
|
|
22
22
|
end
|
23
23
|
update_options = Proc.new do
|
24
24
|
option :change_set, type: :boolean, default: true, desc: "Uses generated change set to update the stack. If false, will perform normal update-stack."
|
25
|
-
option :
|
26
|
-
option :
|
25
|
+
option :codediff_preview, type: :boolean, default: true, desc: "Show codediff changes preview."
|
26
|
+
option :changeset_preview, type: :boolean, default: true, desc: "Show ChangeSet changes preview."
|
27
|
+
option :param_preview, type: :boolean, default: true, desc: "Show parameter diff preview."
|
27
28
|
option :sure, type: :boolean, desc: "Skips are you sure prompt"
|
28
29
|
end
|
29
30
|
|
@@ -75,20 +76,15 @@ module Lono
|
|
75
76
|
desc "preview STACK", "Preview a CloudFormation stack update. This is similar to terraform's plan or puppet's dry-run mode."
|
76
77
|
long_desc Lono::Help.text("cfn/preview")
|
77
78
|
option :keep, type: :boolean, desc: "keep the changeset instead of deleting it afterwards"
|
78
|
-
option :
|
79
|
+
option :param_preview, type: :boolean, default: true, desc: "Show parameter diff preview."
|
80
|
+
option :codediff_preview, type: :boolean, default: true, desc: "Show codediff changes preview."
|
81
|
+
option :changeset_preview, type: :boolean, default: true, desc: "Show ChangeSet changes preview."
|
79
82
|
base_options.call
|
80
83
|
suffix_option.call
|
81
84
|
def preview(stack_name=:current)
|
82
|
-
|
83
|
-
Preview.new(stack_name, options).run
|
84
|
-
|
85
|
-
|
86
|
-
desc "diff STACK", "Diff newly generated template vs existing template."
|
87
|
-
long_desc Lono::Help.text("cfn/diff")
|
88
|
-
base_options.call
|
89
|
-
suffix_option.call
|
90
|
-
def diff(stack_name=:current)
|
91
|
-
Diff.new(stack_name, options).run
|
85
|
+
Preview::Param.new(stack_name, options).run if options[:param_preview]
|
86
|
+
Preview::Codediff.new(stack_name, options).run if options[:codediff_preview]
|
87
|
+
Preview::Changeset.new(stack_name, options).run if options[:changeset_preview]
|
92
88
|
end
|
93
89
|
|
94
90
|
desc "download STACK", "Download CloudFormation template from existing stack."
|
data/lib/lono/cfn/preview.rb
CHANGED
@@ -1,151 +1,4 @@
|
|
1
1
|
class Lono::Cfn
|
2
|
-
|
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
|
12
|
-
end
|
13
|
-
|
14
|
-
def preview_change_set(params)
|
15
|
-
success = create_change_set(params)
|
16
|
-
display_change_set if success
|
17
|
-
end
|
18
|
-
|
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
|
41
|
-
end
|
42
|
-
|
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']
|
47
|
-
|
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
|
56
|
-
end
|
57
|
-
|
58
|
-
def display_change_set
|
59
|
-
print "Generating CloudFormation Change Set for preview.."
|
60
|
-
change_set = describe_change_set
|
61
|
-
until change_set_finished?(change_set) do
|
62
|
-
change_set = describe_change_set
|
63
|
-
sleep 1
|
64
|
-
print '.'
|
65
|
-
end
|
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"
|
83
|
-
end
|
84
|
-
end
|
85
|
-
|
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
|
92
|
-
|
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
|
99
|
-
|
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")}"
|
103
|
-
end
|
104
|
-
|
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
|
133
|
-
|
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
|
139
|
-
|
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
|
2
|
+
module Preview
|
150
3
|
end
|
151
|
-
end
|
4
|
+
end
|
@@ -0,0 +1,154 @@
|
|
1
|
+
module Lono::Cfn::Preview
|
2
|
+
class Changeset < Lono::Cfn::Base
|
3
|
+
# Override run from Base superclass, the run method is different enough with Preview
|
4
|
+
def run
|
5
|
+
puts "Changeset Preview:".color(:green)
|
6
|
+
|
7
|
+
if @options[:noop]
|
8
|
+
puts "NOOP CloudFormation preview for #{@stack_name} update"
|
9
|
+
return
|
10
|
+
end
|
11
|
+
|
12
|
+
params = generate_all
|
13
|
+
success = preview_change_set(params)
|
14
|
+
delete_change_set if success && !@options[:keep] # Clean up and delete the change set
|
15
|
+
end
|
16
|
+
|
17
|
+
def preview_change_set(params)
|
18
|
+
success = create_change_set(params)
|
19
|
+
display_change_set if success
|
20
|
+
end
|
21
|
+
|
22
|
+
def create_change_set(params)
|
23
|
+
unless stack_exists?(@stack_name)
|
24
|
+
puts "WARN: Cannot create a change set for the stack because the #{@stack_name} does not exists.".color(:yellow)
|
25
|
+
return false
|
26
|
+
end
|
27
|
+
exit_unless_updatable!(stack_status(@stack_name))
|
28
|
+
|
29
|
+
params = {
|
30
|
+
change_set_name: change_set_name,
|
31
|
+
stack_name: @stack_name,
|
32
|
+
parameters: params,
|
33
|
+
capabilities: capabilities, # ["CAPABILITY_IAM", "CAPABILITY_NAMED_IAM"],
|
34
|
+
}
|
35
|
+
params[:tags] = tags unless tags.empty?
|
36
|
+
set_template_body!(params)
|
37
|
+
show_parameters(params, "cfn.create_change_set")
|
38
|
+
begin
|
39
|
+
cfn.create_change_set(params)
|
40
|
+
rescue Aws::CloudFormation::Errors::ValidationError => e
|
41
|
+
handle_error(e)
|
42
|
+
end
|
43
|
+
true
|
44
|
+
end
|
45
|
+
|
46
|
+
# Example errors:
|
47
|
+
# "Template error: variable names in Fn::Sub syntax must contain only alphanumeric characters, underscores, periods, and colons"
|
48
|
+
def handle_error(e)
|
49
|
+
raise if ENV['FULL_BACKTRACE']
|
50
|
+
|
51
|
+
if e.message =~ /^Parameters: / || e.message =~ /^Template error: /
|
52
|
+
puts "Error creating CloudFormation preview because invalid CloudFormation parameters. Full error message:".color(:red)
|
53
|
+
puts e.message
|
54
|
+
puts "For full backtrace run command again with FULL_BACKTRACE=1"
|
55
|
+
quit(1)
|
56
|
+
else
|
57
|
+
raise
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
def display_change_set
|
62
|
+
print "Generating CloudFormation Change Set for preview.."
|
63
|
+
change_set = describe_change_set
|
64
|
+
until change_set_finished?(change_set) do
|
65
|
+
change_set = describe_change_set
|
66
|
+
sleep 1
|
67
|
+
print '.'
|
68
|
+
end
|
69
|
+
puts
|
70
|
+
|
71
|
+
case change_set.status
|
72
|
+
when "CREATE_COMPLETE"
|
73
|
+
puts "CloudFormation preview for '#{@stack_name}' stack update. Changes:"
|
74
|
+
changes = change_set.changes.sort_by do |change|
|
75
|
+
change["resource_change"]["action"]
|
76
|
+
end
|
77
|
+
changes.each do |change|
|
78
|
+
display_change(change)
|
79
|
+
end
|
80
|
+
when "FAILED"
|
81
|
+
puts "WARN: Fail to create a CloudFormation preview for '#{@stack_name}' stack update. Reason:".color(:yellow)
|
82
|
+
puts change_set.status_reason
|
83
|
+
quit(0)
|
84
|
+
else
|
85
|
+
raise "hell: never come here"
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
def delete_change_set
|
90
|
+
cfn.delete_change_set(
|
91
|
+
change_set_name: change_set_name,
|
92
|
+
stack_name: @stack_name
|
93
|
+
)
|
94
|
+
end
|
95
|
+
|
96
|
+
def execute_change_set
|
97
|
+
cfn.execute_change_set(
|
98
|
+
change_set_name: change_set_name,
|
99
|
+
stack_name: @stack_name
|
100
|
+
)
|
101
|
+
end
|
102
|
+
|
103
|
+
# generates a change set name
|
104
|
+
def change_set_name
|
105
|
+
@change_set_name ||= "changeset-#{Time.now.strftime("%Y%d%m%H%M%S")}"
|
106
|
+
end
|
107
|
+
|
108
|
+
private
|
109
|
+
# Private: formats a Aws::CloudFormation::Types::Change in pretty human readable form
|
110
|
+
#
|
111
|
+
# change - Aws::CloudFormation::Types::Change
|
112
|
+
#
|
113
|
+
# Examples
|
114
|
+
#
|
115
|
+
# display_change(change)
|
116
|
+
# => Remove AWS::Route53::RecordSet: DnsRecord testsubdomain.sub.tongueroo.com
|
117
|
+
#
|
118
|
+
# Returns nil
|
119
|
+
#
|
120
|
+
# change.to_h
|
121
|
+
# {:type=>"Resource",
|
122
|
+
# :resource_change=>
|
123
|
+
# {:action=>"Remove",
|
124
|
+
# :logical_resource_id=>"DnsRecord",
|
125
|
+
# :physical_resource_id=>"testsubdomain.sub.tongueroo.com",
|
126
|
+
# :resource_type=>"AWS::Route53::RecordSet",
|
127
|
+
# :scope=>[],
|
128
|
+
# :details=>[]}}
|
129
|
+
def display_change(change)
|
130
|
+
message = if change.type == "Resource"
|
131
|
+
c = change.resource_change
|
132
|
+
"#{c.action} #{c.resource_type}: #{c.logical_resource_id} #{c.physical_resource_id}"
|
133
|
+
else
|
134
|
+
change.to_h
|
135
|
+
end
|
136
|
+
|
137
|
+
colors = { Remove: :red, Add: :green, Modify: :yellow }
|
138
|
+
action = change.resource_change.action.to_sym
|
139
|
+
message = message.color(colors[action]) if colors.has_key?(action)
|
140
|
+
puts message
|
141
|
+
end
|
142
|
+
|
143
|
+
def change_set_finished?(change_set)
|
144
|
+
change_set.status =~ /_COMPLETE/ || change_set.status == "FAILED"
|
145
|
+
end
|
146
|
+
|
147
|
+
def describe_change_set
|
148
|
+
cfn.describe_change_set(
|
149
|
+
change_set_name: change_set_name,
|
150
|
+
stack_name: @stack_name
|
151
|
+
)
|
152
|
+
end
|
153
|
+
end
|
154
|
+
end
|
@@ -1,8 +1,11 @@
|
|
1
|
-
|
2
|
-
class
|
1
|
+
module Lono::Cfn::Preview
|
2
|
+
class Codediff < Lono::Cfn::Base
|
3
|
+
include DiffViewer
|
3
4
|
include Lono::AwsServices
|
4
5
|
|
5
6
|
def run
|
7
|
+
puts "Code Diff Preview:".color(:green)
|
8
|
+
|
6
9
|
unless stack_exists?(@stack_name)
|
7
10
|
puts "WARN: Cannot create a diff for the stack because the #{@stack_name} does not exists.".color(:yellow)
|
8
11
|
return
|
@@ -14,7 +17,7 @@ class Lono::Cfn
|
|
14
17
|
generate_all # from Base superclass. Generates the output lono teplates
|
15
18
|
puts "Generating CloudFormation source code diff..."
|
16
19
|
download_existing_cfn_template
|
17
|
-
|
20
|
+
show_diff(existing_template_path, new_cfn_template)
|
18
21
|
end
|
19
22
|
end
|
20
23
|
|
@@ -27,22 +30,11 @@ class Lono::Cfn
|
|
27
30
|
IO.write(existing_template_path, resp.template_body)
|
28
31
|
end
|
29
32
|
|
30
|
-
def show_changes
|
31
|
-
command = "#{diff_viewer} #{existing_template_path} #{new_cfn_template}"
|
32
|
-
puts "Running: #{command}"
|
33
|
-
system(command)
|
34
|
-
end
|
35
|
-
|
36
33
|
# for clarity
|
37
34
|
def new_cfn_template
|
38
35
|
@template_path
|
39
36
|
end
|
40
37
|
|
41
|
-
def diff_viewer
|
42
|
-
return ENV['LONO_DIFF'] if ENV['LONO_DIFF']
|
43
|
-
system("type colordiff > /dev/null") ? "colordiff" : "diff"
|
44
|
-
end
|
45
|
-
|
46
38
|
def existing_template_path
|
47
39
|
"/tmp/existing_cfn_template.yml"
|
48
40
|
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module Lono::Cfn::Preview
|
2
|
+
module DiffViewer
|
3
|
+
def show_diff(existing_path, new_path)
|
4
|
+
command = "#{diff_viewer} #{existing_path} #{new_path}"
|
5
|
+
puts "Running: #{command}"
|
6
|
+
out = `#{command}`
|
7
|
+
if out.strip == ''
|
8
|
+
puts "There were no differences."
|
9
|
+
else
|
10
|
+
puts out
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
def diff_viewer
|
15
|
+
return ENV['LONO_DIFF'] if ENV['LONO_DIFF']
|
16
|
+
system("type colordiff > /dev/null") ? "colordiff" : "diff"
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|