lono 3.1.3 → 3.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 +4 -4
- data/CHANGELOG.md +4 -0
- data/lib/lono.rb +1 -0
- data/lib/lono/cli.rb +5 -0
- data/lib/lono/help.rb +10 -0
- data/lib/lono/importer.rb +8 -4
- data/lib/lono/inspector.rb +26 -0
- data/lib/lono/inspector/base.rb +33 -0
- data/lib/lono/inspector/depends.rb +120 -0
- data/lib/lono/inspector/help.rb +21 -0
- data/lib/lono/inspector/params.rb +28 -0
- data/lib/lono/version.rb +1 -1
- data/lib/starter_projects/json_project/.gitignore +1 -0
- data/lib/starter_projects/yaml_project/.gitignore +1 -0
- data/lono.gemspec +1 -0
- data/spec/fixtures/my_project/config/templates/base/stacks.rb +0 -2
- data/spec/lib/lono/inspect_spec.rb +20 -0
- metadata +24 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 6960654946363019c9b4f49f0dbd174939c09949
|
4
|
+
data.tar.gz: 170581eadc5099100aba6146a6ed51d14c89e01a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 9b06de16d5ce5912eedc70f5c821f578a4a01f1a794d0ffe8369a2c8b3d0df7840962ca635b5b3f3878996cd7f15945e183a861579a71a8b05f57a511c31dc8f
|
7
|
+
data.tar.gz: 675ec16efffaf96b22dd69034ba7a636314a45f22d530a818c11f0ca32cbfe1c91c9d5c70346a350d8cfa1c5fa048e967fd1c8d2fcce6e40ee49da35cc5d9adf
|
data/CHANGELOG.md
CHANGED
@@ -3,6 +3,10 @@
|
|
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
|
+
## [3.2.0]
|
7
|
+
- lono inspect depends
|
8
|
+
- lono inspect params
|
9
|
+
|
6
10
|
## [3.1.3]
|
7
11
|
- fix randomize stack name option
|
8
12
|
|
data/lib/lono.rb
CHANGED
data/lib/lono/cli.rb
CHANGED
@@ -19,6 +19,7 @@ module Lono
|
|
19
19
|
option :format, type: :string, default: "yaml", desc: "format for the final template"
|
20
20
|
option :project_root, default: ".", aliases: "-r", desc: "project root"
|
21
21
|
option :casing, default: "underscore", desc: "camelcase or underscore the template name"
|
22
|
+
option :name, default: nil, desc: "final name of downloaded template without extension"
|
22
23
|
def import(source)
|
23
24
|
Importer.new(source, options).run
|
24
25
|
end
|
@@ -56,5 +57,9 @@ module Lono
|
|
56
57
|
desc "param ACTION", "param subcommand tasks"
|
57
58
|
long_desc Help.param
|
58
59
|
subcommand "param", Lono::Param
|
60
|
+
|
61
|
+
desc "inspect ACTION", "inspect subcommand tasks"
|
62
|
+
long_desc Help.inspector
|
63
|
+
subcommand "inspect", Inspector
|
59
64
|
end
|
60
65
|
end
|
data/lib/lono/help.rb
CHANGED
data/lib/lono/importer.rb
CHANGED
@@ -12,10 +12,12 @@ class Lono::Importer
|
|
12
12
|
end
|
13
13
|
|
14
14
|
def run
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
15
|
+
unless options[:noop]
|
16
|
+
download_template
|
17
|
+
template_definition_path = add_template_definition
|
18
|
+
puts "Imported raw CloudFormation template and lono-fied it!"
|
19
|
+
puts "Template definition added to #{template_definition_path}."
|
20
|
+
end
|
19
21
|
puts "Template downloaded to #{dest_path}."
|
20
22
|
end
|
21
23
|
|
@@ -51,6 +53,8 @@ class Lono::Importer
|
|
51
53
|
end
|
52
54
|
|
53
55
|
def template_name
|
56
|
+
return @options[:name] if @options[:name]
|
57
|
+
# else infer name from the original source
|
54
58
|
name = File.basename(@source, ".*")
|
55
59
|
@options[:casing] == "camelcase" ? name.camelize : name.underscore.dasherize
|
56
60
|
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
require "thor"
|
2
|
+
|
3
|
+
class Lono::Inspector < Lono::Command
|
4
|
+
autoload :Help, 'lono/inspector/help'
|
5
|
+
autoload :Base, 'lono/inspector/base'
|
6
|
+
autoload :Params, 'lono/inspector/params'
|
7
|
+
autoload :Depends, 'lono/inspector/depends'
|
8
|
+
|
9
|
+
class_option :verbose, type: :boolean
|
10
|
+
class_option :noop, type: :boolean
|
11
|
+
class_option :project_root, desc: "Project folder. Defaults to current directory", default: "."
|
12
|
+
|
13
|
+
desc "params STACK", "Prints report of CloudFormation template parameters"
|
14
|
+
option :type, type: :string, desc: "type can be: all, required, optional", default: "all"
|
15
|
+
long_desc Help.params
|
16
|
+
def params(name)
|
17
|
+
Params.new(name, options).run
|
18
|
+
end
|
19
|
+
|
20
|
+
desc "depends STACK", "Prints dependencies tree of CloudFormation template resources"
|
21
|
+
long_desc Help.depends
|
22
|
+
option :display, type: :string, desc: "graph or text", default: "graph"
|
23
|
+
def depends(name)
|
24
|
+
Depends.new(name, options).run
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
class Lono::Inspector::Base
|
2
|
+
def initialize(stack_name, options)
|
3
|
+
@stack_name = stack_name
|
4
|
+
@options = options
|
5
|
+
@project_root = options[:project_root] || '.'
|
6
|
+
end
|
7
|
+
|
8
|
+
def generate_templates
|
9
|
+
Lono::Template::DSL.new(@options.clone).run
|
10
|
+
end
|
11
|
+
|
12
|
+
def run
|
13
|
+
generate_templates
|
14
|
+
perform
|
15
|
+
end
|
16
|
+
|
17
|
+
def data
|
18
|
+
return @data if @data
|
19
|
+
template_path = "#{@project_root}/output/#{@stack_name}.yml"
|
20
|
+
check_template_exists(template_path)
|
21
|
+
@data = YAML.load(IO.read(template_path))
|
22
|
+
end
|
23
|
+
|
24
|
+
# Check if the template exists and print friendly error message. Exits if it
|
25
|
+
# does not exist.
|
26
|
+
def check_template_exists(template_path)
|
27
|
+
unless File.exist?(template_path)
|
28
|
+
puts "The template #{template_path} does not exist. Are you sure you use the right template name? The template name does not require the extension.".colorize(:red)
|
29
|
+
exit 1
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
end
|
@@ -0,0 +1,120 @@
|
|
1
|
+
require "yaml"
|
2
|
+
require "graph"
|
3
|
+
|
4
|
+
class Lono::Inspector::Depends < Lono::Inspector::Base
|
5
|
+
def initialize(stack_name, options)
|
6
|
+
super
|
7
|
+
@nodes = [] # lookup map
|
8
|
+
end
|
9
|
+
|
10
|
+
def perform
|
11
|
+
puts "Generating dependencies tree..."
|
12
|
+
return if @options[:noop]
|
13
|
+
|
14
|
+
# First loop through top level nodes and build set depends_on property
|
15
|
+
node_list = [] # top level node list
|
16
|
+
resources = data["Resources"]
|
17
|
+
resources.each do |logical_id, resource|
|
18
|
+
node = Node.new(logical_id)
|
19
|
+
node.depends_on = normalize_depends_on(resource)
|
20
|
+
node.resource_type = normalize_resource_type(resource)
|
21
|
+
node_list << node
|
22
|
+
end
|
23
|
+
|
24
|
+
# Now that we have loop through all the top level resources once
|
25
|
+
# we can use the depends_on attribute on each node and set the
|
26
|
+
# children property since the identity nodes are in memory.
|
27
|
+
node_list.each do |node|
|
28
|
+
node.children = normalize_children(node_list, node)
|
29
|
+
end
|
30
|
+
|
31
|
+
# At this point we have a tree of nodes.
|
32
|
+
if @options[:display] == "text"
|
33
|
+
puts "CloudFormation Dependencies:"
|
34
|
+
node_list.each { |node| print_tree(node) }
|
35
|
+
else
|
36
|
+
print_graph(node_list)
|
37
|
+
puts "CloudFormation Dependencies graph generated."
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
# normalized DependsOn attribute to an Array of Strings
|
42
|
+
def normalize_depends_on(resource)
|
43
|
+
dependencies = resource["DependsOn"] || []
|
44
|
+
[dependencies].flatten
|
45
|
+
end
|
46
|
+
|
47
|
+
def normalize_resource_type(resource)
|
48
|
+
type = resource["Type"]
|
49
|
+
type.sub("AWS::", "") # strip out AWS to make less verbose
|
50
|
+
end
|
51
|
+
|
52
|
+
# It is possible with bad CloudFormation templates that the dependency is not
|
53
|
+
# resolved, but we wont deal with that. Users can validate their CloudFormation
|
54
|
+
# template before using this tool.
|
55
|
+
def normalize_children(node_list, node)
|
56
|
+
kids = []
|
57
|
+
node.depends_on.each do |dependent_logical_id|
|
58
|
+
node = node_list.find { |n| n.name == dependent_logical_id }
|
59
|
+
kids << node
|
60
|
+
end
|
61
|
+
kids
|
62
|
+
end
|
63
|
+
|
64
|
+
def print_tree(node, depth=0)
|
65
|
+
spacing = " " * depth
|
66
|
+
puts "#{spacing}#{node.name}"
|
67
|
+
node.children.each do |node|
|
68
|
+
print_tree(node, depth+1)
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
def print_graph(node_list)
|
73
|
+
check_graphviz_installed
|
74
|
+
digraph do
|
75
|
+
# graph_attribs << 'size="6,6"'
|
76
|
+
node_attribs << lightblue << filled
|
77
|
+
|
78
|
+
node_list.each do |n|
|
79
|
+
node(n.graph_name)
|
80
|
+
n.children.each do |child|
|
81
|
+
edge n.graph_name, child.graph_name
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
random = (0...8).map { (65 + rand(26)).chr }.join
|
86
|
+
path = "/tmp/cloudformation-depends-on-#{random}"
|
87
|
+
save path, "png"
|
88
|
+
# Check if open command exists and use it to open the image.
|
89
|
+
system "open #{path}.png" if system("type open > /dev/null")
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
# Check if Graphiz is installed and prints a user friendly message if it is not installed.
|
94
|
+
# Provide instructions if on macosx.
|
95
|
+
def check_graphviz_installed
|
96
|
+
installed = system("type dot > /dev/null") # dot is a command that is part of the graphviz package
|
97
|
+
unless installed
|
98
|
+
puts "It appears that the Graphviz is not installed. Please install it to generate the graph."
|
99
|
+
if RUBY_PLATFORM =~ /darwin/
|
100
|
+
puts "You can install Graphviz with homebrew:"
|
101
|
+
puts " brew install brew install graphviz"
|
102
|
+
end
|
103
|
+
exit 1
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
class Node
|
108
|
+
attr_accessor :name, :resource_type, :children, :depends_on
|
109
|
+
def initialize(name)
|
110
|
+
@name = name
|
111
|
+
@children = []
|
112
|
+
@depends_on = []
|
113
|
+
end
|
114
|
+
|
115
|
+
def graph_name
|
116
|
+
type = "(#{resource_type})" if resource_type
|
117
|
+
[name, type].compact.join("\n")
|
118
|
+
end
|
119
|
+
end
|
120
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
class Lono::Inspector::Params < Lono::Inspector::Base
|
2
|
+
def perform
|
3
|
+
puts "Parameters Summary:"
|
4
|
+
return if @options[:noop]
|
5
|
+
|
6
|
+
print_parameters("Required", required_parameters)
|
7
|
+
print_parameters("Optional", optional_parameters)
|
8
|
+
end
|
9
|
+
|
10
|
+
def print_parameters(label, parameters)
|
11
|
+
puts "#{label}:"
|
12
|
+
if parameters.empty?
|
13
|
+
puts " There are no #{label.downcase} parameters"
|
14
|
+
else
|
15
|
+
parameters.each do |logical_id, p|
|
16
|
+
puts " #{logical_id}"
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def required_parameters
|
22
|
+
data["Parameters"].select { |logical_id, p| p["Default"] }
|
23
|
+
end
|
24
|
+
|
25
|
+
def optional_parameters
|
26
|
+
data["Parameters"].reject { |logical_id, p| p["Default"] }
|
27
|
+
end
|
28
|
+
end
|
data/lib/lono/version.rb
CHANGED
@@ -0,0 +1 @@
|
|
1
|
+
/output
|
@@ -0,0 +1 @@
|
|
1
|
+
/output
|
data/lono.gemspec
CHANGED
@@ -28,6 +28,7 @@ Gem::Specification.new do |gem|
|
|
28
28
|
gem.add_dependency "hashie"
|
29
29
|
gem.add_dependency "aws-sdk", '~> 3'
|
30
30
|
gem.add_dependency "activesupport"
|
31
|
+
gem.add_dependency "graph" # lono inspect depends
|
31
32
|
# gem.add_dependency "plissken" # dependency for vendor/lono-params
|
32
33
|
# using the vendor fork version: https://github.com/tongueroo/plissken
|
33
34
|
# until https://github.com/futurechimp/plissken/pull/6 gets merged
|
@@ -0,0 +1,20 @@
|
|
1
|
+
require_relative "../../spec_helper"
|
2
|
+
|
3
|
+
describe Lono::Inspector do
|
4
|
+
before(:all) do
|
5
|
+
@args = "--noop --project-root spec/fixtures/my_project"
|
6
|
+
end
|
7
|
+
|
8
|
+
describe "lono inspect" do
|
9
|
+
it "depends" do
|
10
|
+
out = execute("bin/lono inspect depends my-stack #{@args}")
|
11
|
+
expect(out).to include("Generating dependencies tree")
|
12
|
+
end
|
13
|
+
|
14
|
+
it "params" do
|
15
|
+
out = execute("bin/lono inspect params my-stack #{@args}")
|
16
|
+
expect(out).to include("Parameters Summary")
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: lono
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 3.
|
4
|
+
version: 3.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Tung Nguyen
|
@@ -150,6 +150,20 @@ dependencies:
|
|
150
150
|
- - ">="
|
151
151
|
- !ruby/object:Gem::Version
|
152
152
|
version: '0'
|
153
|
+
- !ruby/object:Gem::Dependency
|
154
|
+
name: graph
|
155
|
+
requirement: !ruby/object:Gem::Requirement
|
156
|
+
requirements:
|
157
|
+
- - ">="
|
158
|
+
- !ruby/object:Gem::Version
|
159
|
+
version: '0'
|
160
|
+
type: :runtime
|
161
|
+
prerelease: false
|
162
|
+
version_requirements: !ruby/object:Gem::Requirement
|
163
|
+
requirements:
|
164
|
+
- - ">="
|
165
|
+
- !ruby/object:Gem::Version
|
166
|
+
version: '0'
|
153
167
|
- !ruby/object:Gem::Dependency
|
154
168
|
name: byebug
|
155
169
|
requirement: !ruby/object:Gem::Requirement
|
@@ -262,6 +276,11 @@ files:
|
|
262
276
|
- lib/lono/env.rb
|
263
277
|
- lib/lono/help.rb
|
264
278
|
- lib/lono/importer.rb
|
279
|
+
- lib/lono/inspector.rb
|
280
|
+
- lib/lono/inspector/base.rb
|
281
|
+
- lib/lono/inspector/depends.rb
|
282
|
+
- lib/lono/inspector/help.rb
|
283
|
+
- lib/lono/inspector/params.rb
|
265
284
|
- lib/lono/new.rb
|
266
285
|
- lib/lono/param.rb
|
267
286
|
- lib/lono/param/generator.rb
|
@@ -277,6 +296,7 @@ files:
|
|
277
296
|
- lib/lono/template/template.rb
|
278
297
|
- lib/lono/template/upload.rb
|
279
298
|
- lib/lono/version.rb
|
299
|
+
- lib/starter_projects/json_project/.gitignore
|
280
300
|
- lib/starter_projects/json_project/Gemfile
|
281
301
|
- lib/starter_projects/json_project/Guardfile
|
282
302
|
- lib/starter_projects/json_project/config/templates/base/blog.rb
|
@@ -290,6 +310,7 @@ files:
|
|
290
310
|
- lib/starter_projects/json_project/templates/user_data/db2.sh
|
291
311
|
- lib/starter_projects/json_project/templates/user_data/ruby_script.rb
|
292
312
|
- lib/starter_projects/json_project/templates/web.json
|
313
|
+
- lib/starter_projects/yaml_project/.gitignore
|
293
314
|
- lib/starter_projects/yaml_project/Gemfile
|
294
315
|
- lib/starter_projects/yaml_project/Guardfile
|
295
316
|
- lib/starter_projects/yaml_project/config/templates/base/blog.rb
|
@@ -322,6 +343,7 @@ files:
|
|
322
343
|
- spec/fixtures/params/overlay/params/prod/network.txt
|
323
344
|
- spec/fixtures/raw_templates/aws-waf-security-automations.template
|
324
345
|
- spec/lib/lono/cfn_spec.rb
|
346
|
+
- spec/lib/lono/inspect_spec.rb
|
325
347
|
- spec/lib/lono/new_spec.rb
|
326
348
|
- spec/lib/lono/param/generator_spec.rb
|
327
349
|
- spec/lib/lono/param_spec.rb
|
@@ -380,6 +402,7 @@ test_files:
|
|
380
402
|
- spec/fixtures/params/overlay/params/prod/network.txt
|
381
403
|
- spec/fixtures/raw_templates/aws-waf-security-automations.template
|
382
404
|
- spec/lib/lono/cfn_spec.rb
|
405
|
+
- spec/lib/lono/inspect_spec.rb
|
383
406
|
- spec/lib/lono/new_spec.rb
|
384
407
|
- spec/lib/lono/param/generator_spec.rb
|
385
408
|
- spec/lib/lono/param_spec.rb
|