lono 3.1.3 → 3.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
  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