class Puppet::Generate::Type
Responsible for generating type definitions in Puppet
Public Class Methods
Finds the inputs for the generator. @param format [Symbol] The format to use. @param environment [Puppet::Node::Environment] The environment to search for inputs. Defaults to the current environment. @return [Array<Input>] Returns the array of inputs.
# File lib/puppet/generate/type.rb 115 def self.find_inputs(format = :pcore, environment = Puppet.lookup(:current_environment)) 116 Puppet.debug "Searching environment '#{environment.name}' for custom types." 117 inputs = [] 118 environment.modules.each do |mod| 119 directory = File.join(Puppet::Util::Autoload.cleanpath(mod.plugin_directory), 'puppet', 'type') 120 unless Puppet::FileSystem.exist?(directory) 121 Puppet.debug "Skipping '#{mod.name}' module because it contains no custom types." 122 next 123 end 124 125 Puppet.debug "Searching '#{mod.name}' module for custom types." 126 Dir.glob("#{directory}/*.rb") do |file| 127 next unless Puppet::FileSystem.file?(file) 128 Puppet.debug "Found custom type source file '#{file}'." 129 inputs << Input.new(mod.path, file, format) 130 end 131 end 132 133 # Sort the inputs by path 134 inputs.sort_by! { |input| input.path } 135 end
Generates files for the given inputs. If a file is up to date (newer than input) it is kept. If a file is out of date it is regenerated. If there is a file for a non existing output in a given output directory it is removed. If using input specific output removal must be made by hand if input is removed.
@param inputs [Array<Input>] The inputs to generate files for. @param outputdir [String, nil] the outputdir where all output should be generated, or nil if next to input @param force [Boolean] True to force the generation of the output files (skip up-to-date checks) or false if not. @return [void]
# File lib/puppet/generate/type.rb 147 def self.generate(inputs, outputdir = nil, force = false) 148 # remove files for non existing inputs 149 unless outputdir.nil? 150 filenames_to_keep = inputs.map {|i| i.output_name } 151 existing_files = Puppet::FileSystem.children(outputdir).map {|f| Puppet::FileSystem.basename(f) } 152 files_to_remove = existing_files - filenames_to_keep 153 files_to_remove.each do |f| 154 Puppet::FileSystem.unlink(File.join(outputdir, f)) 155 end 156 Puppet.notice(_("Removed output '%{files_to_remove}' for non existing inputs") % { files_to_remove: files_to_remove }) unless files_to_remove.empty? 157 end 158 159 if inputs.empty? 160 Puppet.notice _('No custom types were found.') 161 return nil 162 end 163 164 templates = {} 165 templates.default_proc = lambda { |hash, key| 166 raise _("template was not found at '%{key}'.") % { key: key } unless Puppet::FileSystem.file?(key) 167 template = ERB.new(File.read(key), nil, '-') 168 template.filename = key 169 template 170 } 171 172 up_to_date = true 173 Puppet.notice _('Generating Puppet resource types.') 174 inputs.each do |input| 175 if !force && input.up_to_date?(outputdir) 176 Puppet.debug "Skipping '#{input}' because it is up-to-date." 177 next 178 end 179 180 up_to_date = false 181 182 type_name = input.type_name 183 Puppet.debug "Loading custom type '#{type_name}' in '#{input}'." 184 begin 185 require input.path 186 rescue SystemExit 187 raise 188 rescue Exception => e 189 # Log the exception and move on to the next input 190 Puppet.log_exception(e, _("Failed to load custom type '%{type_name}' from '%{input}': %{message}") % { type_name: type_name, input: input, message: e.message }) 191 next 192 end 193 194 # HACK: there's no way to get a type without loading it (sigh); for now, just get the types hash directly 195 types ||= Puppet::Type.instance_variable_get('@types') 196 197 # Assume the type follows the naming convention 198 type = types[type_name] 199 unless type 200 Puppet.err _("Custom type '%{type_name}' was not defined in '%{input}'.") % { type_name: type_name, input: input } 201 next 202 end 203 204 # Create the model 205 begin 206 model = Models::Type::Type.new(type) 207 rescue Exception => e 208 # Move on to the next input 209 Puppet.log_exception(e, "#{input}: #{e.message}") 210 next 211 end 212 213 # Render the template 214 begin 215 result = model.render(templates[input.template_path]) 216 rescue Exception => e 217 Puppet.log_exception(e) 218 raise 219 end 220 221 # Write the output file 222 begin 223 effective_output_path = input.effective_output_path(outputdir) 224 Puppet.notice _("Generating '%{effective_output_path}' using '%{format}' format.") % { effective_output_path: effective_output_path, format: input.format } 225 FileUtils.mkdir_p(File.dirname(effective_output_path)) 226 Puppet::FileSystem.open(effective_output_path, nil, 'w:UTF-8') do |file| 227 file.write(result) 228 end 229 rescue Exception => e 230 Puppet.log_exception(e, _("Failed to generate '%{effective_output_path}': %{message}") % { effective_output_path: effective_output_path, message: e.message }) 231 # Move on to the next input 232 next 233 end 234 end 235 236 Puppet.notice _('No files were generated because all inputs were up-to-date.') if up_to_date 237 end