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.
@@ -0,0 +1,35 @@
1
+ module Lono
2
+ class OutputTemplate
3
+ def initialize(blueprint, template)
4
+ @blueprint, @template = blueprint, template
5
+ end
6
+
7
+ def data
8
+ template_path = "#{Lono.config.output_path}/#{@blueprint}/templates/#{@template}.yml"
9
+ check_template_exists(template_path)
10
+ YAML.load(IO.read(template_path))
11
+ end
12
+
13
+ # Check if the template exists and print friendly error message. Exits if it
14
+ # does not exist.
15
+ def check_template_exists(template_path)
16
+ unless File.exist?(template_path)
17
+ 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.".color(:red)
18
+ exit 1
19
+ end
20
+ end
21
+
22
+ def required_parameters
23
+ parameters.reject { |logical_id, p| p["Default"] }
24
+ end
25
+
26
+ def optional_parameters
27
+ parameters.select { |logical_id, p| p["Default"] }
28
+ end
29
+
30
+ def parameters
31
+ data["Parameters"] || []
32
+ end
33
+
34
+ end
35
+ end
@@ -13,9 +13,9 @@ class Lono::Param
13
13
  def puts_param_message(type)
14
14
  path = send("#{type}_path")
15
15
  return unless path
16
- if File.exist?(path)
16
+ if param_file?(path)
17
17
  pretty_path = path.sub("#{Lono.root}/",'')
18
- puts "Using param: #{pretty_path}".color(:yellow)
18
+ puts "Using param for #{type}: #{pretty_path}".color(:yellow)
19
19
  end
20
20
  end
21
21
 
@@ -26,34 +26,63 @@ class Lono::Param
26
26
  # configs/BLUEPRINT/params/development.txt
27
27
  #
28
28
  def lookup_param_file(root: Lono.root, env: Lono.env)
29
- long_form = "#{root}/configs/#{@blueprint}/params/#{env}/#{@template}/#{@param}.txt"
30
- medium_form = "#{root}/configs/#{@blueprint}/params/#{env}/#{@param}.txt"
31
- short_form = "#{root}/configs/#{@blueprint}/params/#{env}.txt"
29
+ # The docs conver direct_absolute_form and direct_relative_form as the "Direct Form"
30
+ unless env == "base"
31
+ direct_absolute_form = @param # user provided the absolute full path
32
+ direct_relative_form = "#{root}/#{@param}" # user provided the full path within the lono project
33
+ direct_env_form = "#{root}/configs/#{@blueprint}/params/#{env}/#{@param}" # direct lookup is simple
34
+ direct_simple_form = "#{root}/configs/#{@blueprint}/params/#{@param}" # direct lookup is simple
35
+ end
36
+ long_form = "#{root}/configs/#{@blueprint}/params/#{env}/#{@template}/#{@param}"
37
+ medium_form = "#{root}/configs/#{@blueprint}/params/#{env}/#{@param}"
38
+ short_form = "#{root}/configs/#{@blueprint}/params/#{env}"
32
39
 
33
40
  if ENV['LONO_PARAM_DEBUG']
34
41
  puts "Lono.blueprint_root #{Lono.blueprint_root}"
42
+ puts "direct_absolute_form #{direct_absolute_form}"
43
+ puts "direct_relative_form #{direct_relative_form}"
44
+ puts "direct_env_form #{direct_env_form}"
45
+ puts "direct_simple_form #{direct_simple_form}"
35
46
  puts "long_form #{long_form}"
36
47
  puts "medium_form #{medium_form}"
37
48
  puts "short_form #{short_form}"
38
49
  end
39
50
 
40
- return long_form if File.exist?(long_form) # always consider this first because its so explicit
51
+ unless env == "base"
52
+ return param_file(direct_absolute_form) if param_file?(direct_absolute_form)
53
+ return param_file(direct_relative_form) if param_file?(direct_relative_form)
54
+ return param_file(direct_env_form) if param_file?(direct_env_form) # consider this first its simple and direct but is scope to env so it's more specific
55
+ return param_file(direct_simple_form) if param_file?(direct_simple_form) # consider this first its simple and direct but is scope to env so it's more specific
56
+ end
57
+ return param_file(long_form) if param_file?(long_form) # consider this first because its more explicit
41
58
 
