Class: Lono::DSL

Inherits:
Object
  • Object
show all
Defined in:
lib/lono/dsl.rb

Instance Method Summary collapse

Constructor Details

#initialize(options = {}) ⇒ DSL

Returns a new instance of DSL.



3
4
5
6
7
8
9
10
# File 'lib/lono/dsl.rb', line 3

def initialize(options={})
  @options = options
  @options[:project_root] ||= '.'
  @path = "#{@options[:project_root]}/config/lono.rb"
  @templates = []
  @results = {}
  @detected_format = nil
end

Instance Method Details

#buildObject



59
60
61
62
63
# File 'lib/lono/dsl.rb', line 59

def build
  @templates.each do |t|
    @results[t[:name]] = Template.new(t[:name], t[:block], @options).build
  end
end

#detect_formatObject

Detects the format of the templates. Simply checks the extension of all the templates files. All the templates must be of the same format, either all json or all yaml.



27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
# File 'lib/lono/dsl.rb', line 27

def detect_format
  # @templates contains Array of Hashes. Example:
  # [{name: ""blog-web-prod.json", block: ...},
  #  {name: ""api-web-prod.json", block: ...}]
  formats = @templates.map{ |t| File.extname(t[:name]) }.uniq
  if formats.size > 1
    puts "ERROR: Detected multiple formats: #{formats.join(", ")}".colorize(:red)
    puts "All the source values in the template blocks in the config folder must have the same format extension."
    exit 1
  else
    found_format = formats.first
    if found_format
      detected_format = found_format.sub(/^\./,'')
      detected_format = "yaml" if detected_format == "yml"
    else # empty templates, no templates defined yet
      detected_format = "yaml" # defaults to yaml
    end
  end
  detected_format
end

#ensure_parent_dir(path) ⇒ Object



127
128
129
130
# File 'lib/lono/dsl.rb', line 127

def ensure_parent_dir(path)
  dir = File.dirname(path)
  FileUtils.mkdir_p(dir) unless File.exist?(dir)
end

#evaluateObject



18
19
20
21
22
# File 'lib/lono/dsl.rb', line 18

def evaluate
  instance_eval(File.read(@path), @path)
  load_subfolder
  @detected_format = detect_format
end

#load_subfolderObject

load any templates defined in project/config/lono/*



49
50
51
52
53
# File 'lib/lono/dsl.rb', line 49

def load_subfolder
  Dir.glob("#{File.dirname(@path)}/lono/**/*").select{ |e| File.file? e }.each do |path|
    instance_eval(File.read(path), path)
  end
end

#outputObject



65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
# File 'lib/lono/dsl.rb', line 65

def output
  output_path = "#{@options[:project_root]}/output"
  FileUtils.rm_rf(output_path) if @options[:clean]
  FileUtils.mkdir(output_path) unless File.exist?(output_path)
  puts "Generating CloudFormation templates:" unless @options[:quiet]
  @results.each do |name,text|
    path = "#{output_path}/#{name}"
    puts "  #{path}" unless @options[:quiet]
    ensure_parent_dir(path)
    validate(text, path)
    File.open(path, 'w') do |f|
      f.write(output_format(text))
    end
  end
end

#output_format(text) ⇒ Object



112
113
114
# File 'lib/lono/dsl.rb', line 112

def output_format(text)
  @options[:pretty] ? prettify(text) : text
end

#prettify(text) ⇒ Object

Input text is either yaml or json. Do not prettify yaml format because it removes the !Ref like CloudFormation notation



118
119
120
# File 'lib/lono/dsl.rb', line 118

def prettify(text)
  @detected_format == "json" ? JSON.pretty_generate(JSON.parse(text)) : remove_blank_lines(text)
end

#remove_blank_lines(text) ⇒ Object

ERB templates leaves blank lines around, remove those lines



123
124
125
# File 'lib/lono/dsl.rb', line 123

def remove_blank_lines(text)
  text.split("\n").reject { |l| l.strip == '' }.join("\n") + "\n"
end

#run(options = {}) ⇒ Object



12
13
14
15
16
# File 'lib/lono/dsl.rb', line 12

def run(options={})
  evaluate
  build
  output
end

#template(name, &block) ⇒ Object



55
56
57
# File 'lib/lono/dsl.rb', line 55

def template(name, &block)
  @templates << {name: name, block: block}
end

#validate(text, path) ⇒ Object

TODO: set @detected_format upon DSL.new



82
83
84
85
86
87
88
# File 'lib/lono/dsl.rb', line 82

def validate(text, path)
  if @detected_format == "json"
    validate_json(text, path)
  else
    validate_yaml(text, path)
  end
end

#validate_json(json, path) ⇒ Object



101
102
103
104
105
106
107
108
109
110
# File 'lib/lono/dsl.rb', line 101

def validate_json(json, path)
  begin
    JSON.parse(json)
  rescue JSON::ParserError => e
    puts "Invalid json.  Output written to #{path} for debugging".colorize(:red)
    puts "ERROR: #{e.message}".colorize(:red)
    File.open(path, 'w') {|f| f.write(json) }
    exit 1
  end
end

#validate_yaml(yaml, path) ⇒ Object



90
91
92
93
94
95
96
97
98
99
# File 'lib/lono/dsl.rb', line 90

def validate_yaml(yaml, path)
  begin
    YAML.load(yaml)
  rescue Psych::SyntaxError => e
    puts "Invalid yaml.  Output written to #{path} for debugging".colorize(:red)
    puts "ERROR: #{e.message}".colorize(:red)
    File.open(path, 'w') {|f| f.write(yaml) }
    exit 1
  end
end