Class: Lono::Param::Generator

Inherits:
Object
  • Object
show all
Includes:
Blueprint::Root, Conventions
Defined in:
lib/lono/param/generator.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods included from Conventions

#template_param_convention

Methods included from Blueprint::Root

#bundler_groups, #find_blueprint_root, #require_bundle_gems, #set_blueprint_root

Constructor Details

#initialize(blueprint, options = {}) ⇒ Generator

Returns a new instance of Generator.



7
8
9
10
11
# File 'lib/lono/param/generator.rb', line 7

def initialize(blueprint, options={})
  @blueprint, @options = blueprint, options
  set_blueprint_root(@blueprint)
  @template, @param = template_param_convention(options)
end

Instance Attribute Details

#base_pathObject (readonly)

set when generate is called



6
7
8
# File 'lib/lono/param/generator.rb', line 6

def base_path
  @base_path
end

#env_pathObject (readonly)

set when generate is called



6
7
8
# File 'lib/lono/param/generator.rb', line 6

def env_path
  @env_path
end

Instance Method Details

#contextObject

Context for ERB rendering. This is where we control what references get passed to the ERB rendering.



151
152
153
# File 'lib/lono/param/generator.rb', line 151

def context
  @context ||= Lono::Template::Context.new(@blueprint, @options)
end

#convert_to_cfn_format(contents, casing = :camel) ⇒ Object



166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
# File 'lib/lono/param/generator.rb', line 166

def convert_to_cfn_format(contents, casing=:camel)
  lines = parse_contents(contents)

  # First use a Hash structure so that overlay env files will override
  # the base param file.
  data = {}
  lines.each do |line|
    key,value = line.strip.split("=").map {|x| x.strip}
    data[key] = value
  end

  # Now build up the aws json format for parameters
  params = []
  data.each do |key,value|
    param = if value == "use_previous_value"
              {
                "ParameterKey": key,
                "UsePreviousValue": true
              }
            elsif value
              {
                "ParameterKey": key,
                "ParameterValue": value
              }
            end
    if param
      param = param.to_snake_keys if casing == :underscore
      params << param
    end
  end
  params
end

#generateObject



69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
# File 'lib/lono/param/generator.rb', line 69

def generate
  puts "Generating parameter files for blueprint #{@blueprint.color(:green)}:"

  @base_path, @env_path = lookup_paths

  return unless @base_path || @env_path

  # useful option for lono cfn, since some templates dont require params
  return if @options[:allow_not_exists] && !source_exist?

  if source_exist?
    contents = process_erb
    data = convert_to_cfn_format(contents)
    json = JSON.pretty_generate(data)
    write_output(json)
    unless @options[:mute]
      short_output_path = output_path.sub("#{Lono.root}/","")
      puts "  #{short_output_path}"
    end
  else
    puts "#{@base_path} or #{@env_path} could not be found?  Are you sure it exist?"
    exit 1
  end
  json
end

#lookup_param_file(root: Lono.root, env: Lono.env) ⇒ Object

Lookup precedence:

configs/BLUEPRINT/params/development/TEMPLATE/PARAM.txt
configs/BLUEPRINT/params/development/PARAM.txt
configs/BLUEPRINT/params/development.txt


28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
# File 'lib/lono/param/generator.rb', line 28

def lookup_param_file(root: Lono.root, env: Lono.env)
  long_form = "#{root}/configs/#{@blueprint}/params/#{env}/#{@template}/#{@param}.txt"
  medium_form = "#{root}/configs/#{@blueprint}/params/#{env}/#{@param}.txt"
  short_form = "#{root}/configs/#{@blueprint}/params/#{env}.txt"

  if ENV['LONO_PARAM_DEBUG']
    puts "Lono.blueprint_root #{Lono.blueprint_root}"
    puts "long_form #{long_form}"
    puts "medium_form #{medium_form}"
    puts "short_form #{short_form}"
  end

  return long_form if File.exist?(long_form) # always consider this first because its so explicit

  # All 3 are the same
  # Also, blueprint and template the same and explicitly specified param
  if @blueprint == @template
    return medium_form if File.exist?(medium_form) # higher precedence between longer but short form should be encouraged
    return short_form if File.exist?(short_form)
    return # cannot find a param file
  end

  # Only template and param are the same
  if @template == @param
    return medium_form if File.exist?(medium_form) # only consider medium form
    return # cannot find a param file
  end
