lono 4.2.7 → 5.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.cody/README.md +6 -0
- data/.cody/acceptance.sh +30 -0
- data/.cody/buildspec.yml +21 -0
- data/.cody/demo.rb +38 -0
- data/.cody/project.rb +12 -0
- data/.cody/role.rb +1 -0
- data/.gitignore +2 -0
- data/.gitmodules +6 -3
- data/.travis.yml +7 -0
- data/CHANGELOG.md +10 -0
- data/Gemfile +0 -1
- data/LICENSE.txt +1 -22
- data/README.md +46 -55
- data/lib/lono.rb +20 -27
- data/lib/lono/app_file.rb +5 -0
- data/lib/lono/app_file/base.rb +19 -0
- data/lib/lono/app_file/build.rb +78 -0
- data/lib/lono/app_file/registry.rb +14 -0
- data/lib/lono/app_file/registry/item.rb +46 -0
- data/lib/lono/app_file/upload.rb +39 -0
- data/lib/lono/autoloader.rb +22 -0
- data/lib/lono/aws_services.rb +46 -0
- data/lib/lono/aws_services/util.rb +49 -0
- data/lib/lono/blueprint.rb +113 -0
- data/lib/lono/blueprint/find.rb +90 -0
- data/lib/lono/blueprint/helper.rb +18 -0
- data/lib/lono/blueprint/info.rb +10 -0
- data/lib/lono/blueprint/list.rb +14 -0
- data/lib/lono/blueprint/root.rb +43 -0
- data/lib/lono/cfn.rb +31 -19
- data/lib/lono/cfn/aws_service.rb +16 -0
- data/lib/lono/cfn/base.rb +244 -261
- data/lib/lono/cfn/create.rb +36 -32
- data/lib/lono/cfn/current.rb +1 -1
- data/lib/lono/cfn/delete.rb +2 -2
- data/lib/lono/cfn/deploy.rb +11 -0
- data/lib/lono/cfn/diff.rb +1 -1
- data/lib/lono/cfn/preview.rb +3 -3
- data/lib/lono/cfn/rollback.rb +26 -0
- data/lib/lono/cfn/status.rb +2 -203
- data/lib/lono/cfn/suffix.rb +67 -0
- data/lib/lono/cfn/update.rb +61 -53
- data/lib/lono/cli.rb +42 -23
- data/lib/lono/completer.rb +0 -2
- data/lib/lono/configure.rb +37 -0
- data/lib/lono/configure/aws_services.rb +18 -0
- data/lib/lono/configure/base.rb +94 -0
- data/lib/lono/configure/helpers.rb +128 -0
- data/lib/lono/conventions.rb +11 -0
- data/lib/lono/core.rb +42 -12
- data/lib/lono/core/config.rb +5 -4
- data/lib/lono/default/settings.yml +0 -11
- data/lib/lono/file_uploader.rb +9 -4
- data/lib/lono/help.rb +1 -2
- data/lib/lono/help/blueprint.md +46 -0
- data/lib/lono/help/cfn.md +5 -4
- data/lib/lono/help/cfn/create.md +14 -9
- data/lib/lono/help/cfn/deploy.md +92 -0
- data/lib/lono/help/cfn/diff.md +0 -1
- data/lib/lono/help/cfn/update.md +16 -15
- data/lib/lono/help/completion.md +3 -3
- data/lib/lono/help/generate.md +0 -1
- data/lib/lono/help/new.md +40 -34
- data/lib/lono/help/param.md +1 -1
- data/lib/lono/help/param/generate.md +1 -1
- data/lib/lono/help/template.md +2 -2
- data/lib/lono/help/xgraph.md +1 -1
- data/lib/lono/inspector.rb +1 -1
- data/lib/lono/inspector/base.rb +26 -10
- data/lib/lono/inspector/graph.rb +7 -3
- data/lib/lono/inspector/summary.rb +15 -3
- data/lib/lono/md5.rb +46 -0
- data/lib/lono/new.rb +40 -28
- data/lib/lono/new/helper.rb +2 -3
- data/lib/lono/param.rb +12 -11
- data/lib/lono/param/generator.rb +96 -42
- data/lib/lono/project_checker.rb +27 -8
- data/lib/lono/s3.rb +23 -0
- data/lib/lono/s3/bucket.rb +123 -0
- data/lib/lono/script.rb +4 -8
- data/lib/lono/script/base.rb +7 -2
- data/lib/lono/script/build.rb +7 -8
- data/lib/lono/script/upload.rb +4 -20
- data/lib/lono/sequence.rb +19 -16
- data/lib/lono/setting.rb +19 -27
- data/lib/lono/template.rb +22 -26
- data/lib/lono/template/base.rb +13 -0
- data/lib/lono/template/context.rb +4 -56
- data/lib/lono/template/context/loader.rb +70 -0
- data/lib/lono/template/dsl.rb +15 -151
- data/lib/lono/template/dsl/builder.rb +60 -0
- data/lib/lono/template/dsl/builder/base.rb +14 -0
- data/lib/lono/template/dsl/builder/condition.rb +26 -0
- data/lib/lono/template/dsl/builder/fn.rb +114 -0
- data/lib/lono/template/dsl/builder/helper.rb +64 -0
- data/lib/lono/template/dsl/builder/mapping.rb +24 -0
- data/lib/lono/template/dsl/builder/output.rb +37 -0
- data/lib/lono/template/dsl/builder/parameter.rb +39 -0
- data/lib/lono/template/dsl/builder/resource.rb +38 -0
- data/lib/lono/template/dsl/builder/section.rb +12 -0
- data/lib/lono/template/dsl/builder/syntax.rb +58 -0
- data/lib/lono/template/erb.rb +82 -0
- data/lib/lono/template/evaluate.rb +39 -0
- data/lib/lono/template/generator.rb +29 -0
- data/lib/lono/template/helper.rb +7 -29
- data/lib/lono/template/post_processor.rb +69 -0
- data/lib/lono/template/template.rb +4 -9
- data/lib/lono/template/upload.rb +103 -133
- data/lib/lono/template/util.rb +48 -0
- data/lib/lono/upgrade.rb +5 -3
- data/lib/lono/upgrade/upgrade5.rb +55 -0
- data/lib/lono/user_data.rb +4 -4
- data/lib/lono/version.rb +1 -1
- data/lib/templates/blueprint/%blueprint_name%.gemspec.tt +44 -0
- data/lib/templates/blueprint/.gitignore +14 -0
- data/lib/templates/blueprint/.lono/config.yml.tt +3 -0
- data/lib/templates/blueprint/.meta/config.yml.tt +3 -0
- data/lib/templates/blueprint/CHANGELOG.md +7 -0
- data/lib/templates/blueprint/Gemfile +4 -0
- data/lib/templates/blueprint/README.md +37 -0
- data/lib/templates/blueprint/Rakefile +6 -0
- data/lib/templates/blueprint/setup/configs.rb +54 -0
- data/lib/templates/blueprint_configs/configs/%blueprint_name%/params/base.txt +2 -0
- data/lib/{starter_projects/skeleton/app/definitions/base.rb → templates/blueprint_configs/configs/%blueprint_name%/params/development.txt} +0 -0
- data/lib/templates/blueprint_configs/configs/%blueprint_name%/variables/base.rb +2 -0
- data/lib/templates/blueprint_configs/configs/%blueprint_name%/variables/development.rb +0 -0
- data/lib/templates/blueprint_types/dsl/app/templates/%blueprint_name%.rb +37 -0
- data/lib/templates/blueprint_types/dsl/app/user_data/bootstrap.sh +2 -0
- data/lib/templates/blueprint_types/erb/app/definitions/base.rb.tt +1 -0
- data/lib/templates/blueprint_types/erb/app/templates/%blueprint_name%.yml +8 -0
- data/lib/{starter_projects/autoscaling → templates/skeleton}/.gitignore +1 -0
- data/lib/templates/skeleton/Gemfile +3 -0
- data/lib/{starter_projects/autoscaling → templates/skeleton}/Guardfile +2 -2
- data/lib/templates/skeleton/README.md +58 -0
- data/lib/templates/skeleton/configs/settings.yml +17 -0
- data/lib/templates/upgrade5/blueprints/main/.lono/config.yml +3 -0
- data/lib/templates/upgrade5/blueprints/main/.meta/config.yml +3 -0
- data/lono.gemspec +12 -8
- data/vendor/cfn-status/CHANGELOG.md +10 -0
- data/vendor/cfn-status/Gemfile +4 -0
- data/vendor/cfn-status/LICENSE.txt +21 -0
- data/vendor/cfn-status/README.md +56 -0
- data/vendor/cfn-status/Rakefile +6 -0
- data/vendor/cfn-status/bin/console +14 -0
- data/vendor/cfn-status/bin/setup +8 -0
- data/vendor/cfn-status/cfn-status.gemspec +30 -0
- data/vendor/cfn-status/lib/cfn-status.rb +1 -0
- data/vendor/cfn-status/lib/cfn/aws_service.rb +51 -0
- data/vendor/cfn-status/lib/cfn/status.rb +219 -0
- data/vendor/cfn-status/lib/cfn/status/version.rb +5 -0
- data/vendor/cfn-status/spec/cfn/status_spec.rb +81 -0
- data/vendor/cfn-status/spec/fixtures/cfn/stack-events-complete.json +1080 -0
- data/vendor/cfn-status/spec/fixtures/cfn/stack-events-in-progress.json +1080 -0
- data/vendor/cfn-status/spec/fixtures/cfn/stack-events-update-rollback-complete.json +1086 -0
- data/vendor/cfn-status/spec/spec_helper.rb +14 -0
- data/vendor/cfn_camelizer/CHANGELOG.md +20 -0
- data/vendor/cfn_camelizer/Gemfile +4 -0
- data/vendor/cfn_camelizer/LICENSE.txt +21 -0
- data/vendor/cfn_camelizer/README.md +40 -0
- data/vendor/cfn_camelizer/Rakefile +6 -0
- data/vendor/cfn_camelizer/bin/console +14 -0
- data/vendor/cfn_camelizer/bin/setup +8 -0
- data/vendor/cfn_camelizer/cfn_camelizer.gemspec +32 -0
- data/vendor/cfn_camelizer/lib/camelizer.yml +37 -0
- data/vendor/cfn_camelizer/lib/cfn_camelizer.rb +94 -0
- data/vendor/cfn_camelizer/lib/cfn_camelizer/version.rb +3 -0
- data/vendor/cfn_camelizer/spec/cfn_camelizer_spec.rb +86 -0
- data/vendor/cfn_camelizer/spec/spec_helper.rb +14 -0
- metadata +189 -62
- data/.circleci/bin/commit_docs.sh +0 -26
- data/.circleci/config.yml +0 -72
- data/bin/release +0 -9
- data/lib/lono/help/import.md +0 -54
- data/lib/lono/importer.rb +0 -134
- data/lib/lono/new/message.rb +0 -35
- data/lib/starter_projects/autoscaling/Gemfile +0 -3
- data/lib/starter_projects/autoscaling/README.md +0 -118
- data/lib/starter_projects/autoscaling/app/definitions/base.rb +0 -2
- data/lib/starter_projects/autoscaling/app/templates/autoscaling.yml +0 -682
- data/lib/starter_projects/autoscaling/config/params/base/autoscaling.txt +0 -6
- data/lib/starter_projects/autoscaling/config/settings.yml +0 -33
- data/lib/starter_projects/ec2/.gitignore +0 -2
- data/lib/starter_projects/ec2/Gemfile +0 -3
- data/lib/starter_projects/ec2/Guardfile +0 -12
- data/lib/starter_projects/ec2/README.md +0 -86
- data/lib/starter_projects/ec2/app/definitions/base.rb +0 -2
- data/lib/starter_projects/ec2/app/definitions/development.rb +0 -1
- data/lib/starter_projects/ec2/app/definitions/production.rb +0 -1
- data/lib/starter_projects/ec2/app/helpers/my_custom_helper.rb +0 -17
- data/lib/starter_projects/ec2/app/partials/user_data/bootstrap.sh +0 -4
- data/lib/starter_projects/ec2/app/templates/example.yml +0 -430
- data/lib/starter_projects/ec2/config/params/base/example.txt +0 -2
- data/lib/starter_projects/ec2/config/params/development/example.txt +0 -3
- data/lib/starter_projects/ec2/config/params/production/example.txt +0 -2
- data/lib/starter_projects/ec2/config/settings.yml +0 -33
- data/lib/starter_projects/ec2/config/variables/base.rb +0 -3
- data/lib/starter_projects/ec2/config/variables/development.rb +0 -2
- data/lib/starter_projects/ec2/config/variables/production.rb +0 -2
- data/lib/starter_projects/ec2/welcome.txt +0 -8
- data/lib/starter_projects/skeleton/.gitignore +0 -2
- data/lib/starter_projects/skeleton/Gemfile +0 -3
- data/lib/starter_projects/skeleton/Guardfile +0 -12
- data/lib/starter_projects/skeleton/README.md +0 -53
- data/lib/starter_projects/skeleton/config/settings.yml +0 -33
- data/lib/starter_projects/skeleton/welcome.txt +0 -7
- data/vendor/plissken/Gemfile +0 -14
- data/vendor/plissken/LICENSE.txt +0 -20
- data/vendor/plissken/README.md +0 -46
- data/vendor/plissken/Rakefile +0 -56
- data/vendor/plissken/VERSION +0 -1
- data/vendor/plissken/lib/plissken.rb +0 -1
- data/vendor/plissken/lib/plissken/ext/hash/to_snake_keys.rb +0 -45
- data/vendor/plissken/plissken.gemspec +0 -61
- data/vendor/plissken/spec/lib/to_snake_keys_spec.rb +0 -177
- data/vendor/plissken/spec/spec_helper.rb +0 -90
- data/vendor/plissken/test/helper.rb +0 -20
- data/vendor/plissken/test/plissken/ext/hash/to_snake_keys_test.rb +0 -184
- data/vendor/plissken/test/test_plissken.rb +0 -2
@@ -0,0 +1,14 @@
|
|
1
|
+
class Lono::Blueprint
|
2
|
+
class List
|
3
|
+
class << self
|
4
|
+
def available
|
5
|
+
puts "Current available blueprints:"
|
6
|
+
Find.all_blueprints.each do |b|
|
7
|
+
full_path = Find.find(b)
|
8
|
+
path = full_path.sub("#{Lono.root}/", "")
|
9
|
+
puts " #{b}: #{path}"
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
require "bundler"
|
2
|
+
|
3
|
+
class Lono::Blueprint
|
4
|
+
module Root
|
5
|
+
# Switch the lono root
|
6
|
+
# TODO: account multimode or only have multimode?
|
7
|
+
# TODO: switch to gem path
|
8
|
+
def set_blueprint_root(blueprint)
|
9
|
+
# puts "blueprint #{blueprint}"
|
10
|
+
# puts caller[0..2]
|
11
|
+
|
12
|
+
blueprint_root = find_blueprint_root(blueprint)
|
13
|
+
if blueprint_root
|
14
|
+
Lono.blueprint_root = blueprint_root
|
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)
|
19
|
+
List.available
|
20
|
+
exit 1
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def find_blueprint_root(blueprint)
|
25
|
+
require_bundle_gems # ensures that gem will be found so we can switch to it
|
26
|
+
|
27
|
+
Find.find(blueprint) # blueprint_root
|
28
|
+
end
|
29
|
+
|
30
|
+
def bundler_groups
|
31
|
+
[:default, Lono.env.to_sym]
|
32
|
+
end
|
33
|
+
|
34
|
+
def require_bundle_gems
|
35
|
+
# NOTE: Dont think ENV['BUNDLE_GEMFILE'] is quite working right. We still need
|
36
|
+
# to be in the project directory. Leaving logic in here for when it gets fix.
|
37
|
+
if ENV['BUNDLE_GEMFILE'] || File.exist?("Gemfile")
|
38
|
+
require "bundler/setup"
|
39
|
+
Bundler.require(*bundler_groups)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
data/lib/lono/cfn.rb
CHANGED
@@ -1,24 +1,13 @@
|
|
1
1
|
require "thor"
|
2
|
+
require "cfn/status"
|
2
3
|
|
3
4
|
class Lono::Cfn < Lono::Command
|
4
|
-
autoload :AwsService, 'lono/cfn/aws_service'
|
5
|
-
autoload :Base, 'lono/cfn/base'
|
6
|
-
autoload :CLI, 'lono/cfn/cli'
|
7
|
-
autoload :Create, 'lono/cfn/create'
|
8
|
-
autoload :Current, 'lono/cfn/current'
|
9
|
-
autoload :Delete, 'lono/cfn/delete'
|
10
|
-
autoload :Diff, 'lono/cfn/diff'
|
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'
|
16
|
-
|
17
5
|
class_option :verbose, type: :boolean
|
18
6
|
class_option :noop, type: :boolean
|
19
7
|
|
20
8
|
base_options = Proc.new do
|
21
9
|
# common to create and update
|
10
|
+
option :blueprint, desc: "override convention and specify the template file to use"
|
22
11
|
option :template, desc: "override convention and specify the template file to use"
|
23
12
|
option :param, desc: "override convention and specify the param file to use"
|
24
13
|
option :lono, type: :boolean, desc: "invoke lono to generate CloudFormation templates", default: true
|
@@ -30,9 +19,19 @@ class Lono::Cfn < Lono::Command
|
|
30
19
|
wait_option = Proc.new do
|
31
20
|
option :wait, type: :boolean, desc: "Wait for stack operation to complete.", default: true
|
32
21
|
end
|
22
|
+
suffix_option = Proc.new do
|
23
|
+
option :suffix, desc: "Suffix for stack name."
|
24
|
+
end
|
25
|
+
update_options = Proc.new do
|
26
|
+
option :change_set, type: :boolean, default: true, desc: "Uses generated change set to update the stack. If false, will perform normal update-stack."
|
27
|
+
option :diff, type: :boolean, default: true, desc: "Show diff of the source code template changes before continuing."
|
28
|
+
option :preview, type: :boolean, default: true, desc: "Show preview of the stack changes before continuing."
|
29
|
+
option :sure, type: :boolean, desc: "Skips are you sure prompt"
|
30
|
+
end
|
33
31
|
|
34
32
|
desc "create STACK", "Create a CloudFormation stack using the generated template."
|
35
33
|
base_options.call
|
34
|
+
suffix_option.call
|
36
35
|
wait_option.call
|
37
36
|
long_desc Lono::Help.text("cfn/create")
|
38
37
|
def create(stack_name)
|
@@ -41,16 +40,23 @@ class Lono::Cfn < Lono::Command
|
|
41
40
|
|
42
41
|
desc "update STACK", "Update a CloudFormation stack using the generated template."
|
43
42
|
long_desc Lono::Help.text("cfn/update")
|
44
|
-
option :change_set, type: :boolean, default: true, desc: "Uses generated change set to update the stack. If false, will perform normal update-stack."
|
45
|
-
option :diff, type: :boolean, default: true, desc: "Show diff of the source code template changes before continuing."
|
46
|
-
option :preview, type: :boolean, default: true, desc: "Show preview of the stack changes before continuing."
|
47
|
-
option :sure, type: :boolean, desc: "Skips are you sure prompt"
|
48
43
|
base_options.call
|
44
|
+
update_options.call
|
49
45
|
wait_option.call
|
50
46
|
def update(stack_name=:current)
|
51
47
|
Update.new(stack_name, options).run
|
52
48
|
end
|
53
49
|
|
50
|
+
desc "deploy STACK", "Create or update a CloudFormation stack using the generated template."
|
51
|
+
long_desc Lono::Help.text("cfn/deploy")
|
52
|
+
base_options.call
|
53
|
+
suffix_option.call
|
54
|
+
update_options.call
|
55
|
+
wait_option.call
|
56
|
+
def deploy(stack_name=:current)
|
57
|
+
Deploy.new(stack_name, options).run
|
58
|
+
end
|
59
|
+
|
54
60
|
desc "delete STACK", "Delete a CloudFormation stack."
|
55
61
|
long_desc Lono::Help.text("cfn/delete")
|
56
62
|
option :sure, type: :boolean, desc: "Skips are you sure prompt"
|
@@ -65,6 +71,7 @@ class Lono::Cfn < Lono::Command
|
|
65
71
|
option :keep, type: :boolean, desc: "keep the changeset instead of deleting it afterwards"
|
66
72
|
option :diff, type: :boolean, default: true, desc: "Show diff of the source code template changes also."
|
67
73
|
base_options.call
|
74
|
+
suffix_option.call
|
68
75
|
def preview(stack_name=:current)
|
69
76
|
Diff.new(stack_name, options).run if options[:diff]
|
70
77
|
Preview.new(stack_name, options).run
|
@@ -73,6 +80,7 @@ class Lono::Cfn < Lono::Command
|
|
73
80
|
desc "diff STACK", "Diff newly generated template vs existing template."
|
74
81
|
long_desc Lono::Help.text("cfn/diff")
|
75
82
|
base_options.call
|
83
|
+
suffix_option.call
|
76
84
|
def diff(stack_name=:current)
|
77
85
|
Diff.new(stack_name, options).run
|
78
86
|
end
|
@@ -81,6 +89,7 @@ class Lono::Cfn < Lono::Command
|
|
81
89
|
long_desc Lono::Help.text("cfn/download")
|
82
90
|
option :name, desc: "Name you want to save the template as. Default: existing stack name."
|
83
91
|
base_options.call
|
92
|
+
suffix_option.call
|
84
93
|
def download(stack_name=:current)
|
85
94
|
Download.new(stack_name, options).run
|
86
95
|
end
|
@@ -89,14 +98,17 @@ class Lono::Cfn < Lono::Command
|
|
89
98
|
long_desc Lono::Help.text("cfn/current")
|
90
99
|
option :rm, type: :boolean, desc: "Remove all current settings. Removes `.lono/current`"
|
91
100
|
option :name, desc: "Current stack name."
|
92
|
-
|
101
|
+
suffix_option.call
|
93
102
|
def current
|
94
103
|
Current.new(options).run
|
95
104
|
end
|
96
105
|
|
97
106
|
desc "status", "Shows the current status for the stack."
|
98
107
|
long_desc Lono::Help.text("cfn/status")
|
108
|
+
suffix_option.call
|
99
109
|
def status(stack_name=:current)
|
100
|
-
Status.new(stack_name, options)
|
110
|
+
status = Lono::Cfn::Status.new(stack_name, options)
|
111
|
+
success = status.run
|
112
|
+
exit 3 unless success
|
101
113
|
end
|
102
114
|
end
|
data/lib/lono/cfn/aws_service.rb
CHANGED
@@ -31,6 +31,22 @@ module Lono::Cfn::AwsService
|
|
31
31
|
exist
|
32
32
|
end
|
33
33
|
|
34
|
+
def find_stack(stack_name)
|
35
|
+
resp = cfn.describe_stacks(stack_name: stack_name)
|
36
|
+
resp.stacks.first
|
37
|
+
rescue Aws::CloudFormation::Errors::ValidationError => e
|
38
|
+
# example: Stack with id demo-web does not exist
|
39
|
+
if e.message =~ /Stack with/ && e.message =~ /does not exist/
|
40
|
+
nil
|
41
|
+
else
|
42
|
+
raise
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def rollback_complete?(stack)
|
47
|
+
stack.stack_status == 'ROLLBACK_COMPLETE'
|
48
|
+
end
|
49
|
+
|
34
50
|
def testing_update?
|
35
51
|
ENV['TEST'] && self.class.name == "LonoCfn::Update"
|
36
52
|
end
|
data/lib/lono/cfn/base.rb
CHANGED
@@ -1,318 +1,301 @@
|
|
1
1
|
require "lono"
|
2
2
|
|
3
|
-
class Lono::Cfn
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
Lono::ProjectChecker.check unless options[:lono] # already ran checker in lono generate
|
12
|
-
|
13
|
-
@template_name = options[:template] || remove_suffix(@stack_name)
|
14
|
-
@param_name = options[:param] || @template_name
|
15
|
-
@template_path = get_source_path(@template_name, :template)
|
16
|
-
@param_path = get_source_path(@param_name, :param)
|
17
|
-
puts "Using template: #{@template_path}" unless @options[:mute_using]
|
18
|
-
puts "Using parameters: #{@param_path}" unless @options[:mute_using]
|
19
|
-
end
|
3
|
+
class Lono::Cfn
|
4
|
+
class Base
|
5
|
+
extend Memoist
|
6
|
+
include Lono::AwsServices
|
7
|
+
include Lono::Blueprint::Root
|
8
|
+
include Lono::Conventions
|
9
|
+
include Suffix
|
10
|
+
include Util
|
20
11
|
|
21
|
-
|
22
|
-
|
23
|
-
end
|
12
|
+
def initialize(stack_name, options={})
|
13
|
+
@options = options # options must be set first because @option used in append_suffix
|
24
14
|
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
puts "#{action} #{@stack_name.color(:green)} stack..."
|
29
|
-
end
|
15
|
+
stack_name = switch_current(stack_name)
|
16
|
+
@stack_name = append_suffix(stack_name)
|
17
|
+
Lono::ProjectChecker.check
|
30
18
|
|
31
|
-
|
32
|
-
|
33
|
-
params = generate_all
|
34
|
-
begin
|
35
|
-
save_stack(params) # defined in the sub class
|
36
|
-
rescue Aws::CloudFormation::Errors::InsufficientCapabilitiesException => e
|
37
|
-
capabilities = e.message.match(/\[(.*)\]/)[1]
|
38
|
-
confirm = prompt_for_iam(capabilities)
|
39
|
-
if confirm =~ /^y/
|
40
|
-
@options.merge!(capabilities: [capabilities])
|
41
|
-
puts "Re-running: #{command_with_iam(capabilities).color(:green)}"
|
42
|
-
retry
|
43
|
-
else
|
44
|
-
puts "Exited"
|
45
|
-
exit 1
|
46
|
-
end
|
47
|
-
end
|
19
|
+
@blueprint = options[:blueprint] || remove_suffix(@stack_name)
|
20
|
+
@template, @param = template_param_convention(options)
|
48
21
|
|
49
|
-
|
50
|
-
|
51
|
-
end
|
22
|
+
# Add template and param to options because used later for Lono::Param::Generator
|
23
|
+
@options[:blueprint], @options[:template], @options[:param] = @blueprint, @template, @param
|
52
24
|
|
53
|
-
|
54
|
-
@status ||= Lono::Cfn::Status.new(@stack_name)
|
55
|
-
end
|
25
|
+
set_blueprint_root(@blueprint)
|
56
26
|
|
57
|
-
|
58
|
-
|
59
|
-
puts " #{command_with_iam(capabilities)}"
|
27
|
+
@template_path = "#{Lono.config.output_path}/#{@blueprint}/templates/#{@template}.yml"
|
28
|
+
end
|
60
29
|
|
61
|
-
|
62
|
-
|
63
|
-
|
30
|
+
def switch_current(stack_name)
|
31
|
+
Current.name!(stack_name)
|
32
|
+
end
|
64
33
|
|
65
|
-
|
66
|
-
|
67
|
-
|
34
|
+
def starting_message
|
35
|
+
action = self.class.to_s.split('::').last
|
36
|
+
puts "#{action} #{@stack_name.color(:green)} stack..."
|
37
|
+
end
|
68
38
|
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
39
|
+
def run
|
40
|
+
starting_message
|
41
|
+
params = generate_all
|
42
|
+
begin
|
43
|
+
save_stack(params) # defined in the sub class
|
44
|
+
rescue Aws::CloudFormation::Errors::InsufficientCapabilitiesException => e
|
45
|
+
capabilities = e.message.match(/\[(.*)\]/)[1]
|
46
|
+
confirm = prompt_for_iam(capabilities)
|
47
|
+
if confirm =~ /^y/
|
48
|
+
@options.merge!(capabilities: [capabilities])
|
49
|
+
puts "Re-running: #{command_with_iam(capabilities).color(:green)}"
|
50
|
+
retry
|
51
|
+
else
|
52
|
+
puts "Exited"
|
53
|
+
exit
|
54
|
+
end
|
55
|
+
rescue Aws::CloudFormation::Errors::ValidationError => e
|
56
|
+
if e.message.include?("No updates") # No updates are to be performed.
|
57
|
+
puts "WARN: #{e.message}".color(:yellow)
|
58
|
+
elsif e.message.include?("UPDATE_ROLLBACK_FAILED") # https://amzn.to/2IiEjc5
|
59
|
+
continue_update_rollback
|
60
|
+
else
|
61
|
+
puts "ERROR: #{e.message}".color(:red)
|
62
|
+
exit 1
|
63
|
+
end
|
77
64
|
end
|
65
|
+
|
66
|
+
return unless @options[:wait]
|
67
|
+
|
68
|
+
success = false
|
69
|
+
if !@options[:noop]
|
70
|
+
success = status.wait
|
71
|
+
end
|
72
|
+
|
73
|
+
# exit code for cfn.rb cli, so there's less duplication
|
74
|
+
exit 1 unless success
|
75
|
+
success
|
78
76
|
end
|
79
|
-
params = generate_params(mute: @options[:mute_params])
|
80
|
-
check_for_errors
|
81
|
-
params
|
82
|
-
end
|
83
77
|
|
84
|
-
|
85
|
-
|
86
|
-
|
78
|
+
def continue_update_rollback_sure?
|
79
|
+
puts <<~EOL
|
80
|
+
The stack is in the UPDATE_ROLLBACK_FAILED state. More info here: https://amzn.to/2IiEjc5
|
81
|
+
Would you like to try to continue the update rollback? (y/N)
|
82
|
+
EOL
|
87
83
|
|
88
|
-
|
89
|
-
|
90
|
-
|
84
|
+
sure = @options[:sure] ? "y" : $stdin.gets
|
85
|
+
unless sure =~ /^y/
|
86
|
+
puts "Exiting without continuing the update rollback."
|
87
|
+
exit 0
|
88
|
+
end
|
89
|
+
end
|
91
90
|
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
91
|
+
def continue_update_rollback
|
92
|
+
continue_update_rollback_sure?
|
93
|
+
params = {stack_name: @stack_name}
|
94
|
+
show_parameters(params, "cfn.continue_update_rollback")
|
95
|
+
begin
|
96
|
+
cfn.continue_update_rollback(params)
|
97
|
+
rescue Aws::CloudFormation::Errors::ValidationError => e
|
98
|
+
puts "ERROR5: #{e.message}".red
|
99
|
+
exit 1
|
100
|
+
end
|
101
|
+
end
|
96
102
|
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
end
|
103
|
+
def delete_rollback_stack
|
104
|
+
rollback = Rollback.new(@stack_name)
|
105
|
+
rollback.delete_stack
|
106
|
+
end
|
102
107
|
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
end
|
108
|
+
def status
|
109
|
+
@status ||= Cfn::Status.new(@stack_name)
|
110
|
+
end
|
107
111
|
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
allow_no_file: true
|
112
|
-
}.merge(options)
|
113
|
-
generator = Lono::Param::Generator.new(@param_name, generator_options)
|
114
|
-
generator.generate # Writes the json file in CamelCase keys format
|
115
|
-
generator.params # Returns Array in underscore keys format
|
116
|
-
end
|
112
|
+
def prompt_for_iam(capabilities)
|
113
|
+
puts "This stack will create IAM resources. Please approve to run the command again with #{capabilities} capabilities."
|
114
|
+
puts " #{command_with_iam(capabilities)}"
|
117
115
|
|
118
|
-
|
119
|
-
|
120
|
-
# {"a"=>"1", "b"=>"2"}
|
121
|
-
# To
|
122
|
-
# [{key: "a", value: "1"}, {key: "b", value: "2"}]
|
123
|
-
#
|
124
|
-
def tags
|
125
|
-
tags = @options[:tags] || []
|
126
|
-
tags = tags.map do |k,v|
|
127
|
-
{ key: k, value: v }
|
116
|
+
puts "Please confirm (y/n)"
|
117
|
+
$stdin.gets
|
128
118
|
end
|
129
119
|
|
130
|
-
|
131
|
-
|
132
|
-
resp = cfn.describe_stacks(stack_name: @stack_name)
|
133
|
-
tags = resp.stacks.first.tags
|
134
|
-
tags = tags.map(&:to_h)
|
120
|
+
def command_with_iam(capabilities)
|
121
|
+
"#{File.basename($0)} #{ARGV.join(' ')} --capabilities #{capabilities}"
|
135
122
|
end
|
136
123
|
|
137
|
-
|
138
|
-
|
124
|
+
# Use class variable to cache this only runs once across all classes. base.rb, diff.rb, preview.rb
|
125
|
+
@@generate_all = nil
|
126
|
+
def generate_all
|
127
|
+
return @@generate_all if @@generate_all
|
128
|
+
|
129
|
+
if @options[:lono]
|
130
|
+
ensure_s3_bucket_exist
|
131
|
+
|
132
|
+
build_scripts
|
133
|
+
generate_templates # generates with some placeholders for build_files IE: file://app/files/my.rb
|
134
|
+
build_files # builds app/files to output/BLUEPRINT/files
|
135
|
+
|
136
|
+
post_process_templates
|
137
|
+
|
138
|
+
unless @options[:noop]
|
139
|
+
upload_files
|
140
|
+
upload_scripts
|
141
|
+
upload_templates
|
142
|
+
end
|
143
|
+
end
|
139
144
|
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
145
|
+
# Pass down all options to generate_params because it eventually uses template
|
146
|
+
param_generator.generate # Writes the json file in CamelCase keys format
|
147
|
+
@@generate_all = param_generator.params # Returns Array in underscore keys format
|
148
|
+
|
149
|
+
# At this point we have the info about params path used so we can display it.
|
150
|
+
# We display other useful info here too so it's together logically.
|
151
|
+
unless @options[:mute_using]
|
152
|
+
puts "Using template: #{pretty_path(@template_path)}"
|
153
|
+
param_generator.puts_param_message(:base)
|
154
|
+
param_generator.puts_param_message(:env)
|
155
|
+
end
|
156
|
+
|
157
|
+
check_for_errors
|
158
|
+
@@generate_all
|
146
159
|
end
|
147
|
-
|
148
|
-
|
149
|
-
|
160
|
+
|
161
|
+
def param_generator
|
162
|
+
generator_options = {
|
163
|
+
regenerate: false,
|
164
|
+
allow_not_exists: true
|
165
|
+
}.merge(@options)
|
166
|
+
Lono::Param::Generator.new(@blueprint, generator_options)
|
150
167
|
end
|
151
|
-
|
168
|
+
memoize :param_generator
|
152
169
|
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
170
|
+
def ensure_s3_bucket_exist
|
171
|
+
bucket = Lono::S3::Bucket.new
|
172
|
+
return if bucket.exist?
|
173
|
+
bucket.create
|
157
174
|
end
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
output_param_path = @param_path.sub(/\.txt/, '.json')
|
162
|
-
output_param_path = "#{Lono.config.output_path}/#{output_param_path}"
|
163
|
-
if @options[:param] && !File.exist?(output_param_path)
|
164
|
-
warns << "Parameters file missing: could not find #{output_param_path}"
|
175
|
+
|
176
|
+
def build_scripts
|
177
|
+
Lono::Script::Build.new(@blueprint, @options).run
|
165
178
|
end
|
166
|
-
[errors, warns]
|
167
|
-
end
|
168
179
|
|
169
|
-
|
170
|
-
|
171
|
-
# else fall back to convention, which also eventually gets checked in check_for_errors
|
172
|
-
#
|
173
|
-
# Type - :param or :template
|
174
|
-
def get_source_path(path, type)
|
175
|
-
if path.nil?
|
176
|
-
convention_path(@stack_name, type) # default convention
|
177
|
-
else
|
178
|
-
# convention path based on the input from the user
|
179
|
-
convention_path(path, type)
|
180
|
+
def build_files
|
181
|
+
Lono::AppFile::Build.new(@blueprint, @options).run
|
180
182
|
end
|
181
|
-
end
|
182
183
|
|
183
|
-
|
184
|
-
|
185
|
-
when :template
|
186
|
-
"#{Lono.config.output_path}/templates/#{name}.yml"
|
187
|
-
when :param
|
188
|
-
"#{Lono.config.params_path}/#{Lono.env}/#{name}.txt"
|
189
|
-
else
|
190
|
-
raise "hell: dont come here"
|
184
|
+
def generate_templates
|
185
|
+
Lono::Template::Generator.new(@blueprint, @options).run
|
191
186
|
end
|
192
|
-
path.sub(/^\.\//, '')
|
193
|
-
end
|
194
187
|
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
return true if testing_update?
|
199
|
-
return false if @options[:noop]
|
188
|
+
def post_process_templates
|
189
|
+
Lono::Template::PostProcessor.new(@blueprint, @options).run
|
190
|
+
end
|
200
191
|
|
201
|
-
|
202
|
-
|
203
|
-
|
192
|
+
def upload_templates
|
193
|
+
Lono::Template::Upload.new(@blueprint).run
|
194
|
+
end
|
204
195
|
|
205
|
-
|
206
|
-
|
207
|
-
|
196
|
+
def upload_scripts
|
197
|
+
Lono::Script::Upload.new(@blueprint).run
|
198
|
+
end
|
208
199
|
|
209
|
-
|
210
|
-
|
211
|
-
quit(1)
|
200
|
+
def upload_files
|
201
|
+
Lono::AppFile::Upload.new(@blueprint).upload
|
212
202
|
end
|
213
|
-
end
|
214
203
|
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
204
|
+
# Maps to CloudFormation format. Example:
|
205
|
+
#
|
206
|
+
# {"a"=>"1", "b"=>"2"}
|
207
|
+
# To
|
208
|
+
# [{key: "a", value: "1"}, {key: "b", value: "2"}]
|
209
|
+
#
|
210
|
+
def tags
|
211
|
+
tags = @options[:tags] || []
|
212
|
+
tags = tags.map do |k,v|
|
213
|
+
{ key: k, value: v }
|
214
|
+
end
|
219
215
|
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
# lono cfn update demo-1
|
227
|
-
#
|
228
|
-
# Instead of typing:
|
229
|
-
#
|
230
|
-
# lono cfn create demo-1 --template demo
|
231
|
-
# lono cfn update demo-1 --template demo
|
232
|
-
#
|
233
|
-
# The suffix can be specified at the CLI but can also be saved as a
|
234
|
-
# preference.
|
235
|
-
#
|
236
|
-
# A random suffix can be specified with random. Example:
|
237
|
-
#
|
238
|
-
# lono cfn current --suffix random
|
239
|
-
# lono cfn create demo => demo-[RANDOM], example: demo-abc
|
240
|
-
# lono cfn update demo-abc
|
241
|
-
#
|
242
|
-
# It is not a default setting because it might confuse new lono users.
|
243
|
-
def append_suffix(stack_name)
|
244
|
-
suffix = Lono.suffix == 'random' ? random_suffix : Lono.suffix
|
245
|
-
[stack_name, suffix].compact.join('-')
|
246
|
-
end
|
216
|
+
update_operation = %w[Preview Update].include?(self.class.to_s)
|
217
|
+
if tags.empty? && update_operation
|
218
|
+
resp = cfn.describe_stacks(stack_name: @stack_name)
|
219
|
+
tags = resp.stacks.first.tags
|
220
|
+
tags = tags.map(&:to_h)
|
221
|
+
end
|
247
222
|
|
248
|
-
|
249
|
-
|
223
|
+
tags
|
224
|
+
end
|
250
225
|
|
251
|
-
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
|
256
|
-
|
257
|
-
|
226
|
+
def check_for_errors
|
227
|
+
errors = check_files
|
228
|
+
unless errors.empty?
|
229
|
+
puts "Please double check the command you ran. There were some errors."
|
230
|
+
puts "ERROR: #{errors.join("\n")}".color(:red)
|
231
|
+
exit
|
232
|
+
end
|
258
233
|
end
|
259
|
-
end
|
260
234
|
|
261
|
-
|
262
|
-
|
263
|
-
|
264
|
-
|
265
|
-
|
235
|
+
def check_files
|
236
|
+
errors = []
|
237
|
+
unless File.exist?(@template_path)
|
238
|
+
errors << "Template file missing: could not find #{@template_path}"
|
239
|
+
end
|
240
|
+
errors
|
241
|
+
end
|
242
|
+
|
243
|
+
# All CloudFormation states listed here:
|
244
|
+
# http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/using-cfn-describing-stacks.html
|
245
|
+
def stack_status(stack_name)
|
246
|
+
return true if testing_update?
|
247
|
+
return false if @options[:noop]
|
266
248
|
|
267
|
-
|
268
|
-
|
269
|
-
return @options[:suffix] # CLI option takes highest precedence
|
249
|
+
resp = cfn.describe_stacks(stack_name: stack_name)
|
250
|
+
resp.stacks[0].stack_status
|
270
251
|
end
|
271
252
|
|
272
|
-
|
273
|
-
|
274
|
-
|
275
|
-
|
253
|
+
def exit_unless_updatable!(status)
|
254
|
+
return true if testing_update?
|
255
|
+
return false if @options[:noop]
|
256
|
+
|
257
|
+
unless status =~ /_COMPLETE$/ || status == "UPDATE_ROLLBACK_FAILED"
|
258
|
+
puts "Cannot create a change set for the stack because the #{@stack_name} is not in an updatable state. Stack status: #{status}".color(:red)
|
259
|
+
quit(1)
|
260
|
+
end
|
261
|
+
end
|
276
262
|
|
277
|
-
|
278
|
-
|
279
|
-
|
280
|
-
["CAPABILITY_IAM", "CAPABILITY_NAMED_IAM"]
|
263
|
+
# To allow mocking in specs
|
264
|
+
def quit(signal)
|
265
|
+
exit signal
|
281
266
|
end
|
282
|
-
end
|
283
267
|
|
284
|
-
|
285
|
-
|
286
|
-
|
287
|
-
|
288
|
-
|
289
|
-
|
290
|
-
end
|
268
|
+
def capabilities
|
269
|
+
return @options[:capabilities] if @options[:capabilities]
|
270
|
+
if @options[:iam]
|
271
|
+
["CAPABILITY_IAM", "CAPABILITY_NAMED_IAM"]
|
272
|
+
end
|
273
|
+
end
|
291
274
|
|
292
|
-
|
293
|
-
|
294
|
-
|
295
|
-
|
275
|
+
def show_parameters(params, meth=nil)
|
276
|
+
params = params.clone.compact
|
277
|
+
params[:template_body] = "Hidden due to size... View at: #{pretty_path(@template_path)}"
|
278
|
+
to = meth || "AWS API"
|
279
|
+
puts "Parameters passed to #{to}:"
|
280
|
+
puts YAML.dump(params.deep_stringify_keys)
|
281
|
+
end
|
296
282
|
|
297
|
-
|
298
|
-
|
299
|
-
|
300
|
-
|
301
|
-
|
302
|
-
|
303
|
-
|
304
|
-
|
305
|
-
|
306
|
-
|
307
|
-
# if s3_folder is set this means s3 upload is enabled
|
308
|
-
if s3_folder # s3_folder defined in cfn/base.rb
|
309
|
-
upload = Lono::Template::Upload.new
|
310
|
-
url = upload.s3_presigned_url(@template_path)
|
283
|
+
# Lono always uploads the template to s3 so we can use much larger templates.
|
284
|
+
#
|
285
|
+
# template_body: 51,200 bytes - filesystem limit
|
286
|
+
# template_url: 460,800 bytes - s3 limit
|
287
|
+
#
|
288
|
+
# Reference: https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/cloudformation-limits.html
|
289
|
+
def set_template_body!(params)
|
290
|
+
upload = Lono::Template::Upload.new(@blueprint)
|
291
|
+
url_path = @template_path.sub("#{Lono.root}/",'')
|
292
|
+
url = upload.s3_presigned_url(url_path)
|
311
293
|
params[:template_url] = url
|
312
|
-
|
313
|
-
params[:template_body] = IO.read(@template_path)
|
294
|
+
params
|
314
295
|
end
|
315
296
|
|
316
|
-
|
297
|
+
def pretty_path(path)
|
298
|
+
path.sub("#{Lono.root}/",'')
|
299
|
+
end
|
317
300
|
end
|
318
|
-
end
|
301
|
+
end
|