class Cfhighlander::Compiler::ComponentCompiler

Attributes

cfn_output_location[RW]
cfn_template_paths[RW]
compiled_subcomponents[RW]
component[RW]
component_name[RW]
config_output_location[RW]
dsl_output_location[RW]
lambda_mock_resolve[RW]
lambda_src_paths[RW]
process_lambdas[RW]
silent_mode[RW]
workdir[RW]

Public Class Methods

new(component) click to toggle source
# File lib/cfhighlander.compiler.rb, line 37
def initialize(component)

  @workdir = ENV['CFHIGHLANDER_WORKDIR']
  @component = component
  @sub_components = []
  @component_name = component.highlander_dsl.name.downcase
  @cfndsl_compiled = false
  @config_compiled = false
  @cfn_template_paths = []
  @lambdas_processed = false
  @silent_mode = false
  @lambda_src_paths = []
  @config_yaml_path = nil
  @cfn_model = nil
  @process_lambdas = true
  @lambda_mock_resolve = false

  if @@global_extensions_paths.empty?
    global_extensions_folder = "#{File.dirname(__FILE__)}/../cfndsl_ext"
    Dir["#{global_extensions_folder}/*.rb"].each { |f| @@global_extensions_paths << f }
  end

  @component.highlander_dsl.subcomponents.each do |sub_component|
    sub_component_compiler = Cfhighlander::Compiler::ComponentCompiler.new(sub_component.component_loaded)
    sub_component_compiler.component_name = sub_component.name
    @sub_components << sub_component_compiler
  end
end

Public Instance Methods

clear_out_dir() click to toggle source
# File lib/cfhighlander.compiler.rb, line 66
def clear_out_dir
  # Clear previous packages
  FileUtils.rmtree "#{@workdir}/out/"
end
compileCfnDsl(out_format) click to toggle source
# File lib/cfhighlander.compiler.rb, line 86
def compileCfnDsl(out_format)
  processLambdas unless @lambdas_processed
  writeConfig unless @config_written
  dsl = @component.highlander_dsl
  component_cfndsl = @component.cfndsl_content

  @component.highlander_dsl.subcomponents.each { |sc|
    sc.distribution_format = out_format
  }

  # figure out cfndsl version
  cfndsl_version = CfnDsl::VERSION
  legacy_cfndsl = cfndsl_version.to_f < 1

  # indent component cfndsl
  component_cfndsl.gsub!("\n", "\n\t")
  component_cfndsl.gsub!("\r\n", "\r\n\t")
  # render cfndsl
  renderer = ERB.new(File.read("#{__dir__}/../templates/cfndsl.component.template.erb"), nil, '-')
  cfn_template = renderer.result(OpenStruct.new({
      'dsl' => dsl,
      'component_cfndsl' => component_cfndsl,
      'component_requires' => (@@global_extensions_paths + @component.cfndsl_ext_files),
      'distribution_format' => out_format,
      'legacy_cfndsl' => legacy_cfndsl,
      'cfndsl_version' => cfndsl_version
  }).instance_eval { binding })

  # write to output file
  output_dir = "#{@workdir}/out/cfndsl"
  @dsl_output_location = output_dir
  output_path = "#{output_dir}/#{@component_name}.compiled.cfndsl.rb"
  FileUtils.mkdir_p(output_dir) unless Dir.exist?(output_dir)
  File.write(output_path, cfn_template)
  puts "cfndsl template for #{dsl.name} written to #{output_path}"
  @cfndsl_compiled_path = output_path

  @sub_components.each { |subcomponent_compiler|
    puts "Rendering sub-component cfndsl: #{subcomponent_compiler.component_name}"
    subcomponent_compiler.compileCfnDsl out_format
  }

  @cfndsl_compiled = true