end

#lookup_pathsObject



57
58
59
60
61
62
63
64
65
66
67
# File 'lib/lono/param/generator.rb', line 57

def lookup_paths
  @base_path = lookup_param_file(env: "base")
  @env_path = lookup_param_file(env: Lono.env)

  if ENV['LONO_PARAM_DEBUG']
    puts "  @base_path #{@base_path.inspect}"
    puts "  @env_path #{@env_path.inspect}"
  end

  [@base_path, @env_path]
end

#output_pathObject



199
200
201
202
203
204
205
206
207
208
# File 'lib/lono/param/generator.rb', line 199

def output_path
  output = Lono.config.output_path.sub("#{Lono.root}/","")
  path = if @base_path && !@env_path
           # Handle case when base config exist but the env config does not
           @base_path.sub("configs", output).sub("base", Lono.env)
         else
           @env_path.sub("configs", output)
         end
  path.sub(/\.txt$/,'.json')
end

#params(casing = :underscore) ⇒ Object

useful for when calling CloudFormation via the aws-sdk gem



105
106
107
108
109
110
111
112
113
# File 'lib/lono/param/generator.rb', line 105

def params(casing = :underscore)
  @base_path, @env_path = lookup_paths

  # useful option for lono cfn
  return {} if @options[:allow_not_exists] && !source_exist?

  contents = process_erb
  convert_to_cfn_format(contents, casing)
end

#parse_contents(contents) ⇒ Object



155
156
157
158
159
160
161
162
163
164
# File 'lib/lono/param/generator.rb', line 155

def parse_contents(contents)
  lines = contents.split("\n")
  # remove comment at the end of the line
  lines.map! { |l| l.sub(/#.*/,'').strip }
  # filter out commented lines
  lines = lines.reject { |l| l =~ /(^|\s)#/i }
  # filter out empty lines
  lines = lines.reject { |l| l.strip.empty? }
  lines
end

#process_erbObject

Reads both the base source and env source and overlay the two Example 1:

params/base/mystack.txt - base path
params/production/mystack.txt - env path

the base/mystack.txt gets combined with the prod/mystack.txt
it produces a final prod/mystack.txt

Example 2:

params/base/mystack.txt - base path

the base/mystack.txt is used to produced a prod/mystack.txt

Example 3:

params/production/mystack.txt - env path

the prod/mystack.txt is used to produced a prod/mystack.txt


132
133
134
135
136
137
138
139
140
# File 'lib/lono/param/generator.rb', line 132

def process_erb
  contents = []
  contents << render_erb(@base_path)
  contents << render_erb(@env_path)
  result = contents.compact.join("\n")
  # puts "process_erb result".color(:yellow)
  # puts result
  result
end

#puts_param_message(type) ⇒ Object



13
14
15
16
17
18
19
20
# File 'lib/lono/param/generator.rb', line 13

def puts_param_message(type)
  path = send("#{type}_path")
  return unless path
  if File.exist?(path)
    pretty_path = path.sub("#{Lono.root}/",'')
    puts "Using param: #{pretty_path}".color(:yellow)
  end
end

#render_erb(path) ⇒ Object



142
143
144
145
146
147
# File 'lib/lono/param/generator.rb', line 142

def render_erb(path)
  return unless path
  if File.exist?(path)
    RenderMePretty.result(path, context: context)
  end
end

#source_exist?Boolean

Checks both base and source path for existing of the param file. Example:

params/base/mystack.txt - base path
params/production/mystack.txt - source path

Returns:

  • (Boolean)


99
100
101
102
# File 'lib/lono/param/generator.rb', line 99

def source_exist?
  @base_path && File.exist?(@base_path) ||
  @env_path && File.exist?(@env_path)
end

#write_output(json) ⇒ Object



210
211
212
213
214
# File 'lib/lono/param/generator.rb', line 210

def write_output(json)
  dir = File.dirname(output_path)
  FileUtils.mkdir_p(dir)
  IO.write(output_path, json)
end