Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
185 changes: 185 additions & 0 deletions lib/puppet/provider/yumrepo/inifile.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,185 @@
require 'puppet/util/inifile'

Puppet::Type.type(:yumrepo).provide(:inifile) do
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Renamed to inifile from ruby here.

desc 'Manage yum repos'

PROPERTIES = Puppet::Type.type(:yumrepo).validproperties

# @return [Array<Puppet::Providers>] Return all the providers built up from
# discovered content on the local node.
def self.instances
instances = []
# Iterate over each section of our virtual file.
virtual_inifile.each_section do |section|
attributes_hash = {:name => section.name, :ensure => :present, :provider => :yumrepo}
# We need to build up a attributes hash
section.entries.each do |key, value|
key = key.to_sym
if valid_property?(key)
# We strip the values here to handle cases where distros set values
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added the stripping here to handle 'enabled = 1' cases.

# like enabled = 1 with spaces.
attributes_hash[key] = value.strip
end
end
instances << new(attributes_hash)
end
return instances
end

# @param resources [Array<Puppet::Resource>] Resources to prefetch.
# @return [Array<Puppet::Resource>] Resources with providers set.
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. Fail if none found.
# @param conf [String] Configuration file to look for directories in.
# @param dirs [Array] Default locations for yum repos.
# @return [Array] Directories that were found to exist on the node.
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

# We can't use the below due to Ruby 1.8.7
# dirs.select! { |dir| Puppet::FileSystem.exist?(dir) }
dirs.delete_if { |dir| ! Puppet::FileSystem.exist?(dir) }
if dirs.empty?
fail('No yum directories were found on the local filesystem')
else
return dirs
end
end

# Helper method to look up specific values in ini style files.
# @todo Migrate this into Puppet::Util::IniConfig.
# @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 File.exists?(conf)
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

After seeing @peterhuene's fix up yesterday at a76d681, I took a look at this pull. There are some file api accesses via the native ruby api (e.g. here) and some via the Puppet::FileSystem abstraction (e.g. line 50). For consistency's sake, we should probably scrub this pull to use that abstraction consistently. @apenney @adrienthebo thoughts?

contents = File.read(conf)
match = /^#{value}\s*=\s*(.*)/.match(contents)
end

return match.captures[0] if match
end

# Build a virtual inifile by reading in numerous .repo
# files into a single virtual file to ease manipulation.
# @return [Puppet::Util::IniConfig::File] The virtual inifile representing
# multiple real files.
def self.virtual_inifile
unless @virtual
@virtual = Puppet::Util::IniConfig::File.new
reposdir.each do |dir|
Dir.glob("#{dir}/*.repo").each do |file|
@virtual.read(file) if ::File.file?(file)
end
end
end
return @virtual
end

# @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

# We need to return a valid section from the larger virtual inifile here,
# which we do by first looking it up and then creating a new section for
# the appropriate name if none was found.
# @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
# Previously we did an .each on reposdir with the effect that we
# constantly created and overwrote result until the last entry of
# the array. This was done because the ordering is
# [defaults, custom] for reposdir and we want to use the custom if
# we have it and the defaults if not.
path = ::File.join(reposdir.last, "#{name}.repo")
Puppet.info("create new repo #{name} in file #{path}")
result = self.virtual_inifile.add_section(name, path)
end
result
end

# Here we store all modifications to disk, forcing the output file to 0644 if it differs.
# @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]
::File.chmod(target_mode, file)
end
end
end

# @return [void]
def create
@property_hash[:ensure] = :present

# 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)
section(@resource[:name])[property.to_s] = value
@property_hash[property] = value
end
end
end

# We don't actually destroy the file here, merely mark it for
# destruction in the section.
# @return [void]
def destroy
# Flag file for deletion on flush.
section(@resource[:name]).destroy=(true)

@property_hash.clear
end

# @return [void]
def flush
self.class.store
end

# @return [void]
def section(name)
self.class.section(name)
end

# Create all of our setters.
mk_resource_methods
PROPERTIES.each do |property|
# Exclude ensure, as we don't need to create an ensure=
next if property == :ensure
# Builds the property= method.
define_method("#{property.to_s}=") do |value|
section(@property_hash[:name])[property.to_s] = value
@property_hash[property] = value
end
end

# @return [Boolean] Returns true if ensure => present.
def exists?
@property_hash[:ensure] == :present
end

end
Loading