end
compileCloudFormation(format = 'yaml') click to toggle source
# File lib/cfhighlander.compiler.rb, line 146
def compileCloudFormation(format = 'yaml')

  dsl = @component.highlander_dsl

  # create out dir if not there
  @cfn_output_location = "#{@workdir}/out/#{format}" if @cfn_output_location.nil?
  output_dir = @cfn_output_location
  FileUtils.mkdir_p(output_dir) unless Dir.exist?(output_dir)


  # compile templates
  output_path = "#{output_dir}/#{@component_name}.compiled.#{format}"
  @cfn_template_paths << output_path
  # configure cfndsl


  # grab cfndsl model

  # 1st pass of cloudformation compiling - does the substacks normally
  model = evaluateCloudFormation
  @component.set_cfndsl_model model

  # compile sub-component templates
  @sub_components.each do |sub_component|
    sub_component.compileCloudFormation format
    @cfn_template_paths += sub_component.cfn_template_paths
    @lambda_src_paths += sub_component.lambda_src_paths
  end

  # 2nd pass will flatten any inlined components
  model = Cfhighlander::Util::CloudFormation.flattenCloudformation(
      component: @component
  )

  # write resulting cloud formation template
  if format == 'json'
    output_content = JSON.pretty_generate(model)
  elsif format == 'yaml'
    output_content = JSON.parse(model.to_json).to_yaml
  else
    raise StandardError, "#{format} not supported for cfn generation"
  end

  File.write(output_path, output_content)
  # `cfndsl #{@cfndsl_compiled_path} -p -f #{format} -o #{output_path} --disable-binding`
  puts "CloudFormation #{format.upcase} template for #{dsl.name} written to #{output_path}"

  return JSON.parse(model.to_json)

end
evaluateCloudFormation(format = 'yaml') click to toggle source
# File lib/cfhighlander.compiler.rb, line 132
def evaluateCloudFormation(format = 'yaml')
  #compile cfndsl templates first
  compileCfnDsl format unless @cfndsl_compiled

  # write config
  cfndsl_opts = []
  cfndsl_opts.push([:yaml, @config_yaml_path])

  # grab cfndsl model
  model = CfnDsl.eval_file_with_extras(@cfndsl_compiled_path, cfndsl_opts, false)
  @cfn_model = model
  return model
end
lambda_mock_resolve=(value) click to toggle source
# File lib/cfhighlander.compiler.rb, line 81
def lambda_mock_resolve=(value)
  @lambda_mock_resolve = value
  @sub_components.each { |scc| scc.lambda_mock_resolve = value }
end
processLambdas() click to toggle source
# File lib/cfhighlander.compiler.rb, line 216
def processLambdas()
  @component.highlander_dsl.lambda_functions_keys.each do |lfk|
    resolver = LambdaResolver.new(@component,
        lfk,
        @workdir,
        (not @silent_mode),
        @lambda_mock_resolve
    )
    @lambda_src_paths += resolver.generateSourceArchives if @process_lambdas
    resolver.mergeComponentConfig
  end

  @lambdas_processed = true

end
process_lambdas=(value) click to toggle source
# File lib/cfhighlander.compiler.rb, line 71
def process_lambdas=(value)
  @process_lambdas = value
  @sub_components.each { |scc| scc.process_lambdas = value }
end
silent_mode=(value) click to toggle source
# File lib/cfhighlander.compiler.rb, line 76
def silent_mode=(value)
  @silent_mode = value
  @sub_components.each { |scc| scc.silent_mode = value }
end
writeConfig(write_subcomponents_config = false) click to toggle source
# File lib/cfhighlander.compiler.rb, line 197
def writeConfig(write_subcomponents_config = false)
  @config_output_location = "#{@workdir}/out/config"
  config_yaml_path = "#{@config_output_location}/#{@component_name}.config.yaml"
  FileUtils.mkdir_p(@config_output_location) unless Dir.exist?(@config_output_location)

  File.write(config_yaml_path, @component.config.to_yaml)
  puts "Config for #{@component.highlander_dsl.name} written to #{config_yaml_path}"

  if write_subcomponents_config
    # compile sub-component templates
    @sub_components.each do |sub_component|
      sub_component.writeConfig write_subcomponents_config
    end
  end
  @config_written = true
  @config_yaml_path = config_yaml_path
  return @config_yaml_path
end