42
59
  # All 3 are the same
43
60
  # Also, blueprint and template the same and explicitly specified param
44
61
  if @blueprint == @template
45
- return medium_form if File.exist?(medium_form) # higher precedence between longer but short form should be encouraged
46
- return short_form if File.exist?(short_form)
62
+ return param_file(medium_form) if param_file?(medium_form) # higher precedence between longer but short form should be encouraged
63
+ return param_file(short_form) if param_file?(short_form)
47
64
  return # cannot find a param file
48
65
  end
49
66
 
50
67
  # Only template and param are the same
51
68
  if @template == @param
52
- return medium_form if File.exist?(medium_form) # only consider medium form
69
+ return param_file(medium_form) if param_file?(medium_form) # only consider medium form
53
70
  return # cannot find a param file
54
71
  end
55
72
  end
56
73
 
74
+ # Allows user to specify the .txt extension or not to.
75
+ # Also allows user to use other extensions like .sh if they are explicit about it.
76
+ def param_file?(path)
77
+ File.file?(path) || File.file?("#{path}.txt") || File.file?("#{path}.sh")
78
+ end
79
+
80
+ def param_file(path)
81
+ return path if File.file?(path)
82
+ return "#{path}.txt" if File.file?("#{path}.txt")
83
+ return "#{path}.sh" if File.file?("#{path}.sh")
84
+ end
85
+
57
86
  def lookup_paths
58
87
  @base_path = lookup_param_file(env: "base")
59
88
  @env_path = lookup_param_file(env: Lono.env)
@@ -133,7 +133,9 @@ class Lono::Seed
133
133
 
134
134
  def default_value(data)
135
135
  value = data["Default"]
136
- if value.blank?
136
+ # Dont use !blank? since there can be false optional values
137
+ # Also dont use .empty? since value can be an Integer
138
+ if value.nil? || value == ''
137
139
  description_example(data["Description"])
138
140
  else
139
141
  value
@@ -148,11 +150,11 @@ class Lono::Seed
148
150
  memoize :parameters
149
151
 
150
152
  def required(parameters)
151
- parameters.reject { |logical_id, p| p["Default"] }
153
+ parameters.select { |logical_id, p| p["Default"].nil? } # allow for false
152
154
  end
153
155
 
154
156
  def optional(parameters)
155
- parameters.select { |logical_id, p| p["Default"] }
157
+ parameters.select { |logical_id, p| !p["Default"].nil? } # allow for false
156
158
  end
157
159
 
158
160
  private
@@ -1,8 +1,10 @@
1
1
  # Encapsulates helper methods and instance variables to be rendered in the ERB templates.
2
2
  class Lono::Template
3
3
  class Context
4
+ extend Memoist
4
5
  include Lono::Template::Helper
5
6
  include Loader
7
+ include Helpers
6
8
 
7
9
  def initialize(blueprint, options={})
8
10
  @blueprint, @options = blueprint, options
@@ -0,0 +1,14 @@
1
+ class Lono::Template::Context
2
+ module Helpers
3
+ extend Memoist
4
+
5
+ def ssm(name)
6
+ ssm_fetcher.get(name)
7
+ end
8
+
9
+ def ssm_fetcher
10
+ SsmFetcher.new
11
+ end
12
+ memoize :ssm_fetcher
13
+ end
14
+ end
@@ -0,0 +1,23 @@
1
+ require 'aws-sdk-ssm'
2
+
3
+ class Lono::Template::Context
4
+ class SsmFetcher
5
+ extend Memoist
6
+
7
+ def get(name)
8
+ fetch_ssm_value(name)
9
+ end
10
+
11
+ def fetch_ssm_value(name)
12
+ resp = ssm.get_parameter(name: name, with_decryption: true)
13
+ resp.parameter.value
14
+ rescue Aws::SSM::Errors::ParameterNotFound
15
+ 'SSM-PARAM-NOT-FOUND'
16
+ end
17
+
18
+ def ssm
19
+ Aws::SSM::Client.new
20
+ end
21
+ memoize :ssm
22
+ end
23
+ end
@@ -16,10 +16,10 @@ class Lono::Template::Dsl::Builder
16
16
  elsif definition.size == 2 && second.is_a?(Hash) # medium form
