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