require 'erb' require 'hashie' module ITrigga module Generator class Generator attr_accessor :opts, :config # # Opts: (* is required) # :template_dir* - where to look for the .erb templates # :output_dir* - where to put the generated files # :config_file* - the yml config file that provides the hash of values passed to each template. Also the list of templates to render # :pattern - the file pattern name to be used for the template (eg which templates to render) # # All other params are made available to the templates # # All template files must end in .config # def initialize(opts = {}) raise "Config file does not exist / not accessible" unless (opts[:config_file] && File.exist?(opts[:config_file]) && File.readable?(opts[:config_file])) || opts[:config_file] == false raise "Template dir does not exist / not accessible" unless (opts[:template_dir] && File.exist?(opts[:template_dir]) && File.readable?(opts[:template_dir])) raise "Output dir does not exist / not accessible" unless (opts[:output_dir] && File.exist?(opts[:output_dir]) && File.writable?(opts[:output_dir])) # load and parse the config file if opts[:config_file] == false # we dont want to use a config file @config = Hashie::Mash.new else begin config = YAML::load(File.open(opts[:config_file],"r")) if config.kind_of?(Hash) @config = Hashie::Mash.new(config) else raise "Config file #{opts[:config_file]} did not serialize into a hash" end rescue Exception => e raise "Could not parse config file. Is is YAML format?. Exception was: #{e}" return false end end # if the pattern is not given set a default opts[:pattern] ||= ".*" @opts = Hashie::Mash.new(opts) include_constants end def generate # TODO : we merge in the entire config file mainly for the ssh monitoring scripts (need server dns & ports etc). Once config files are refactored this should change also if config.processes_to_start config.processes_to_start.each do |process| template_file_path = template_file(process) generate_template( template_file_path, config.merge(config.processes[process] || {}).merge(opts)) end else # we dont have a config file to tell use which templates to render, so we render all templates that match the extension files_in_template_dir.each {|f| generate_template( f, opts) } end end # # Returns the filenames of all the files in the template_dir that match the given regex # def files_in_template_dir(regex = opts.pattern) Dir[File.join(File.expand_path(opts.template_dir),"*.config")].reject{|f| File.basename(f).to_s.match(/.inactive$/) }.select{|f| File.basename(f).to_s.match(Regexp.new(regex.to_s)) } end # # Returns the absolute path to the template file # def template_file(filename) files_in_template_dir.find{|f| File.basename(f).match(/^#{filename}/)} end # # Returns the absolute path to the output file (which is the template file name without the .config) # def output_file(filename) File.expand_path( File.join(opts.output_dir,filename.gsub(".config","")) ) end # # Includes the output from all the methods defined in the constants.rb file into the hash to be available to the templates # def include_constants ITrigga::Generator.public_methods.select{|m| ITrigga::Generator.method(m).owner.to_s.match(/ITrigga::Generator/) }.each do |m| opts[m] = ITrigga::Generator.send(m) end end # # Generates the output file from the template file # def generate_template(template_file_path, template_variables = {}) begin # load template template = ERB.new( File.read(template_file_path) ) # render erb rendered_template = template.result(template_variables.send("binding")) # write output file File.open( output_file(File.basename(template_file_path)), "w" ){|f| f.write(rendered_template) } rescue Exception => e puts "Exception when rendering template '#{template_file_path}'" puts "Exception: #{e}" puts "template variables: #{template_variables.inspect}" puts e.backtrace throw e end end end end end