17
17
  logical_id, properties = first, second
18
18
  { logical_id => properties }
19
- elsif (definition.size == 2 && num_or_str?(second)) || # short form
19
+ elsif (definition.size == 2 && valid_value?(second)) || # short form
20
20
  definition.size == 1
21
21
  logical_id = first
22
- properties = num_or_str?(second) ? { default: second } : {}
22
+ properties = valid_value?(second) ? { default: second } : {}
23
23
  { logical_id => properties }
24
24
  else # I dont know what form
25
25
  raise "Invalid form provided. definition #{definition.inspect}"
@@ -32,8 +32,8 @@ class Lono::Template::Dsl::Builder
32
32
  attributes
33
33
  end
34
34
 
35
- def num_or_str?(o)
36
- o.is_a?(Float) || o.is_a?(Integer) || o.is_a?(String)
35
+ def valid_value?(o)
36
+ o.is_a?(Float) || o.is_a?(Integer) || o.is_a?(String) || o.is_a?(TrueClass) || o.is_a?(FalseClass)
37
37
  end
38
38
  end
39
39
  end
@@ -17,19 +17,24 @@ class Lono::Template::Dsl::Builder
17
17
  logical_id, attributes = first, second
18
18
  attributes.delete(:properties) if attributes[:properties].nil? || attributes[:properties].empty?
19
19
  { logical_id => attributes }
20
- elsif definition.size == 2 && second.is_a?(String) # short form
20
+ elsif definition.size == 2 && second.is_a?(String) # short form with no properties
21
21
  logical_id, type = first, second
22
22
  { logical_id => {
23
23
  type: type
24
24
  }}
25
- elsif definition.size == 3 && (second.is_a?(String) || second.is_a?(NilClass))# short form
25
+ elsif definition.size == 3 && (second.is_a?(String) || second.is_a?(NilClass)) # short form
26
26
  logical_id, type, properties = first, second, third
