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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 9676395a3c8e7bca5d65e687de6b5b696cf6f592
4
- data.tar.gz: c07ef7778f3fa56c64c0ac1245c7ca752ccdd436
3
+ metadata.gz: 6960654946363019c9b4f49f0dbd174939c09949
4
+ data.tar.gz: 170581eadc5099100aba6146a6ed51d14c89e01a
5
5
  SHA512:
6
- metadata.gz: cbcd2b38a457165cd0bb324f85320233f14aa138cbf1903c0e7e653a8875ddfbb26cdfa5465e1e70f7cca597551436c4dc2cec3191e21e97ff1ffde0afb5e954
7
- data.tar.gz: 5908edf59c81935a75f72b9426c0b3175810e1e1d3527d7e05a3ec6693344db19e534e7983accb6248f2bb60de5069c8e6ff5928e140b96ccd8c5dd0914b5a9d
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
@@ -25,6 +25,7 @@ module Lono
25
25
  autoload :Clean, 'lono/clean'
26
26
  autoload :Settings, 'lono/settings'
27
27
  autoload :Importer, 'lono/importer'
28
+ autoload :Inspector, 'lono/inspector'
28
29
  end
29
30
 
30
31
  Lono::Env.setup!
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
@@ -68,5 +68,15 @@ $ lono param generate
68
68
  EOL
69
69
  end
70
70
 
71
+ def inspector
72
+ <<-EOL
73
+ Examples:
74
+
75
+ $ lono inspect params my-stack
76
+
77
+ $ lono inspect depends my-stack
78
+ EOL
79
+ end
80
+
71
81
  extend self
72
82
  end
data/lib/lono/importer.rb CHANGED
@@ -12,10 +12,12 @@ class Lono::Importer
12
12
  end
13
13
 
14
14
  def run
15
- download_template
16
- template_definition_path = add_template_definition
17
- puts "Imported raw CloudFormation template and lono-fied it!"
18
- puts "Template definition added to #{template_definition_path}."
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,21 @@
1
+ class Lono::Inspector::Help
2
+ class << self
3
+ def params
4
+ <<-EOL
5
+ Example:
6
+
7
+ $ lono inspect params my-stack
8
+
9
+ EOL
10
+ end
11
+
12
+ def depends
13
+ <<-EOL
14
+ Example:
15
+
16
+ $ lono inspect depends my-stack
17
+
18
+ EOL
19
+ end
20
+ end
21
+ 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
@@ -1,3 +1,3 @@
1
1
  module Lono
2
- VERSION = "3.1.3"
2
+ VERSION = "3.2.0"
3
3
  end
@@ -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
@@ -1,3 +1 @@
1
1
  # this file is just in here to get the lono-cfn spec to pass
2
-
3
- template "aws-waf-security-automations"
@@ -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.1.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