diff --git a/lib/puppet/provider/yumrepo/inifile.rb b/lib/puppet/provider/yumrepo/inifile.rb index 4feb0f72b..0abb3dc72 100644 --- a/lib/puppet/provider/yumrepo/inifile.rb +++ b/lib/puppet/provider/yumrepo/inifile.rb @@ -1,299 +1,301 @@ require 'puppet/util/inifile' Puppet::Type.type(:yumrepo).provide(:inifile) do desc <<-EOD Manage yum repo configurations by parsing yum INI configuration files. ## Fetching instances When fetching repo instances, directory entries in '/etc/yum/repos.d', '/etc/yum.repos.d', and the directory optionally specified by the reposdir key in '/etc/yum.conf' will be checked. If a given directory does not exist it will be ignored. In addition, all sections in '/etc/yum.conf' aside from 'main' will be created as sections. ## Storing instances When creating a new repository, a new section will be added in the first yum repo directory that exists. The custom directory specified by the '/etc/yum.conf' reposdir property is checked first, followed by '/etc/yum/repos.d', and then '/etc/yum.repos.d'. If none of these exist, the section will be created in '/etc/yum.conf'. EOD PROPERTIES = Puppet::Type.type(:yumrepo).validproperties # Retrieve all providers based on existing yum repositories # # @api public # @return [Array] providers generated from existing yum # repository definitions. def self.instances instances = [] virtual_inifile.each_section do |section| # Ignore the 'main' section in yum.conf since it's not a repository. next if section.name == "main" attributes_hash = {:name => section.name, :ensure => :present, :provider => :yumrepo} section.entries.each do |key, value| key = key.to_sym if valid_property?(key) attributes_hash[key] = value elsif key == :name attributes_hash[:descr] = value end end instances << new(attributes_hash) end instances end # Match catalog type instances to provider instances. # # @api public # @param resources [Array] Resources to prefetch. # @return [void] def self.prefetch(resources) repos = instances resources.keys.each do |name| if provider = repos.find { |repo| repo.name == name } resources[name].provider = provider end end end # Return a list of existing directories that could contain repo files. # # @api private # @param conf [String] Configuration file to look for directories in. # @param dirs [Array] Default locations for yum repos. # @return [Array] All present directories that may contain yum repo configs. def self.reposdir(conf='/etc/yum.conf', dirs=['/etc/yum.repos.d', '/etc/yum/repos.d']) reposdir = find_conf_value('reposdir', conf) - dirs << reposdir if reposdir + # Use directories in reposdir if they are set instead of default + dirs = reposdir.split(",").map(&:strip) if reposdir + dirs.select! { |dir| Puppet::FileSystem.exist?(dir) } if dirs.empty? Puppet.debug('No yum directories were found on the local filesystem') end dirs end # Used for testing only # @api private def self.clear @virtual = nil end # Helper method to look up specific values in ini style files. # # @api private # @param value [String] Value to look for in the configuration file. # @param conf [String] Configuration file to check for value. # @return [String] The value of a looked up key from the configuration file. def self.find_conf_value(value, conf='/etc/yum.conf') if Puppet::FileSystem.exist?(conf) file = Puppet::Util::IniConfig::PhysicalFile.new(conf) file.read if (main = file.get_section('main')) main[value] end end end # Enumerate all files that may contain yum repository configs. # '/etc/yum.conf' is always included. # # @api private # @return [Array def self.repofiles files = ["/etc/yum.conf"] reposdir.each do |dir| Dir.glob("#{dir}/*.repo").each do |file| files << file end end files end # Build a virtual inifile by reading in numerous .repo files into a single # virtual file to ease manipulation. # @api private # @return [Puppet::Util::IniConfig::File] The virtual inifile representing # multiple real files. def self.virtual_inifile unless @virtual @virtual = Puppet::Util::IniConfig::File.new self.repofiles.each do |file| @virtual.read(file) if Puppet::FileSystem.file?(file) end end return @virtual end # Is the given key a valid type property? # # @api private # @param key [String] The property to look up. # @return [Boolean] Returns true if the property is defined in the type. def self.valid_property?(key) PROPERTIES.include?(key) end # Return an existing INI section or create a new section in the default location # # The default location is determined based on what yum repo directories # and files are present. If /etc/yum.conf has a value for 'reposdir' then that # is preferred. If no such INI property is found then the first default yum # repo directory that is present is used. If no default directories exist then # /etc/yum.conf is used. # # @param name [String] Section name to lookup in the virtual inifile. # @return [Puppet::Util::IniConfig] The IniConfig section def self.section(name) result = self.virtual_inifile[name] # Create a new section if not found. unless result dirs = reposdir() if dirs.empty? # If no repo directories are present, default to using yum.conf. path = '/etc/yum.conf' else # The ordering of reposdir is [defaults, custom], and we want to use # the custom directory if present. path = File.join(dirs.last, "#{name}.repo") end result = self.virtual_inifile.add_section(name, path) end result end # Save all yum repository files and force the mode to 0644 # @api private # @return [void] def self.store inifile = self.virtual_inifile inifile.store target_mode = 0644 inifile.each_file do |file| current_mode = Puppet::FileSystem.stat(file).mode & 0777 unless current_mode == target_mode Puppet.info "changing mode of #{file} from %03o to %03o" % [current_mode, target_mode] Puppet::FileSystem.chmod(target_mode, file) end end end # Create a new section for the given repository and set all the specified # properties in the section. # # @api public # @return [void] def create @property_hash[:ensure] = :present new_section = current_section # We fetch a list of properties from the type, then iterate # over them, avoiding ensure. We're relying on .should to # check if the property has been set and should be modified, # and if so we set it in the virtual inifile. PROPERTIES.each do |property| next if property == :ensure if value = @resource.should(property) self.send("#{property}=", value) end end end # Does the given repository already exist? # # @api public # @return [Boolean] def exists? @property_hash[:ensure] == :present end # Mark the given repository section for destruction. # # The actual removal of the section will be handled by {#flush} after the # resource has been fully evaluated. # # @api public # @return [void] def destroy # Flag file for deletion on flush. current_section.destroy=(true) @property_hash.clear end # Finalize the application of the given resource. # # @api public # @return [void] def flush self.class.store end # Generate setters and getters for our INI properties. PROPERTIES.each do |property| # The ensure property uses #create, #exists, and #destroy we can't generate # meaningful setters and getters for this next if property == :ensure define_method(property) do get_property(property) end define_method("#{property}=") do |value| set_property(property, value) end end # Map the yumrepo 'descr' type property to the 'name' INI property. def descr if ! @property_hash.has_key?(:descr) @property_hash[:descr] = current_section['name'] end value = @property_hash[:descr] value.nil? ? :absent : value end def descr=(value) value = (value == :absent ? nil : value) current_section['name'] = value @property_hash[:descr] = value end private def get_property(property) if ! @property_hash.has_key?(property) @property_hash[property] = current_section[property.to_s] end value = @property_hash[property] value.nil? ? :absent : value end def set_property(property, value) value = (value == :absent ? nil : value) current_section[property.to_s] = value @property_hash[property] = value end def section(name) self.class.section(name) end def current_section self.class.section(self.name) end end