27
- template = { logical_id => {
27
+ resource = { logical_id => {
28
28
  type: type
29
29
  }}
30
- attributes = template.values.first
30
+
31
+ attributes = resource.values.first
32
+
33
+ property_mover = PropertyMover.new(resource, logical_id, properties)
34
+ property_mover.move!
35
+
31
36
  attributes[:properties] = properties unless properties.empty?
32
- template
37
+ resource
33
38
  else # Dont understand this form
34
39
  raise "Invalid form provided. definition #{definition.inspect}"
35
40
  end
@@ -0,0 +1,19 @@
1
+ class Lono::Template::Dsl::Builder::Resource
2
+ # Moves the property to the top-level attributes *destructively*
3
+ class PropertyMover
4
+ def initialize(resource, logical_id, properties)
5
+ @resource, @logical_id, @properties = resource, logical_id, properties
6
+ end
7
+
8
+ def move!
9
+ %w[depends_on condition].each do |attribute_name|
10
+ move(attribute_name.to_sym)
11
+ end
12
+ end
13
+
14
+ def move(attribute_name)
15
+ attribute_value = @properties.delete(attribute_name)
16
+ @resource[@logical_id][attribute_name] = attribute_value if attribute_value
17
+ end
18
+ end
19
+ end
data/lib/lono/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Lono
2
- VERSION = "5.2.8"
2
+ VERSION = "5.3.0"
3
3
  end
data/lono.gemspec CHANGED
@@ -26,6 +26,7 @@ Gem::Specification.new do |gem|
26
26
  gem.add_dependency "aws-sdk-ec2" # lono seed
27
27
  gem.add_dependency "aws-sdk-iam" # lono seed
28
28
  gem.add_dependency "aws-sdk-s3"
29
+ gem.add_dependency "aws-sdk-ssm"
29
30
  gem.add_dependency "cfn_camelizer"
30
31
  gem.add_dependency "filesize"
31
32
  gem.add_dependency "graph" # lono xgraph command dependency
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: lono
3
3
  version: !ruby/object:Gem::Version
4
- version: 5.2.8
4
+ version: 5.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Tung Nguyen
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2019-11-10 00:00:00.000000000 Z
11
+ date: 2019-11-23 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -94,6 +94,20 @@ dependencies:
94
94
  - - ">="
95
95
  - !ruby/object:Gem::Version
96
96
  version: '0'
97
+ - !ruby/object:Gem::Dependency
98
+ name: aws-sdk-ssm
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ">="
102
+ - !ruby/object:Gem::Version
103
+ version: '0'
104
+ type: :runtime
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ">="
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
97
111
  - !ruby/object:Gem::Dependency
98
112
  name: cfn_camelizer
99
113
  requirement: !ruby/object:Gem::Requirement
@@ -453,9 +467,12 @@ files:
453
467
  - lib/lono/cfn/current.rb
454
468
  - lib/lono/cfn/delete.rb
455
469
  - lib/lono/cfn/deploy.rb
456
- - lib/lono/cfn/diff.rb
457
470
  - lib/lono/cfn/download.rb
458
471
  - lib/lono/cfn/preview.rb
472
+ - lib/lono/cfn/preview/changeset.rb
473
+ - lib/lono/cfn/preview/codediff.rb
474
+ - lib/lono/cfn/preview/diff_viewer.rb
475
+ - lib/lono/cfn/preview/param.rb
459
476
  - lib/lono/cfn/rollback.rb
460
477
  - lib/lono/cfn/status.rb
461
478
  - lib/lono/cfn/suffix.rb
@@ -481,7 +498,6 @@ files:
481
498
  - lib/lono/help/cfn/current.md
482
499
  - lib/lono/help/cfn/delete.md
483
500
  - lib/lono/help/cfn/deploy.md
484
- - lib/lono/help/cfn/diff.md
485
501
  - lib/lono/help/cfn/download.md
486
502
  - lib/lono/help/cfn/preview.md
487
503
  - lib/lono/help/cfn/status.md
@@ -509,6 +525,7 @@ files:
509
525
  - lib/lono/md5.rb
510
526
  - lib/lono/new.rb
511
527
  - lib/lono/new/helper.rb
528
+ - lib/lono/output_template.rb
512
529
  - lib/lono/param.rb
513
530
  - lib/lono/param/generator.rb
514
531
  - lib/lono/project_checker.rb
@@ -527,7 +544,9 @@ files:
527
544
  - lib/lono/template/base.rb
528
545
  - lib/lono/template/bashify.rb
529
546
  - lib/lono/template/context.rb
547
+ - lib/lono/template/context/helpers.rb
530
548
  - lib/lono/template/context/loader.rb
549
+ - lib/lono/template/context/ssm_fetcher.rb
531
550
  - lib/lono/template/dsl.rb
532
551
  - lib/lono/template/dsl/builder.rb
533
552
  - lib/lono/template/dsl/builder/base.rb
@@ -538,6 +557,7 @@ files:
538
557
  - lib/lono/template/dsl/builder/output.rb
539
558
  - lib/lono/template/dsl/builder/parameter.rb
540
559
  - lib/lono/template/dsl/builder/resource.rb
560
+ - lib/lono/template/dsl/builder/resource/property_mover.rb
541
561
  - lib/lono/template/dsl/builder/section.rb
542
562
  - lib/lono/template/dsl/builder/syntax.rb
543
563
  - lib/lono/template/erb.rb
@@ -1,24 +0,0 @@
1
- Displays code diff of the generated CloudFormation template locally vs the existing template on AWS. You can set a desired diff viewer by setting the `LONO_DIFF` environment variable.
2
-
3
- ## Examples
4
-
5
- $ lono cfn diff ec2
6
- Using template: output/templates/ec2.yml
7
- Using parameters: config/params/development/ec2.txt
8
- No detected app/scripts
9
- Generating CloudFormation templates:
10
- output/templates/ec2.yml
11
- output/params/ec2.json
12
- Generating CloudFormation source code diff...
13
- Running: colordiff /tmp/existing_cfn_template.yml output/templates/ec2.yml
14
- 19c19
15
- < Default: t2.small
16
- ---
17
- > Default: t2.medium
18
- $
19
-
20
- Here's a screenshot of the output with the colored diff:
21
-
22
- <img src="/img/reference/lono-cfn-diff.png" alt="Stack Update" class="doc-photo">
23
-
24
- A `lono cfn diff` is perform automatically as part of `lono cfn update`.