Behavior for custom classes
Doc string for properties that can be made ‘absent’
This map exists due to the use of hyphens and reserved words in the authorization schema.
This provides a mapping of puppet types to DirectoryService type strings.
False can be false/0/no and True can be true/1/yes in yum.
Override how parameters are handled so that we support the extra parameters that are used with defined resource types.
# File lib/puppet/type/component.rb, line 16 def [](param) return super if self.class.valid_parameter?(param) @extra_parameters[param.to_sym] end
Override how parameters are handled so that we support the extra parameters that are used with defined resource types.
# File lib/puppet/type/component.rb, line 23 def []=(param, value) return super if self.class.valid_parameter?(param) @extra_parameters[param.to_sym] = value end
# File lib/puppet/type/resources.rb, line 100 def able_to_ensure_absent?(resource) resource[:ensure] = :absent rescue ArgumentError, Puppet::Error err "The 'ensure' attribute on #{self[:name]} resources does not accept 'absent' as a value" false end
# File lib/puppet/provider/zone/solaris.rb, line 129 def add_cmd(cmd) @cmds = [] if @cmds.nil? @cmds << cmd end
# File lib/puppet/provider/service/upstart.rb, line 340 def add_default_start_to(text) text + "\nstart on runlevel [2,3,4,5]" end
# File lib/puppet/provider/zfs/zfs.rb, line 13 def add_properties properties = [] Puppet::Type.type(:zfs).validproperties.each do |property| next if property == :ensure if value = @resource[property] and value != "" properties << "-o" << "#{property}=#{value}" end end properties end
# File lib/puppet/vendor/semantic/spec/unit/semantic/dependency_spec.rb, line 147 def add_source_modules(name, versions, deps = {}) versions = Array(versions) releases = versions.map { |ver| create_release(source, name, ver, deps) } source.stub(:fetch).with(name).and_return(modules[name].concat(releases)) end
# File lib/puppet/provider/group/groupadd.rb, line 67 def addcmd if @resource.forcelocal? cmd = [command(:localadd)] @custom_environment = Puppet::Util::Libuser.getenv else cmd = [command(:add)] end if gid = @resource.should(:gid) unless gid == :absent cmd << flag(:gid) << gid end end cmd += check_allow_dup cmd << "-r" if @resource.system? and self.class.system_groups? cmd << @resource[:name] cmd end
# File lib/puppet/provider/maillist/mailman.rb, line 31 def aliases mailman = self.class.command(:mailman) name = self.name.downcase aliases = {name => "| #{mailman} post #{name}"} %w{admin bounces confirm join leave owner request subscribe unsubscribe}.each do |address| aliases["#{name}-#{address}"] = "| #{mailman} #{address} #{name}" end aliases end
Return a list of all applications (both legacy and Face applications), along with a summary
of their functionality.
@return [Array] An Array of Arrays. The outer array contains one entry per application; each
element in the outer array is a pair whose first element is a String containing the application name, and whose second element is a String containing the summary for that application.
# File lib/puppet/face/help.rb, line 136 def all_application_summaries() Puppet::Application.available_application_names.sort.inject([]) do |result, appname| next result if exclude_from_docs?(appname) if (is_face_app?(appname)) begin face = Puppet::Face[appname, :current] result << [appname, face.summary] rescue Puppet::Error result << [ "! #{appname}", "! Subcommand unavailable due to error. Check error logs." ] end else result << [appname, horribly_extract_summary_from(appname)] end end end
# File lib/puppet/type/cron.rb, line 282 def alpha %w{sunday monday tuesday wednesday thursday friday saturday} end
# File lib/puppet/type/file.rb, line 463 def ancestors ancestors = Pathname.new(self[:path]).enum_for(:ascend).map(&:to_s) ancestors.delete(self[:path]) ancestors end
# File lib/puppet/provider/package/aptitude.rb, line 11 def aptget(*args) args.flatten! # Apparently aptitude hasn't always supported a -q flag. args.delete("-q") if args.include?("-q") args.delete("--force-yes") if args.include?("--force-yes") output = aptitude(*args) # Yay, stupid aptitude doesn't throw an error when the package is missing. if args.include?(:install) and output =~ /Couldn't find any package/ raise Puppet::Error.new( "Could not find package #{self.name}" ) end end
# File lib/puppet/provider/scheduled_task/win32_taskscheduler.rb, line 52 def arguments task.parameters end
# File lib/puppet/provider/scheduled_task/win32_taskscheduler.rb, line 147 def arguments=(value) task.parameters = value end
##
Helper Methods ##
##
# File lib/puppet/provider/user/directoryservice.rb, line 482 def assert_full_pbkdf2_password missing = [:password, :salt, :iterations].select { |parameter| @resource[parameter].nil? } if !missing.empty? raise Puppet::Error, "OS X versions > 10\.7 use PBKDF2 password hashes, which requires all three of salt, iterations, and password hash. This resource is missing: #{missing.join(', ')}." end end
@param type [Type] the type the value must be an instance of @param value [Object] the value to assert
# File lib/puppet/functions/assert_type.rb, line 33 def assert_type(type, value) unless Puppet::Pops::Types::TypeCalculator.instance?(type,value) inferred_type = Puppet::Pops::Types::TypeCalculator.infer(value) if block_given? # Give the inferred type to allow richer comparisson in the given block (if generalized # information is lost). # value = yield(type, inferred_type) else # Do not give all the details - i.e. format as Integer, instead of Integer[n, n] for exact value, which # is just confusing. (OTOH: may need to revisit, or provide a better "type diff" output. # actual = Puppet::Pops::Types::TypeCalculator.generalize!(inferred_type) raise Puppet::ParseError, "assert_type(): Expected type #{type} does not match actual: #{actual}" end end value end
@param type_string [String] the type the value must be an instance of given in String form @param value [Object] the value to assert
# File lib/puppet/functions/assert_type.rb, line 55 def assert_type_s(type_string, value, &proc) t = Puppet::Pops::Types::TypeParser.new.parse(type_string) block_given? ? assert_type(t, value, &proc) : assert_type(t, value) end
# File lib/puppet/functions/each.rb, line 104 def asserted_enumerable(obj) unless enum = Puppet::Pops::Types::Enumeration.enumerator(obj) raise ArgumentError, ("#{self.class.name}(): wrong argument type (#{obj.class}; must be something enumerable.") end enum end
# File lib/puppet/functions/slice.rb, line 102 def asserted_slice_serving_size(pblock, slice_size) if pblock arity = pblock.arity serving_size = arity < 0 ? slice_size : arity else serving_size = 1 end if serving_size == 0 raise ArgumentError, "slice(): block must define at least one parameter. Block has 0." end unless serving_size == 1 || serving_size == slice_size raise ArgumentError, "slice(): block must define one parameter, or " + "the same number of parameters as the given size of the slice (#{slice_size}). Block has #{serving_size}; "+ pblock.parameter_names.join(', ') end serving_size end
Determine the user to write files as.
# File lib/puppet/type/file.rb, line 397 def asuser if self.should(:owner) and ! self.should(:owner).is_a?(Symbol) writeable = Puppet::Util::SUIDManager.asuser(self.should(:owner)) { FileTest.writable?(::File.dirname(self[:path])) } # If the parent directory is writeable, then we execute # as the user in question. Otherwise we'll rely on # the 'owner' property to do things. asuser = self.should(:owner) if writeable end asuser end
# File lib/puppet/provider/group/aix.rb, line 118 def attributes filter_attributes(getosinfo(false)) end
# File lib/puppet/provider/group/aix.rb, line 122 def attributes=(attr_hash) #self.class.validate(param, value) param = :attributes cmd = modifycmd({param => filter_attributes(attr_hash)}) if cmd begin execute(cmd) rescue Puppet::ExecutionFailure => detail raise Puppet::Error, "Could not set #{param} on #{@resource.class.name}[#{@resource.name}]: #{detail}", detail.backtrace end end end
# File lib/puppet/provider/macauthorization/macauthorization.rb, line 288 def auth_type if resource.should(:auth_type) != nil return resource.should(:auth_type) elsif self.exists? # this is here just for ralsh, so it can work out what type it is. if self.class.rights.has_key?(resource[:name]) return :right elsif self.class.rules.has_key?(resource[:name]) return :rule else raise Puppet::Error.new("#{resource[:name]} is unknown type.") end else raise Puppet::Error.new("auth_type required for new resources.") end end
# File lib/puppet/provider/macauthorization/macauthorization.rb, line 305 def auth_type=(value) @property_hash[:auth_type] = value end
# File lib/puppet/provider/user/user_role_add.rb, line 110 def auths user_attributes[:auths] if user_attributes end
Back up the existing file at a given prior to it being removed @api private @raise [Puppet::Error] if the file backup failed @return [void]
# File lib/puppet/type/file.rb, line 873 def backup_existing unless perform_backup raise Puppet::Error, "Could not back up; will not replace" end end
This method accepts an argument of a hex password hash, and base64 decodes it into a format that OS X 10.7 and 10.8 will store in the user’s plist.
# File lib/puppet/provider/user/directoryservice.rb, line 598 def base64_decode_string(value) Base64.decode64([[value].pack("H*")].pack("m").strip) end
# File lib/puppet/provider/scheduled_task/win32_taskscheduler.rb, line 411 def bitfield_from_days(days) bitfield = 0 days = [days] unless days.is_a?(Array) days.each do |day| # The special "day" of 'last' is represented by day "number" # 32. 'last' has the special meaning of "the last day of the # month", no matter how many days there are in the month. day = 32 if day == 'last' integer_day = Integer(day) self.fail "Day must be specified as an integer in the range 1-31, or as 'last'" unless integer_day = day.to_f and integer_day.between?(1,32) bitfield |= 1 << integer_day - 1 end bitfield end
# File lib/puppet/provider/scheduled_task/win32_taskscheduler.rb, line 430 def bitfield_from_days_of_week(days_of_week) bitfield = 0 days_of_week = [days_of_week] unless days_of_week.is_a?(Array) days_of_week.each do |day_of_week| bitfield |= day_of_week_name_to_constant(day_of_week) end bitfield end
# File lib/puppet/provider/scheduled_task/win32_taskscheduler.rb, line 397 def bitfield_from_months(months) bitfield = 0 months = [months] unless months.is_a?(Array) months.each do |month| integer_month = Integer(month) rescue nil self.fail 'Month must be specified as an integer in the range 1-12' unless integer_month == month.to_f and integer_month.between?(1,12) bitfield |= scheduler_months[integer_month - 1] end bitfield end
# File lib/puppet/type/file.rb, line 412 def bucket return @bucket if @bucket backup = self[:backup] return nil unless backup return nil if backup =~ /^\./ unless catalog or backup == "puppet" fail "Can not find filebucket for backups without a catalog" end unless catalog and filebucket = catalog.resource(:filebucket, backup) or backup == "puppet" fail "Could not find filebucket #{backup} specified in backup" end return default_bucket unless filebucket @bucket = filebucket.bucket @bucket end
# File lib/puppet/provider/user/user_role_add.rb, line 138 def build_keys_cmd(keys_hash) cmd = [] keys_hash.each do |k,v| cmd << "-K" << "#{k}=#{v}" end cmd end
Adds log and spare
# File lib/puppet/provider/zpool/zpool.rb, line 69 def build_named(name) if prop = @resource[name.intern] [name] + prop.collect { |p| p.split(' ') }.flatten else [] end end
builds up the vdevs for create command
# File lib/puppet/provider/zpool/zpool.rb, line 88 def build_vdevs if disk = @resource[:disk] disk.collect { |d| d.split(' ') }.flatten elsif mirror = @resource[:mirror] handle_multi_arrays("mirror", mirror) elsif raidz = @resource[:raidz] handle_multi_arrays(raidzarity, raidz) end end
@return [Boolean] If the current file can be backed up and needs to be backed up.
# File lib/puppet/type/file.rb, line 832 def can_backup?(type) if type == "directory" and not force? # (#18110) Directories cannot be removed without :force, so it doesn't # make sense to back them up. false else true end end
Make output a bit prettier
# File lib/puppet/type/augeas.rb, line 180 def change_to_s(currentvalue, newvalue) "executed successfully" end
# File lib/puppet/type/resources.rb, line 90 def check(resource) @checkmethod ||= "#{self[:name]}_check" @hascheck ||= respond_to?(@checkmethod) if @hascheck return send(@checkmethod, resource) else return true end end
# File lib/puppet/provider/group/groupadd.rb, line 52 def check_allow_dup # We have to manually check for duplicates when using libuser # because by default duplicates are allowed. This check is # to ensure consistent behaviour of the useradd provider when # using both useradd and luseradd if not @resource.allowdupe? and @resource.forcelocal? if @resource.should(:gid) and findgroup('gid', @resource.should(:gid).to_s) raise(Puppet::Error, "GID #{@resource.should(:gid).to_s} already exists, use allowdupe to force group creation") end elsif @resource.allowdupe? and not @resource.forcelocal? return ["-o"] end [] end
# File lib/puppet/provider/user/useradd.rb, line 136 def check_manage_expiry cmd = [] if @resource[:expiry] and not @resource.forcelocal? cmd << "-e #{@resource[:expiry]}" end cmd end
# File lib/puppet/provider/user/useradd.rb, line 126 def check_manage_home cmd = [] if @resource.managehome? and not @resource.forcelocal? cmd << "-m" elsif not @resource.managehome? and Facter.value(:osfamily) == 'RedHat' cmd << "-M" end cmd end
(Un)install may “fail” because the package requested a reboot, the system requested a reboot, or something else entirely. Reboot requests mean the package was installed successfully, but we warn since we don’t have a good reboot strategy.
# File lib/puppet/provider/package/windows.rb, line 86 def check_result(hr) operation = resource[:ensure] == :absent ? 'uninstall' : 'install' case hr when self.class::ERROR_SUCCESS # yeah when self.class::ERROR_SUCCESS_REBOOT_INITIATED warning("The package #{operation}ed successfully and the system is rebooting now.") when self.class::ERROR_SUCCESS_REBOOT_REQUIRED warning("The package #{operation}ed successfully, but the system must be rebooted.") else raise Puppet::Util::Windows::Error.new("Failed to #{operation}", hr) end end
# File lib/puppet/provider/user/useradd.rb, line 145 def check_system_users if self.class.system_users? and resource.system? ["-r"] else [] end end
# File lib/puppet/provider/user/useradd.rb, line 117 def check_valid_shell unless File.exists?(@resource.should(:shell)) raise(Puppet::Error, "Shell #{@resource.should(:shell)} must exist") end unless File.executable?(@resource.should(:shell).to_s) raise(Puppet::Error, "Shell #{@resource.should(:shell)} must be executable") end end
Verify that we have the executable
# File lib/puppet/provider/exec/windows.rb, line 35 def checkexe(command) exe = extractexe(command) if absolute_path?(exe) if !Puppet::FileSystem.exist?(exe) raise ArgumentError, "Could not find command '#{exe}'" elsif !File.file?(exe) raise ArgumentError, "'#{exe}' is a #{File.ftype(exe)}, not a file" end return end if resource[:path] Puppet::Util.withenv :PATH => resource[:path].join(File::PATH_SEPARATOR) do return if which(exe) end end raise ArgumentError, "Could not find command '#{exe}'" end
A derivative of DPKG; this is how most people actually manage Debian boxes, and the only thing that differs is that it can install packages from remote sites.
# File lib/puppet/provider/package/apt.rb, line 29 def checkforcdrom have_cdrom = begin !!(File.read("/etc/apt/sources.list") =~ /^[^#]*cdrom:/) rescue # This is basically pathological... false end if have_cdrom and @resource[:allowcdrom] != :true raise Puppet::Error, "/etc/apt/sources.list contains a cdrom source; not installing. Use 'allowcdrom' to override this failure." end end
Defines an instance method within a class
# File lib/puppet/util/metaid.rb, line 17 def class_def(name, &blk) class_eval { define_method name, &blk } end
clean facts for host
# File lib/puppet/face/node/clean.rb, line 80 def clean_cached_facts(node) Puppet::Node::Facts.indirection.destroy(node) Puppet.info "#{node}'s facts removed" end
clean cached node host
# File lib/puppet/face/node/clean.rb, line 86 def clean_cached_node(node) Puppet::Node.indirection.destroy(node) Puppet.info "#{node}'s cached node removed" end
clean signed cert for host
# File lib/puppet/face/node/clean.rb, line 69 def clean_cert(node) if Puppet::SSL::CertificateAuthority.ca? Puppet::Face[:ca, :current].revoke(node) Puppet::Face[:ca, :current].destroy(node) Puppet.info "#{node} certificates removed from ca" else Puppet.info "Not managing #{node} certs as this host is not a CA" end end
clean node reports for host
# File lib/puppet/face/node/clean.rb, line 92 def clean_reports(node) Puppet::Transaction::Report.indirection.destroy(node) Puppet.info "#{node}'s reports removed" end
clean storeconfig for node
# File lib/puppet/face/node/clean.rb, line 98 def clean_storeconfigs(node, do_unexport=false) return unless Puppet[:storeconfigs] && Puppet.features.rails? require 'puppet/rails' Puppet::Rails.connect unless rails_node = Puppet::Rails::Host.find_by_name(node) Puppet.notice "No entries found for #{node} in storedconfigs." return end if do_unexport unexport(rails_node) Puppet.notice "Force #{node}'s exported resources to absent" Puppet.warning "Please wait until all other hosts have checked out their configuration before finishing the cleanup with:" Puppet.warning "$ puppet node clean #{node}" else rails_node.destroy Puppet.notice "#{node} storeconfigs removed" end end
# File lib/puppet/face/node/clean.rb, line 60 def cleanup(node, unexport) clean_cert(node) clean_cached_facts(node) clean_cached_node(node) clean_reports(node) clean_storeconfigs(node, unexport) end
# File lib/puppet/provider/scheduled_task/win32_taskscheduler.rb, line 39 def clear_task @task = nil @triggers = nil end
# File lib/puppet/util/log/destinations.rb, line 6 def close Syslog.close end
# File lib/puppet/provider/augeas/augeas.rb, line 193 def close_augeas if @aug @aug.close debug("Closed the augeas connection") @aug = nil end end
# File lib/puppet/provider/scheduled_task/win32_taskscheduler.rb, line 48 def command task.application_name end
# File lib/puppet/provider/scheduled_task/win32_taskscheduler.rb, line 143 def command=(value) task.application_name = value end
# File lib/puppet/provider/user/windows_adsi.rb, line 64 def comment user['Description'] end
# File lib/puppet/provider/user/windows_adsi.rb, line 68 def comment=(value) user['Description'] = value end
# File lib/puppet/provider/service/upstart.rb, line 305 def comment_start_block_in(text) parens = 0 text.lines.map do |line| if line.match(START_ON) || parens > 0 # If there are more opening parens than closing parens, we need to comment out a multiline 'start on' stanza parens += unbalanced_parens_on(remove_trailing_comments_from(line)) "#" + line else line end end.join('') end
Turn the results of getconfig into status information.
# File lib/puppet/provider/zone/solaris.rb, line 316 def config_status config = getconfig result = {} result[:autoboot] = config[:autoboot] ? config[:autoboot].intern : :true result[:pool] = config[:pool] result[:shares] = config[:shares] if dir = config["inherit-pkg-dir"] result[:inherit] = dir.collect { |dirs| dirs[:dir] } end if datasets = config["dataset"] result[:dataset] = datasets.collect { |dataset| dataset[:name] } end result[:iptype] = config[:'ip-type'] if config[:'ip-type'] if net = config["net"] result[:ip] = net.collect do |params| if params[:defrouter] "#{params[:physical]}:#{params[:address]}:#{params[:defrouter]}" elsif params[:address] "#{params[:physical]}:#{params[:address]}" else params[:physical] end end end result end
Perform all of our configuration steps.
# File lib/puppet/provider/zone/solaris.rb, line 111 def configure self.fail "Path is required" unless @resource[:path] arr = ["create -b #{@resource[:create_args]}"] # Then perform all of our configuration steps. It's annoying # that we need this much internal info on the resource. self.resource.properties.each do |property| next unless my_properties.include? property.name method = (property.name.to_s + '_conf').intern arr << self.send(method ,@resource[property.name]) unless property.safe_insync?(properties[property.name]) end setconfig(arr.join("\n")) end
# File lib/puppet/provider/mcx/mcxcontent.rb, line 91 def content ds_parms = get_dsparams self.class.mcxexport(ds_parms[:ds_type], ds_parms[:ds_name]) end
# File lib/puppet/provider/mcx/mcxcontent.rb, line 97 def content=(value) # dscl localhost -mcximport ds_parms = get_dsparams mcximport(ds_parms[:ds_type], ds_parms[:ds_name], resource[:content]) end
# File lib/puppet/type/tidy.rb, line 114 def convert(unit, multi) if num = AgeConvertors[unit] return num * multi else self.fail "Invalid age unit '#{unit}'" end end
# File lib/puppet/provider/macauthorization/macauthorization.rb, line 214 def convert_plist_to_native_attributes(propertylist) # This mainly converts the keys from the puppet attributes to the # 'native' ones, but also enforces that the keys are all Strings # rather than Symbols so that any merges of the resultant Hash are # sane. The exception is booleans, where we coerce to a proper bool # if they come in as a symbol. newplist = {} propertylist.each_pair do |key, value| next if key == :ensure # not part of the auth db schema. next if key == :auth_type # not part of the auth db schema. case value when true, :true value = true when false, :false value = false end new_key = key if PuppetToNativeAttributeMap.has_key?(key) new_key = PuppetToNativeAttributeMap[key].to_s elsif not key.is_a?(String) new_key = key.to_s end newplist[new_key] = value end newplist end
# File lib/puppet/provider/zfs/zfs.rb, line 24 def create zfs *([:create] + add_properties + [@resource[:name]]) end
Create the new user with dscl
# File lib/puppet/provider/user/directoryservice.rb, line 508 def create_new_user(username) dscl '.', '-create', "/Users/#{username}" end
# File lib/puppet/vendor/semantic/spec/unit/semantic/dependency_spec.rb, line 5 def create_release(source, name, version, deps = {}) Semantic::Dependency::ModuleRelease.new( source, name, Semantic::Version.parse(version), Hash[deps.map { |k, v| [k, Semantic::VersionRange.parse(v) ] }] ) end
# File lib/puppet/provider/user/user_role_add.rb, line 98 def create_role if exists? and !is_role? run(transition("role"), "transition user to") else run(addcmd, "create role") end end
# File lib/puppet/provider/zpool/zpool.rb, line 59 def current_pool @current_pool = process_zpool_data(get_pool_data) unless (defined?(@current_pool) and @current_pool) @current_pool end
# File lib/puppet/provider/yumrepo/inifile.rb, line 300 def current_section self.class.section(self.name) end
returns the full path to the current daemon directory note that this path can be overriden in the resource definition
# File lib/puppet/provider/service/daemontools.rb, line 111 def daemon File.join(resource[:path], resource[:name]) end
ActiveSupport 2.3.x mixes in a dangerous method that can cause rspec to fork bomb and other strange things like that.
# File lib/puppet/util/monkey_patches.rb, line 64 def daemonize raise NotImplementedError, "Kernel.daemonize is too dangerous, please don't try to use it." end
# File lib/puppet/util/instrumentation/listeners/log.rb, line 20 def data @last_logs.dup end
# File lib/puppet/network/formats.rb, line 41 def data_to_instance(klass, data) return data if data.is_a?(klass) unless data.is_a? Hash raise Puppet::Network::FormatHandler::FormatError, "Serialized YAML did not contain a valid instance of #{klass}" end klass.from_data_hash(data) end
# File lib/puppet/provider/scheduled_task/win32_taskscheduler.rb, line 532 def day_of_week_constant_to_name(constant) case constant when Win32::TaskScheduler::SUNDAY; 'sun' when Win32::TaskScheduler::MONDAY; 'mon' when Win32::TaskScheduler::TUESDAY; 'tues' when Win32::TaskScheduler::WEDNESDAY; 'wed' when Win32::TaskScheduler::THURSDAY; 'thurs' when Win32::TaskScheduler::FRIDAY; 'fri' when Win32::TaskScheduler::SATURDAY; 'sat' end end
# File lib/puppet/provider/scheduled_task/win32_taskscheduler.rb, line 544 def day_of_week_name_to_constant(name) case name when 'sun'; Win32::TaskScheduler::SUNDAY when 'mon'; Win32::TaskScheduler::MONDAY when 'tues'; Win32::TaskScheduler::TUESDAY when 'wed'; Win32::TaskScheduler::WEDNESDAY when 'thurs'; Win32::TaskScheduler::THURSDAY when 'fri'; Win32::TaskScheduler::FRIDAY when 'sat'; Win32::TaskScheduler::SATURDAY end end
# File lib/puppet/provider/scheduled_task/win32_taskscheduler.rb, line 453 def days_from_bitfield(bitfield) days = [] i = 0 while bitfield > 0 if bitfield & 1 > 0 # Day 32 has the special meaning of "the last day of the # month", no matter how many days there are in the month. days << (i == 31 ? 'last' : i + 1) end bitfield = bitfield >> 1 i += 1 end days end
# File lib/puppet/provider/scheduled_task/win32_taskscheduler.rb, line 471 def days_of_week_from_bitfield(bitfield) days_of_week = [] scheduler_days_of_week.each do |day_of_week| if bitfield & day_of_week != 0 days_of_week << day_of_week_constant_to_name(day_of_week) end end days_of_week end
# File lib/puppet/network/formats.rb, line 107 def decode(data) Zlib::Inflate.inflate(Base64.decode64(data)) end
# File lib/puppet/provider/service/src.rb, line 49 def default_action "once" end
# File lib/puppet/type/file.rb, line 434 def default_bucket Puppet::Type.type(:filebucket).mkdefaultbucket.bucket end
@api private
# File lib/puppet/provider/service/openbsd.rb, line 256 def default_disabled? line = File.readlines(self.class.rcconf).find {|l| l =~ /#{rcvar_name}/ } self.class.parse_rc_line(line) == 'NO' end
# File lib/puppet/provider/service/src.rb, line 45 def default_runlevel "2" end
# File lib/puppet/provider/group/windows_adsi.rb, line 85 def delete Puppet::Util::Windows::ADSI::Group.delete(@resource[:name]) @deleted = true end
# File lib/puppet/provider/group/aix.rb, line 89 def deletecmd [self.class.command(:delete)] + self.get_ia_module_args + [@resource[:name]] end
# File lib/puppet/type/tidy.rb, line 205 def depthfirst? true end
Map the yumrepo ‘descr’ type property to the ‘name’ INI property.
# File lib/puppet/provider/yumrepo/inifile.rb, line 266 def descr if ! @property_hash.has_key?(:descr) @property_hash[:descr] = current_section['name'] end value = @property_hash[:descr] value.nil? ? :absent : value end
# File lib/puppet/provider/yumrepo/inifile.rb, line 274 def descr=(value) value = (value == :absent ? nil : value) current_section['name'] = value @property_hash[:descr] = value end
# File lib/puppet/provider/zfs/zfs.rb, line 28 def destroy zfs(:destroy, @resource[:name]) end
utility methods below
# File lib/puppet/provider/macauthorization/macauthorization.rb, line 134 def destroy_right security "authorizationdb", :remove, resource[:name] end
# File lib/puppet/provider/macauthorization/macauthorization.rb, line 138 def destroy_rule authdb = Plist::parse_xml(AuthDB) authdb_rules = authdb["rules"].dup if authdb_rules[resource[:name]] begin authdb["rules"].delete(resource[:name]) Plist::Emit.save_plist(authdb, AuthDB) rescue Errno::EACCES => e raise Puppet::Error.new("Error saving #{AuthDB}: #{e}", e) end end end
Given a blob of output from `nimclient -o showres` and a package name, this method checks to see if there are multiple versions of the package available on the lpp_source. If there are, the method returns
(where package_type is one of :installp or :rpm).
If there is only one version of the package available, it returns [package_type, nil], because the caller doesn’t need to pass the version string to the command-line command if there is only one version available. If the package is not available at all, the method simply returns nil (instead of a tuple).
# File lib/puppet/provider/package/nim.rb, line 258 def determine_latest_version(showres_output, package_name) packages = parse_showres_output(showres_output) unless packages.has_key?(package_name) return nil end if (packages[package_name].count == 1) version = packages[package_name].keys[0] return packages[package_name][version], nil else versions = packages[package_name].keys latest_version = (versions.sort { |a, b| Puppet::Util::Package.versioncmp(b, a) })[0] return packages[package_name][latest_version], latest_version end end
# File lib/puppet/provider/package/nim.rb, line 273 def determine_package_type(showres_output, package_name, version) packages = parse_showres_output(showres_output) unless (packages.has_key?(package_name) and packages[package_name].has_key?(version)) return nil end packages[package_name][version] end
Return the appropriate digest algorithm with fallbacks in case puppet defaults have not been initialized.
# File lib/puppet/type/file/checksum.rb, line 40 def digest_algorithm value || Puppet[:digest_algorithm].to_sym end
# File lib/puppet/provider/ssh_authorized_key/parsed.rb, line 37 def dir_perm 0700 end
# File lib/puppet/provider/service/systemd.rb, line 24 def disable output = systemctl(:disable, @resource[:name]) rescue Puppet::ExecutionFailure raise Puppet::Error, "Could not disable #{self.name}: #{output}", $!.backtrace end
# File lib/puppet/provider/service/upstart.rb, line 273 def disable_post_0_9_0(over_text) write_script_to(overscript, ensure_disabled_with_manual(over_text)) end
# File lib/puppet/provider/service/upstart.rb, line 264 def disable_pre_0_6_7(script_text) disabled_script = comment_start_block_in(script_text) write_script_to(initscript, disabled_script) end
# File lib/puppet/provider/service/upstart.rb, line 269 def disable_pre_0_9_0(script_text) write_script_to(initscript, ensure_disabled_with_manual(script_text)) end
# File lib/puppet/provider/package/yum.rb, line 178 def disablerepo scan_options(resource[:install_options], '--disablerepo') end
Actually execute the augeas changes.
# File lib/puppet/provider/augeas/augeas.rb, line 439 def do_execute_changes commands = parse_commands(resource[:changes]) commands.each do |cmd_array| fail("invalid command #{cmd_array.join[" "]}") if cmd_array.length < 2 command = cmd_array[0] cmd_array.shift begin case command when "set" debug("sending command '#{command}' with params #{cmd_array.inspect}") rv = aug.set(cmd_array[0], cmd_array[1]) fail("Error sending command '#{command}' with params #{cmd_array.inspect}") if (!rv) when "setm" if aug.respond_to?(command) debug("sending command '#{command}' with params #{cmd_array.inspect}") rv = aug.setm(cmd_array[0], cmd_array[1], cmd_array[2]) fail("Error sending command '#{command}' with params #{cmd_array.inspect}") if (rv == -1) else fail("command '#{command}' not supported in installed version of ruby-augeas") end when "rm", "remove" debug("sending command '#{command}' with params #{cmd_array.inspect}") rv = aug.rm(cmd_array[0]) fail("Error sending command '#{command}' with params #{cmd_array.inspect}") if (rv == -1) when "clear" debug("sending command '#{command}' with params #{cmd_array.inspect}") rv = aug.clear(cmd_array[0]) fail("Error sending command '#{command}' with params #{cmd_array.inspect}") if (!rv) when "clearm" # Check command exists ... doesn't currently in ruby-augeas 0.4.1 if aug.respond_to?(command) debug("sending command '#{command}' with params #{cmd_array.inspect}") rv = aug.clearm(cmd_array[0], cmd_array[1]) fail("Error sending command '#{command}' with params #{cmd_array.inspect}") if (!rv) else fail("command '#{command}' not supported in installed version of ruby-augeas") end when "insert", "ins" label = cmd_array[0] where = cmd_array[1] path = cmd_array[2] case where when "before"; before = true when "after"; before = false else fail("Invalid value '#{where}' for where param") end debug("sending command '#{command}' with params #{[label, where, path].inspect}") rv = aug.insert(path, label, before) fail("Error sending command '#{command}' with params #{cmd_array.inspect}") if (rv == -1) when "defvar" debug("sending command '#{command}' with params #{cmd_array.inspect}") rv = aug.defvar(cmd_array[0], cmd_array[1]) fail("Error sending command '#{command}' with params #{cmd_array.inspect}") if (!rv) when "defnode" debug("sending command '#{command}' with params #{cmd_array.inspect}") rv = aug.defnode(cmd_array[0], cmd_array[1], cmd_array[2]) fail("Error sending command '#{command}' with params #{cmd_array.inspect}") if (!rv) when "mv", "move" debug("sending command '#{command}' with params #{cmd_array.inspect}") rv = aug.mv(cmd_array[0], cmd_array[1]) fail("Error sending command '#{command}' with params #{cmd_array.inspect}") if (rv == -1) else fail("Command '#{command}' is not supported") end rescue SystemExit,NoMemoryError raise rescue Exception => e fail("Error sending command '#{command}' with params #{cmd_array.inspect}/#{e.message}") end end end
# File lib/puppet/functions/match.rb, line 97 def do_match(s, regexp) if result = regexp.match(s) result.to_a end end
# File lib/puppet/provider/scheduled_task/win32_taskscheduler.rb, line 257 def dummy_time_trigger now = Time.now { 'flags' => 0, 'random_minutes_interval' => 0, 'end_day' => 0, 'end_year' => 0, 'minutes_interval' => 0, 'end_month' => 0, 'minutes_duration' => 0, 'start_year' => now.year, 'start_month' => now.month, 'start_day' => now.day, 'start_hour' => now.hour, 'start_minute' => now.min, 'trigger_type' => Win32::TaskScheduler::ONCE, } end
# File lib/puppet/face/parser.rb, line 124 def dump_parse(source, filename, options, show_filename = true) output = "" dumper = Puppet::Pops::Model::ModelTreeDumper.new evaluating_parser = Puppet::Pops::Parser::EvaluatingParser.new begin if options[:validate] parse_result = evaluating_parser.parse_string(source, filename) else # side step the assert_and_report step parse_result = evaluating_parser.parser.parse_string(source) end if show_filename output << "--- #{filename}" end output << dumper.dump(parse_result) << "\n" rescue Puppet::ParseError => detail if show_filename Puppet.err("--- #{filename}") end Puppet.err(detail.message) "" end end
# File lib/puppet/provider/service/systemd.rb, line 49 def enable output = systemctl("enable", @resource[:name]) rescue Puppet::ExecutionFailure raise Puppet::Error, "Could not enable #{self.name}: #{output}", $!.backtrace end
# File lib/puppet/provider/service/upstart.rb, line 250 def enable_post_0_9_0(script_text, over_text) over_text = remove_manual_from(over_text) if enabled_post_0_9_0?(script_text, over_text) == :false if script_text.match(START_ON) over_text << extract_start_on_block_from(script_text) else over_text << "\nstart on runlevel [2,3,4,5]" end end write_script_to(overscript, over_text) end
# File lib/puppet/provider/service/upstart.rb, line 232 def enable_pre_0_9_0(text) # We also need to remove any manual stanzas to ensure that it is enabled text = remove_manual_from(text) if enabled_pre_0_9_0?(text) == :false enabled_script = if text.match(COMMENTED_START_ON) uncomment_start_block_in(text) else add_default_start_to(text) end else enabled_script = text end write_script_to(initscript, enabled_script) end
# File lib/puppet/provider/scheduled_task/win32_taskscheduler.rb, line 44 def enabled task.flags & Win32::TaskScheduler::DISABLED == 0 ? :true : :false end
# File lib/puppet/provider/scheduled_task/win32_taskscheduler.rb, line 155 def enabled=(value) if value == :true task.flags = task.flags & ~Win32::TaskScheduler::DISABLED else task.flags = task.flags | Win32::TaskScheduler::DISABLED end end
# File lib/puppet/provider/service/systemd.rb, line 30 def enabled? begin systemctl("is-enabled", @resource[:name]) rescue Puppet::ExecutionFailure return :false end :true end
# File lib/puppet/provider/service/upstart.rb, line 209 def enabled_post_0_9_0?(script_text, over_text) # This version has manual stanzas and override files # So we check to see if an uncommented start on or manual stanza is the last one in the # conf file and any override files. The last one in the file wins. enabled = :false script_text.each_line do |line| if line.match(START_ON) enabled = :true elsif line.match(MANUAL) enabled = :false end end over_text.each_line do |line| if line.match(START_ON) enabled = :true elsif line.match(MANUAL) enabled = :false end end if over_text enabled end
# File lib/puppet/provider/service/upstart.rb, line 185 def enabled_pre_0_6_7?(script_text) # Upstart version < 0.6.7 means no manual stanza. if script_text.match(START_ON) return :true else return :false end end
# File lib/puppet/provider/service/upstart.rb, line 194 def enabled_pre_0_9_0?(script_text) # Upstart version < 0.9.0 means no override files # So we check to see if an uncommented start on or manual stanza is the last one in the file # The last one in the file wins. enabled = :false script_text.each_line do |line| if line.match(START_ON) enabled = :true elsif line.match(MANUAL) enabled = :false end end enabled end
# File lib/puppet/provider/package/yum.rb, line 174 def enablerepo scan_options(resource[:install_options], '--enablerepo') end
# File lib/puppet/network/formats.rb, line 111 def encode(text) requiring_zlib do Base64.encode64(Zlib::Deflate.deflate(text, Zlib::BEST_COMPRESSION)) end end
# File lib/puppet/provider/service/upstart.rb, line 344 def ensure_disabled_with_manual(text) remove_manual_from(text) + "\nmanual" end
Matches given Array against given pattern and returns an Array with mapped match results.
@param array [Array<String>] the array of strings to match @param pattern [String, Regexp, Puppet::Pops::Types::PPatternType, Puppet::Pops::PRegexpType, Array] the pattern @return [Array<Array<String, nil>>] Array with matches (see {match}), non matching entries produce a nil entry
# File lib/puppet/functions/match.rb, line 56 def enumerable_match(array, pattern) array.map {|s| match(s, pattern) } end
# File lib/puppet/face/node/clean.rb, line 146 def environment @environment ||= Puppet.lookup(:current_environment) end
# File lib/puppet/functions/epp.rb, line 50 def epp(scope, path, parameters = nil) Puppet::Pops::Evaluator::EppEvaluator.epp(scope, path, scope.compiler.environment, parameters) end
# File lib/puppet/face/help.rb, line 117 def erb(name) template = (Pathname(__FILE__).dirname + "help" + name) erb = ERB.new(template.read, nil, '-') erb.filename = template.to_s return erb end
# File lib/puppet/provider/service/freebsd.rb, line 16 def error(msg) raise Puppet::Error, msg end
Create any children via recursion or whatever.
# File lib/puppet/type/file.rb, line 457 def eval_generate return [] unless self.recurse? recurse end
This should absolutely be a private method, but for some reason it appears that you can't use the 'private' keyword inside of a Face definition. See #14205.
private :#horribly_extract_summary_from
# File lib/puppet/face/help.rb, line 176 def exclude_from_docs?(appname) %w{face_base indirection_base}.include? appname end
# File lib/puppet/provider/package/pkg.rb, line 197 def exec_cmd(*cmd) output = Puppet::Util::Execution.execute(cmd, :failonfail => false, :combine => true) {:out => output, :exit => $CHILD_STATUS.exitstatus} end
Required workaround, since SELinux policy prevents setsebool from writing to any files, even tmp, preventing the standard ‘setsebool(“…”)’ construct from working.
# File lib/puppet/provider/selboolean/getsetsebool.rb, line 36 def execoutput (cmd) output = '' begin execpipe(cmd) do |out| output = out.readlines.join('').chomp! end rescue Puppet::ExecutionFailure raise Puppet::ExecutionFailure, output.split("\n")[0], $!.backtrace end output end
# File lib/puppet/provider/augeas/augeas.rb, line 417 def execute_changes # Workaround Augeas bug where changing the save mode doesn't trigger a # reload of the previously saved file(s) when we call Augeas#load @aug.match("/augeas/events/saved").each do |file| @aug.rm("/augeas#{@aug.get(file)}/mtime") end # Reload augeas, and execute the changes for real set_augeas_save_mode(SAVE_OVERWRITE) if versioncmp(get_augeas_version, "0.3.6") >= 0 @aug.load do_execute_changes unless @aug.save print_put_errors fail("Save failed, see debug") end :executed ensure close_augeas end
Does the file currently exist? Just checks for whether we have a stat
# File lib/puppet/type/file.rb, line 440 def exist? stat ? true : false end
# File lib/puppet/provider/service/launchd.rb, line 227 def exists? Puppet.debug("Puppet::Provider::Launchd:Ensure for #{@property_hash[:name]}: #{@property_hash[:ensure]}") @property_hash[:ensure] != :absent end
Get expiry from system and convert to Puppet-style date
# File lib/puppet/provider/user/pw.rb, line 86 def expiry expiry = self.get(:expiry) expiry = :absent if expiry == 0 if expiry != :absent t = Time.at(expiry) expiry = "%4d-%02d-%02d" % [t.year, t.month, t.mday] end expiry end
# File lib/puppet/provider/user/aix.rb, line 203 def expiry_from_attr(value) if value =~ /(..)(..)(..)(..)(..)/ #d= DateTime.parse("20#{$5}-#{$1}-#{$2} #{$3}:#{$4}") #expiry_date = d.strftime("%Y-%m-%d %H:%M") #expiry_date = d.strftime("%Y-%m-%d") expiry_date = "20#{$5}-#{$1}-#{$2}" else Puppet.warn("Could not convert AIX expires date '#{value}' on #{@resource.class.name}[#{@resource.name}]") unless value == '0' expiry_date = :absent end expiry_date end
The expiry date for this user. Must be provided in a zero padded YYYY-MM-DD HH:MM format
# File lib/puppet/provider/user/aix.rb, line 192 def expiry_to_attr(value) # For chuser the expires parameter is a 10-character string in the MMDDhhmmyy format # that is,"%m%d%H%M%y" newdate = '0' if value.is_a? String and value!="0000-00-00" d = DateTime.parse(value, "%Y-%m-%d %H:%M") newdate = d.strftime("%m%d%H%M%y") end newdate end
# File lib/puppet/provider/service/upstart.rb, line 330 def extract_start_on_block_from(text) parens = 0 text.lines.map do |line| if line.match(START_ON) || parens > 0 parens += unbalanced_parens_on(remove_trailing_comments_from(line)) line end end.join('') end
Extract value name from service or rcvar
# File lib/puppet/provider/service/freebsd.rb, line 31 def extract_value_name(name, rc_index, regex, regex_index) value_name = self.rcvar[rc_index] self.error("No #{name} name found in rcvar") if value_name.nil? value_name = value_name.gsub!(regex, regex_index) self.error("#{name} name is empty") if value_name.nil? self.debug("#{name} name is #{value_name}") value_name end
Make sure the file we wrote out is what we think it is.
# File lib/puppet/type/file.rb, line 885 def fail_if_checksum_is_wrong(path, content_checksum) newsum = parameter(:checksum).sum_file(path) return if [:absent, nil, content_checksum].include?(newsum) self.fail "File written to disk did not match checksum; discarding changes (#{content_checksum} vs #{newsum})" end
# File lib/puppet/provider/file/windows.rb, line 91 def file @file ||= Puppet::FileSystem.pathname(resource[:path]) end
# File lib/puppet/provider/ssh_authorized_key/parsed.rb, line 41 def file_perm 0600 end
# File lib/puppet/functions/filter.rb, line 73 def filter_Enumerable_1(enumerable) result = [] index = 0 enum = asserted_enumerable(enumerable) begin loop do it = enum.next if yield(it) == true result << it end end rescue StopIteration end result end
# File lib/puppet/functions/filter.rb, line 89 def filter_Enumerable_2(enumerable) result = [] index = 0 enum = asserted_enumerable(enumerable) begin loop do it = enum.next if yield(index, it) == true result << it end index += 1 end rescue StopIteration end result end
# File lib/puppet/functions/filter.rb, line 59 def filter_Hash_1(hash) result = hash.select {|x, y| yield([x, y]) == true } # Ruby 1.8.7 returns Array result = Hash[result] unless result.is_a? Hash result end
# File lib/puppet/functions/filter.rb, line 66 def filter_Hash_2(hash) result = hash.select {|x, y| yield(x, y) == true } # Ruby 1.8.7 returns Array result = Hash[result] unless result.is_a? Hash result end
# File lib/puppet/provider/group/aix.rb, line 108 def filter_attributes(hash) # Return only not managed attributtes. hash.select { |k,v| !self.class.attribute_mapping_from.include?(k) and !self.class.attribute_ignore.include?(k) }.inject({}) { |hash, array| hash[array[0]] = array[1]; hash } end
# File lib/puppet/provider/group/groupadd.rb, line 30 def findgroup(key, value) group_file = "/etc/group" group_keys = ['group_name', 'password', 'gid', 'user_list'] index = group_keys.index(key) File.open(group_file) do |f| f.each_line do |line| group = line.split(":") if group[index] == value f.close return group end end end false end
# File lib/puppet/provider/user/useradd.rb, line 57 def finduser(key, value) passwd_file = "/etc/passwd" passwd_keys = ['account', 'password', 'uid', 'gid', 'gecos', 'directory', 'shell'] index = passwd_keys.index(key) File.open(passwd_file) do |f| f.each_line do |line| user = line.split(":") if user[index] == value f.close return user end end end false end
We have to do some extra finishing, to retrieve our bucket if there is one.
# File lib/puppet/type/file.rb, line 450 def finish # Look up our bucket, if there is one bucket super end
A derivative of DPKG; this is how most people actually manage Debian boxes, and the only thing that differs is that it can install packages from remote sites.
# File lib/puppet/provider/package/fink.rb, line 18 def finkcmd(*args) fink(*args) end
# File lib/puppet/provider/service/openbsd.rb, line 286 def flags @property_hash[:flags] end
# File lib/puppet/provider/service/openbsd.rb, line 290 def flags=(value) @property_hash[:flags] = value end
# File lib/puppet/provider/service/openbsd.rb, line 294 def flush debug "Flusing resource for #{self.name}" # Here we load the contents of the rc.conf.local file into the contents # variable, modify it if needed, and then compare that to the original. If # they are different, we write it out. original = load_rcconf_local_array() content = original debug @property_hash.inspect if resource[:enable] == :true #set_flags(resource[:flags]) content = set_content_flags(content, resource[:flags]) # We need only add append the resource name to the pkg_scripts if the # package is not found in the base system. if not in_base? content = set_content_scripts(content,pkg_scripts_append()) end elsif resource[:enable] == :false # By virtue of being excluded from the base system, all packages are # disabled by default and need not be set in the rc.conf.local at all. if not in_base? content = remove_content_flags(content) content = set_content_scripts(content,pkg_scripts_remove()) else if default_disabled? content = remove_content_flags(content) else content = set_content_flags(content, "NO") end end end # Make sure to append a newline to the end of the file unless content[-1] == "" content << "" end output = content.join("\n") # Write the contents only if necessary, and only once write_rc_contents(self.class.rcconf_local(), output) end
# File lib/puppet/provider/user/directoryservice.rb, line 553 def flush_dscl_cache dscacheutil '-flushcache' end
# File lib/puppet/provider/macauthorization/macauthorization.rb, line 151 def flush_right # first we re-read the right just to make sure we're in sync for # values that weren't specified in the manifest. As we're supplying # the whole plist when specifying the right it seems safest to be # paranoid given the low cost of quering the db once more. cmds = [] cmds << :security << "authorizationdb" << "read" << resource[:name] output = execute(cmds, :failonfail => false, :combine => false) current_values = Plist::parse_xml(output) current_values ||= {} specified_values = convert_plist_to_native_attributes(@property_hash) # take the current values, merge the specified values to obtain a # complete description of the new values. new_values = current_values.merge(specified_values) set_right(resource[:name], new_values) end
# File lib/puppet/provider/macauthorization/macauthorization.rb, line 169 def flush_rule authdb = Plist::parse_xml(AuthDB) authdb_rules = authdb["rules"].dup current_values = {} current_values = authdb_rules[resource[:name]] if authdb_rules[resource[:name]] specified_values = convert_plist_to_native_attributes(@property_hash) new_values = current_values.merge(specified_values) set_rule(resource[:name], new_values) end
# File lib/puppet/vendor/semantic/spec/unit/semantic/dependency_spec.rb, line 168 def foo(range) subject('foo' => range).map { |x| x.last } end
# File lib/puppet/functions/each.rb, line 80 def foreach_Enumerable_1(enumerable) enum = asserted_enumerable(enumerable) begin loop { yield(enum.next) } rescue StopIteration end # produces the receiver enumerable end
# File lib/puppet/functions/each.rb, line 90 def foreach_Enumerable_2(enumerable) enum = asserted_enumerable(enumerable) index = 0 begin loop do yield(index, enum.next) index += 1 end rescue StopIteration end # produces the receiver enumerable end
# File lib/puppet/functions/each.rb, line 62 def foreach_Hash_1(hash) enumerator = hash.each_pair hash.size.times do yield(enumerator.next) end # produces the receiver hash end
# File lib/puppet/functions/each.rb, line 71 def foreach_Hash_2(hash) enumerator = hash.each_pair hash.size.times do yield(*enumerator.next) end # produces the receiver hash end
# File lib/puppet/util/log/destinations.rb, line 122 def format(msg) # logstash_event format is documented at # https://logstash.jira.com/browse/LOGSTASH-675 data = {} data = msg.to_hash data['version'] = 1 data['@timestamp'] = data['time'] data.delete('time') data end
# File lib/puppet/type/tidy.rb, line 236 def generate return [] unless stat(self[:path]) case self[:recurse] when Integer, Fixnum, Bignum, /^\d+$/ parameter = { :recurse => true, :recurselimit => self[:recurse] } when true, :true, :inf parameter = { :recurse => true } end if parameter files = Puppet::FileServing::Fileset.new(self[:path], parameter).files.collect do |f| f == "." ? self[:path] : ::File.join(self[:path], f) end else files = [self[:path]] end result = files.find_all { |path| tidy?(path) }.collect { |path| mkfile(path) }.each { |file| notice "Tidying #{file.ref}" }.sort { |a,b| b[:path] <=> a[:path] } # No need to worry about relationships if we don't have rmdirs; there won't be # any directories. return result unless rmdirs? # Now make sure that all directories require the files they contain, if all are available, # so that a directory is emptied before we try to remove it. files_by_name = result.inject({}) { |hash, file| hash[file[:path]] = file; hash } files_by_name.keys.sort { |a,b| b <=> b }.each do |path| dir = ::File.dirname(path) next unless resource = files_by_name[dir] if resource[:require] resource[:require] << Puppet::Resource.new(:file, path) else resource[:require] = [Puppet::Resource.new(:file, path)] end end result end
# File lib/puppet/provider/group/aix.rb, line 98 def get_arguments(key, value, mapping, objectinfo) # In the case of attributes, return a list of key=vlaue if key == :attributes raise Puppet::Error, "Attributes must be a list of pairs key=value on #{@resource.class.name}[#{@resource.name}]" unless value and value.is_a? Hash return value.select { |k,v| true }.map { |pair| pair.join("=") } end super(key, value, mapping, objectinfo) end
# File lib/puppet/provider/augeas/augeas.rb, line 318 def get_augeas_version @aug.get("/augeas/version") || "" end
Gather ds_type and ds_name from resource or parse it out of the name.
# File lib/puppet/provider/mcx/mcxcontent.rb, line 158 def get_dsparams ds_type = resource[:ds_type] ds_type ||= parse_type(resource[:name]) raise MCXContentProviderException unless TypeMap.keys.include? ds_type.to_sym ds_name = resource[:ds_name] ds_name ||= parse_name(resource[:name]) { :ds_type => ds_type.to_sym, :ds_name => ds_name, } end
Return the IA module arguments based on the resource param ia_load_module
# File lib/puppet/provider/group/aix.rb, line 51 def get_ia_module_args if @resource[:ia_load_module] ["-R", @resource[:ia_load_module].to_s] else [] end end
Generate lens load paths from user given paths and local pluginsync dir
# File lib/puppet/provider/augeas/augeas.rb, line 301 def get_load_path(resource) load_path = [] # Permits colon separated strings or arrays if resource[:load_path] load_path = [resource[:load_path]].flatten load_path.map! { |path| path.split(/:/) } load_path.flatten! end if Puppet::FileSystem.exist?("#{Puppet[:libdir]}/augeas/lenses") load_path << "#{Puppet[:libdir]}/augeas/lenses" end load_path.join(":") end
# File lib/puppet/provider/zpool/zpool.rb, line 50 def get_pool_data # http://docs.oracle.com/cd/E19082-01/817-2271/gbcve/index.html # we could also use zpool iostat -v mypool for a (little bit) cleaner output out = execute("zpool status #{@resource[:pool]}", :failonfail => false, :combine => false) zpool_data = out.lines.select { |line| line.index("\t") == 0 }.collect { |l| l.strip.split("\s")[0] } zpool_data.shift zpool_data end
# File lib/puppet/provider/yumrepo/inifile.rb, line 282 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
This method will return the binary plist that’s embedded in the ShadowHashData key of a user’s plist, or false if it doesn’t exist.
# File lib/puppet/provider/user/directoryservice.rb, line 565 def get_shadow_hash_data(users_plist) if users_plist['ShadowHashData'] password_hash_plist = users_plist['ShadowHashData'][0].string self.class.convert_binary_to_xml(password_hash_plist) else false end end
# File lib/puppet/provider/service/debian.rb, line 57 def get_start_link_count Dir.glob("/etc/rc*.d/S??#{@resource[:name]}").length end
# File lib/puppet/provider/user/directoryservice.rb, line 557 def get_users_plist(username) # This method will retrieve the data stored in a user's plist and # return it as a native Ruby hash. Plist::parse_xml(plutil('-convert', 'xml1', '-o', '/dev/stdout', "#{users_plist_dir}/#{username}.plist")) end
# File lib/puppet/provider/package/openbsd.rb, line 179 def get_version execpipe([command(:pkginfo), "-I", @resource[:name]]) do |process| # our regex for matching pkg_info output regex = /^(.*)-(\d[^-]*)[-]?(\w*)(.*)$/ master_version = 0 version = -1 process.each_line do |line| if match = regex.match(line.split[0]) # now we return the first version, unless ensure is latest version = match.captures[1] return version unless @resource[:ensure] == "latest" master_version = version unless master_version > version end end return master_version unless master_version == 0 return '' if version == -1 raise Puppet::Error, "#{version} is not available for this package" end rescue Puppet::ExecutionFailure return nil end
Collect the configuration of the zone. The output looks like: zonename: z1 zonepath: /export/z1 brand: native autoboot: true bootargs: pool: limitpriv: scheduling-class: ip-type: shared hostid: net:
address: 192.168.1.1 physical: eg0001 defrouter not specified
net:
address: 192.168.1.3 physical: eg0002 defrouter not specified
# File lib/puppet/provider/zone/solaris.rb, line 215 def getconfig output = zonecfg :info name = nil current = nil hash = {} output.split("\n").each do |line| case line when /^(\S+):\s*$/ name = $1 current = nil # reset it when /^(\S+):\s*(\S+)$/ hash[$1.intern] = $2 when /^\s+(\S+):\s*(.+)$/ if name hash[name] ||= [] unless current current = {} hash[name] << current end current[$1.intern] = $2 else err "Ignoring '#{line}'" end else debug "Ignoring zone output '#{line}'" end end hash end
Get the process ID for a running process. Requires the ‘pattern’ parameter.
# File lib/puppet/provider/service/base.rb, line 16 def getpid @resource.fail "Either stop/status commands or a pattern must be specified" unless @resource[:pattern] ps = Facter["ps"].value @resource.fail "You must upgrade Facter to a version that includes 'ps'" unless ps and ps != "" regex = Regexp.new(@resource[:pattern]) self.debug "Executing '#{ps}'" IO.popen(ps) { |table| table.each_line { |line| if regex.match(line) self.debug "Process matched: #{line}" ary = line.sub(/^\s+/, '').split(/\s+/) return ary[1] end } } nil end
# File lib/puppet/provider/group/windows_adsi.rb, line 96 def gid Puppet::Util::Windows::SID.name_to_sid(@resource[:name]) end
# File lib/puppet/provider/group/windows_adsi.rb, line 100 def gid=(value) fail "gid is read-only" end
Get the group gid from its name
# File lib/puppet/provider/user/aix.rb, line 186 def gid_from_attr(value) groupid_by_name(value) end
The user’s primary group. Can be specified numerically or by name.
# File lib/puppet/provider/user/aix.rb, line 181 def gid_to_attr(value) verify_group(value) end
# File lib/puppet/provider/group/windows_adsi.rb, line 62 def group @group ||= Puppet::Util::Windows::ADSI::Group.new(@resource[:name]) end
Convert a gropu name to an id.
# File lib/puppet/provider/user/ldap.rb, line 111 def group2id(group) Puppet::Type.type(:group).provider(:ldap).name2id(group) end
# File lib/puppet/provider/file/windows.rb, line 55 def group=(should) begin set_group(should, resolved_path) rescue => detail raise Puppet::Error, "Failed to set group to '#{should}': #{detail}", detail.backtrace end end
# File lib/puppet/provider/user/ldap.rb, line 117 def group_manager Puppet::Type.type(:group).provider(:ldap).manager end
# File lib/puppet/provider/user/ldap.rb, line 121 def group_properties(values) if values.empty? or values == :absent {:ensure => :present} else {:ensure => :present, :members => values} end end
Get the groupname from its id
# File lib/puppet/provider/user/aix.rb, line 163 def groupid_by_name(groupname) attrs = self.parse_attr_list(execute(lsgroupscmd(groupname)).split("\n")[0], nil) attrs ? attrs[:id].to_i : nil end
Get the groupname from its id
# File lib/puppet/provider/user/aix.rb, line 151 def groupname_by_id(gid) groupname=nil execute(lsgroupscmd("ALL")).each_line { |entry| attrs = self.parse_attr_list(entry, nil) if attrs and attrs.include? :id and gid == attrs[:id].to_i groupname = entry.split(" ")[0] end } groupname end
Find all groups this user is a member of in ldap.
# File lib/puppet/provider/user/ldap.rb, line 55 def groups # We want to cache the current result, so we know if we # have to remove old values. unless @property_hash[:groups] unless result = group_manager.search("memberUid=#{name}") return @property_hash[:groups] = :absent end return @property_hash[:groups] = result.collect { |r| r[:name] }.sort.join(",") end @property_hash[:groups] end
In the setter method we’re only going to take action on groups for which the user is not currently a member.
# File lib/puppet/provider/user/directoryservice.rb, line 342 def groups=(value) guid = self.class.get_attribute_from_dscl('Users', @resource.name, 'GeneratedUID')['dsAttrTypeStandard:GeneratedUID'][0] groups_to_add = value.split(',') - groups.split(',') groups_to_add.each do |group| merge_attribute_with_dscl('Groups', group, 'GroupMembership', @resource.name) merge_attribute_with_dscl('Groups', group, 'GroupMembers', guid) end end
# File lib/puppet/provider/user/useradd.rb, line 228 def groups? !!@resource[:groups] end
# File lib/puppet/util/log/destinations.rb, line 27 def handle(msg) # XXX Syslog currently has a bug that makes it so you # cannot log a message with a '%' in it. So, we get rid # of them. if msg.source == "Puppet" msg.to_s.split("\n").each do |line| @syslog.send(msg.level, line.gsub("%", '%%')) end else msg.to_s.split("\n").each do |line| @syslog.send(msg.level, "(%s) %s" % [msg.source.to_s.gsub("%", ""), line.gsub("%", '%%') ] ) end end end
handle mirror or raid
# File lib/puppet/provider/zpool/zpool.rb, line 83 def handle_multi_arrays(prefix, array) array.collect{ |a| [prefix] + a.split(' ') }.flatten end
Launchd implemented plist overrides in version 10.6. This method checks the major_version of OS X and returns true if it is 10.6 or greater. This allows us to implement different plist behavior for versions >= 10.6
# File lib/puppet/provider/service/launchd.rb, line 198 def has_macosx_plist_overrides? # (#11593) Remove support for OS X 10.4 & earlier # leaving this as is because 10.5 still didn't have plist support return self.class.get_os_version > 9 end
# File lib/puppet/provider/mcx/mcxcontent.rb, line 106 def has_mcx? !content.empty? end
Mark that our init script supports ‘status’ commands.
# File lib/puppet/provider/service/init.rb, line 91 def hasstatus=(value) case value when true, "true"; @parameters[:hasstatus] = true when false, "false"; @parameters[:hasstatus] = false else raise Puppet::Error, "Invalid 'hasstatus' value #{value.inspect}" end end
# File lib/puppet/provider/package/dpkg.rb, line 148 def hold self.install Tempfile.open('puppet_dpkg_set_selection') do |tmpfile| tmpfile.write("#{@resource[:name]} hold\n") tmpfile.flush execute([:dpkg, "--set-selections"], :failonfail => false, :combine => false, :stdinfile => tmpfile.path.to_s) end end
# File lib/puppet/provider/user/windows_adsi.rb, line 72 def home user['HomeDirectory'] end
# File lib/puppet/provider/user/windows_adsi.rb, line 76 def home=(value) user['HomeDirectory'] = value end
# File lib/puppet/face/help.rb, line 153 def horribly_extract_summary_from(appname) begin help = Puppet::Application[appname].help.split("\n") # Now we find the line with our summary, extract it, and return it. This # depends on the implementation coincidence of how our pages are # formatted. If we can't match the pattern we expect we return the empty # string to ensure we don't blow up in the summary. --daniel 2011-04-11 while line = help.shift do if md = /^puppet-#{appname}\([^\)]+\) -- (.*)$/.match(line) then return md[1] end end rescue Exception # Damn, but I hate this: we just ignore errors here, no matter what # class they are. Meh. end return '' end
# File lib/puppet/reports/rrdgraph.rb, line 23 def hostdir @hostdir ||= File.join(Puppet[:rrddir], self.host) end
# File lib/puppet/reports/rrdgraph.rb, line 27 def htmlfile(type, graphs, field) file = File.join(hostdir, "#{type}.html") File.open(file, "w") do |of| of.puts "<html><head><title>#{type.capitalize} graphs for #{host}</title></head><body>" graphs.each do |graph| if field == :first name = graph.sub(/-\w+.png/, '').capitalize else name = graph.sub(/\w+-/, '').sub(".png", '').capitalize end of.puts "<img src=#{graph}><br>" end of.puts "</body></html>" end file end
If it’s a valid SID, get the name. Otherwise, it’s already a name, so just return it.
# File lib/puppet/provider/file/windows.rb, line 21 def id2name(id) if Puppet::Util::Windows::SID.valid_sid?(id) Puppet::Util::Windows::SID.sid_to_name(id) else id end end
# File lib/puppet/provider/package/sun.rb, line 125 def if_have_value(prefix, value) if value [prefix, value] else [] end end
# File lib/puppet/functions/import.rb, line 4 def import(*args) raise Puppet::Pops::SemanticError.new(Puppet::Pops::Issues::DISCONTINUED_IMPORT) end
Determine if the rc script is included in base @api private
# File lib/puppet/provider/service/openbsd.rb, line 250 def in_base? script = File.readlines(self.class.rcconf).find {|s| s =~ /^#{rcvar_name}/ } !script.nil? end
Get info on a package, optionally specifying a device.
# File lib/puppet/provider/package/sun.rb, line 64 def info2hash(device = nil) args = ['-l'] args << '-d' << device if device args << @resource[:name] begin pkgs = self.class.parse_pkginfo(pkginfo(*args)) errmsg = case pkgs.size when 0 'No message' when 1 pkgs[0]['ERROR'] end return self.class.namemap(pkgs[0]) if errmsg.nil? # according to commit 41356a7 some errors do not raise an exception # so eventhough pkginfo passed, we have to check the actual output raise Puppet::Error, "Unable to get information about package #{@resource[:name]} because of: #{errmsg}" rescue Puppet::ExecutionFailure return {:ensure => :absent} end end
# File lib/puppet/provider/service/redhat.rb, line 51 def initscript raise Puppet::Error, "Do not directly call the init script for '#{@resource[:name]}'; use 'service' instead" end
# File lib/puppet/functions/inline_epp.rb, line 84 def inline_epp(scope, template, parameters = nil) Puppet::Pops::Evaluator::EppEvaluator.inline_epp(scope, template, parameters) end
# File lib/puppet/provider/package/yum.rb, line 96 def install wanted = @resource[:name] # If not allowing virtual packages, do a query to ensure a real package exists unless @resource.allow_virtual? yum *['-d', '0', '-e', '0', '-y', install_options, :list, wanted].compact end should = @resource.should(:ensure) self.debug "Ensuring => #{should}" operation = :install case should when true, false, Symbol # pass should = nil else # Add the package version wanted += "-#{should}" is = self.query if is && Puppet::Util::Package.versioncmp(should, is[:ensure]) < 0 self.debug "Downgrading package #{@resource[:name]} from version #{is[:ensure]} to #{should}" operation = :downgrade end end args = ["-d", "0", "-e", "0", "-y", install_options, operation, wanted].compact yum *args # If a version was specified, query again to see if it is a matching version if should is = self.query raise Puppet::Error, "Could not find package #{self.name}" unless is # FIXME: Should we raise an exception even if should == :latest # and yum updated us to a version other than @param_hash[:ensure] ? raise Puppet::Error, "Failed to update to version #{should}, got version #{is[:ensure]} instead" if should != is[:ensure] end end
# File lib/puppet/provider/package/pacman.rb, line 57 def install_from_file source = @resource[:source] begin source_uri = URI.parse source rescue => detail self.fail Puppet::Error, "Invalid source '#{source}': #{detail}", detail end source = case source_uri.scheme when nil then source when /https?/ then source when /ftp/ then source when /file/ then source_uri.path when /puppet/ fail "puppet:// URL is not supported by pacman" else fail "Source #{source} is not supported by pacman" end pacman "--noconfirm", "--noprogressbar", "-Sy" pacman "--noconfirm", "--noprogressbar", "-U", source end
# File lib/puppet/provider/package/pacman.rb, line 42 def install_from_repo if yaourt? cmd = %w{--noconfirm} cmd += install_options if @resource[:install_options] cmd << "-S" << @resource[:name] yaourt *cmd else cmd = %w{--noconfirm --noprogressbar} cmd += install_options if @resource[:install_options] cmd << "-Sy" << @resource[:name] pacman *cmd end end
# File lib/puppet/provider/package/gem.rb, line 132 def install_options join_options(resource[:install_options]) end
# File lib/puppet/vendor/semantic/spec/unit/semantic/dependency/graph_node_spec.rb, line 24 def instance(*args) name = args.first.name unless args.empty? klass.new(name || 'unnamed', *args) end
# File lib/puppet/type/cron.rb, line 333 def insync?(is) if is.is_a? Array return is.sort == @should.sort else return is == @should end end
# File lib/puppet/network/formats.rb, line 7 def intern(klass, text) data = MessagePack.unpack(text) return data if data.is_a?(klass) klass.from_data_hash(data) end
# File lib/puppet/network/formats.rb, line 13 def intern_multiple(klass, text) MessagePack.unpack(text).collect do |data| klass.from_data_hash(data) end end
# File lib/puppet/functions/defined.rb, line 76 def is_defined(scope, *vals) vals.any? do |val| case val when String if val =~ /^\$(.+)$/ scope.exist?($1) else case val when '' next nil when 'main' # Find the main class (known as ''), it does not have to be in the catalog scope.find_hostclass('') else # Find a resource type, definition or class definition scope.find_resource_type(val) || scope.find_definition(val) || scope.find_hostclass(val) #scope.compiler.findresource(:class, val) end end when Puppet::Resource # Find instance of given resource type and title that is in the catalog scope.compiler.findresource(val.type, val.title) when Puppet::Pops::Types::PResourceType raise ArgumentError, 'The given resource type is a reference to all kind of types' if val.type_name.nil? if val.title.nil? scope.find_builtin_resource_type(val.type_name) || scope.find_definition(val.type_name) else scope.compiler.findresource(val.type_name, val.title) end when Puppet::Pops::Types::PHostClassType raise ArgumentError, 'The given class type is a reference to all classes' if val.class_name.nil? scope.compiler.findresource(:class, val.class_name) when Puppet::Pops::Types::PType case val.type when Puppet::Pops::Types::PResourceType # It is most reasonable to take Type[File] and Type[File[foo]] to mean the same as if not wrapped in a Type # Since the difference between File and File[foo] already captures the distinction of type vs instance. is_defined(scope, val.type) when Puppet::Pops::Types::PHostClassType # Interpreted as asking if a class (and nothing else) is defined without having to be included in the catalog # (this is the same as asking for just the class' name, but with the added certainty that it cannot be a defined type. # raise ArgumentError, 'The given class type is a reference to all classes' if val.type.class_name.nil? scope.find_hostclass(val.type.class_name) end else raise ArgumentError, "Invalid argument of type '#{val.class}' to 'defined'" end end end
This should absolutely be a private method, but for some reason it appears that you can't use the 'private' keyword inside of a Face definition. See #14205.
private :exclude_from_docs?
# File lib/puppet/face/help.rb, line 184 def is_face_app?(appname) clazz = Puppet::Application.find(appname) clazz.ancestors.include?(Puppet::Application::FaceBase) end
# File lib/puppet/provider/augeas/augeas.rb, line 201 def is_numeric?(s) case s when Fixnum true when String s.match(/\A[+-]?\d+?(\.\d+)?\Z/) == nil ? false : true else false end end
# File lib/puppet/provider/user/user_role_add.rb, line 64 def is_role? user_attributes and user_attributes[:type] == "role" end
# File lib/puppet/type/cron.rb, line 341 def is_to_s(newvalue) if newvalue if newvalue.is_a?(Array) newvalue.join(",") else newvalue end else nil end end
# File lib/puppet/provider/service/upstart.rb, line 169 def is_upstart?(script = initscript) Puppet::FileSystem.exist?(script) && script.match(/\/etc\/init\/\S+\.conf/) end
The iterations and salt properties, like the password property, can only be modified by directly changing the user’s plist. Because of this fact, we have to treat the ds cache just like you would in the password= method.
# File lib/puppet/provider/user/directoryservice.rb, line 408 def iterations=(value) if (Puppet::Util::Package.versioncmp(self.class.get_os_version, '10.7') > 0) assert_full_pbkdf2_password sleep 2 flush_dscl_cache users_plist = get_users_plist(@resource.name) shadow_hash_data = get_shadow_hash_data(users_plist) set_salted_pbkdf2(users_plist, shadow_hash_data, 'iterations', value) flush_dscl_cache end end
# File lib/puppet/network/formats.rb, line 177 def json @json ||= Puppet::Network::FormatHandler.format(:pson) end
# File lib/puppet/provider/user/user_role_add.rb, line 131 def keys if user_attributes #we have to get rid of all the keys we are managing another way remove_managed_attributes end end
# File lib/puppet/provider/user/user_role_add.rb, line 146 def keys=(keys_hash) run([command(:modify)] + build_keys_cmd(keys_hash) << @resource[:name], "modify attribute key pairs") end
What’s the latest package version available?
# File lib/puppet/provider/package/yum.rb, line 137 def latest upd = self.class.latest_package_version(@resource[:name], enablerepo, disablerepo) unless upd.nil? # FIXME: there could be more than one update for a package # because of multiarch return "#{upd[:epoch]}:#{upd[:version]}-#{upd[:release]}" else # Yum didn't find updates, pretend the current # version is the latest raise Puppet::DevError, "Tried to get latest on a missing package" if properties[:ensure] == :absent return properties[:ensure] end end
@deprecated
# File lib/puppet/provider/package/yum.rb, line 161 def latest_info Puppet.deprecation_warning("#{self.class}##{__method__} is deprecated and is no longer used.") @latest_info end
@deprecated
# File lib/puppet/provider/package/yum.rb, line 167 def latest_info=(latest) Puppet.deprecation_warning("#{self.class}##{__method__} is deprecated and is no longer used.") @latest_info = latest end
# File lib/puppet/provider/package/pip.rb, line 118 def lazy_pip(*args) pip *args rescue NoMethodError => e if pathname = which(self.class.cmd) self.class.commands :pip => pathname pip *args else raise e, 'Could not locate the pip command.', e.backtrace end end
Return a list of applications that are not simply just stubs for Faces.
# File lib/puppet/face/help.rb, line 125 def legacy_applications Puppet::Application.available_application_names.reject do |appname| (is_face_app?(appname)) or (exclude_from_docs?(appname)) end.sort end
Prepare a module object for print in a tree view. Each node in the tree must be a Hash in the following format:
{ :text => "puppetlabs-mysql (v1.0.0)" }
The value of a module’s :text is affected by three (3) factors: the format of the tree, its dependency status, and the location in the modulepath relative to its parent.
Returns a Hash
# File lib/puppet/face/module/list.rb, line 251 def list_build_node(mod, parent, params) str = '' str << (mod.forge_name ? mod.forge_name.gsub('/', '-') : mod.name) str << ' (' + colorize(:cyan, mod.version ? "v#{mod.version}" : '???') + ')' unless File.dirname(mod.path) == params[:path] str << " [#{File.dirname(mod.path)}]" end if @unmet_deps[:version_mismatch].include?(mod.forge_name) if params[:label_invalid] str << ' ' + colorize(:red, 'invalid') elsif parent.respond_to?(:forge_name) unmet_parent = @unmet_deps[:version_mismatch][mod.forge_name][:parent] if (unmet_parent[:name] == parent.forge_name && unmet_parent[:version] == "v#{parent.version}") str << ' ' + colorize(:red, 'invalid') end end end { :text => str } end
Prepare a list of module objects and their dependencies for print in a tree view.
Returns an Array of Hashes
Example:
[
{
:text => "puppetlabs-bacula (v0.0.2)",
:dependencies=> [
{ :text => "puppetlabs-stdlib (v2.2.1)", :dependencies => [] },
{
:text => "puppetlabs-mysql (v1.0.0)"
:dependencies => [
{
:text => "bodepd-create_resources (v0.0.1)",
:dependencies => []
}
]
},
{ :text => "puppetlabs-sqlite (v0.0.1)", :dependencies => [] },
]
}
]
When the above data structure is passed to Puppet::ModuleTool.build_tree you end up with something like this:
/etc/puppet/modules └─┬ puppetlabs-bacula (v0.0.2) ├── puppetlabs-stdlib (v2.2.1) ├─┬ puppetlabs-mysql (v1.0.0) │ └── bodepd-create_resources (v0.0.1) └── puppetlabs-sqlite (v0.0.1)
# File lib/puppet/face/module/list.rb, line 216 def list_build_tree(list, ancestors=[], parent=nil, params={}) list.map do |mod| next if @seen[(mod.forge_name or mod.name)] node = list_build_node(mod, parent, params) @seen[(mod.forge_name or mod.name)] = true unless ancestors.include?(mod) node[:dependencies] ||= [] missing_deps = mod.unmet_dependencies.select do |dep| dep[:reason] == :missing end missing_deps.map do |mis_mod| str = "#{colorize(:bg_red, 'UNMET DEPENDENCY')} #{mis_mod[:name].gsub('/', '-')} " str << "(#{colorize(:cyan, mis_mod[:version_constraint])})" node[:dependencies] << { :text => str } end node[:dependencies] += list_build_tree(mod.dependencies_as_modules, ancestors + [mod], mod, params) end node end.compact end
# File lib/puppet/face/help.rb, line 87 def load_face_help(facename, actionname, version) begin face = Puppet::Face[facename.to_sym, version] rescue Puppet::Error => detail msg = <<-MSG Could not load help for the face #{facename}. Please check the error logs for more information. Detail: "#{detail.message}" MSG fail ArgumentError, msg, detail.backtrace end if actionname action = face.get_action(actionname.to_sym) if not action fail ArgumentError, "Unable to load action #{actionname} from #{face}" end end [face, action] end
@api private
# File lib/puppet/provider/service/openbsd.rb, line 148 def load_rcconf_local_array if File.exists?(self.class.rcconf_local()) File.readlines(self.class.rcconf_local()).map {|l| l.chomp! } else [] end end
# File lib/puppet/provider/user/useradd.rb, line 73 def local_username finduser('uid', @resource.uid) end
# File lib/puppet/provider/group/groupadd.rb, line 46 def localgid group = findgroup('group_name', resource[:name]) return group[2] if group false end
# File lib/puppet/provider/user/useradd.rb, line 77 def localuid user = finduser('account', resource[:name]) return user[2] if user false end
# File lib/puppet/provider/group/aix.rb, line 65 def lsallcmd() lscmd("ALL") end
# File lib/puppet/provider/group/aix.rb, line 59 def lscmd(value=@resource[:name]) [self.class.command(:list)] + self.get_ia_module_args + [ value] end
List groups and Ids
# File lib/puppet/provider/user/aix.rb, line 92 def lsgroupscmd(value=@resource[:name]) [command(:lsgroup)] + self.get_ia_module_args + ["-a", "id", value] end
# File lib/puppet/vendor/semantic/spec/unit/semantic/dependency/module_release_spec.rb, line 9 def make_release(name, version, deps = {}) source.create_release(name, version, deps) end
# File lib/puppet/face/instrumentation_listener.rb, line 48 def manage(name, activate) Puppet::Util::Instrumentation::Listener.indirection.terminus_class = :rest listener = Puppet::Face[:instrumentation_listener, '0.0.1'].find(name) if listener listener.enabled = activate Puppet::Face[:instrumentation_listener, '0.0.1'].save(listener) end end
# File lib/puppet/provider/user/aix.rb, line 280 def managed_attribute_keys(hash) managed_attributes ||= @resource.original_parameters[:attributes] || hash.keys.map{|k| k.to_s} managed_attributes.map {|attr| key, value = attr.split("="); key.strip.to_sym} end
# File lib/puppet/provider/user/user_role_add.rb, line 122 def managed_attributes [:name, :type, :roles, :auths, :profiles, :project] end
# File lib/puppet/provider/service/windows.rb, line 35 def manual_start w32ss = Win32::Service.configure( 'service_name' => @resource[:name], 'start_type' => Win32::Service::SERVICE_DEMAND_START ) raise Puppet::Error.new("Win32 service manual enable of #{@resource[:name]} failed" ) if( w32ss.nil? ) rescue => detail raise Puppet::Error.new("Cannot enable #{@resource[:name]} for manual start, error was: #{detail}", detail ) end
# File lib/puppet/functions/map.rb, line 65 def map_Enumerable_1(enumerable) result = [] index = 0 enum = asserted_enumerable(enumerable) begin loop { result << yield(enum.next) } rescue StopIteration end result end
# File lib/puppet/functions/map.rb, line 76 def map_Enumerable_2(enumerable) result = [] index = 0 enum = asserted_enumerable(enumerable) begin loop do result << yield(index, enum.next) index = index +1 end rescue StopIteration end result end
# File lib/puppet/functions/map.rb, line 57 def map_Hash_1(hash) hash.map {|x, y| yield([x, y]) } end
# File lib/puppet/functions/map.rb, line 61 def map_Hash_2(hash) hash.map {|x, y| yield(x, y) } end
Configure discovered resources to be purged.
# File lib/puppet/type/file.rb, line 497 def mark_children_for_purging(children) children.each do |name, child| next if child[:source] child[:ensure] = :absent end end
Find all matching messages.
# File lib/puppet/reports/tagmail.rb, line 42 def match(taglists) matching_logs = [] taglists.each do |emails, pos, neg| # First find all of the messages matched by our positive tags messages = nil if pos.include?("all") messages = self.logs else # Find all of the messages that are tagged with any of our # tags. messages = self.logs.find_all do |log| pos.detect { |tag| log.tagged?(tag) } end end # Now go through and remove any messages that match our negative tags messages = messages.reject do |log| true if neg.detect do |tag| log.tagged?(tag) end end if messages.empty? Puppet.info "No messages to report to #{emails.join(",")}" next else matching_logs << [emails, messages.collect { |m| m.to_report }.join("\n")] end end matching_logs end
Returns the first matching entry
# File lib/puppet/functions/match.rb, line 89 def match_Array(array, s) result = nil array.flatten.find {|entry| result = match(s, entry) } result end
# File lib/puppet/functions/match.rb, line 62 def match_Object(obj, s) msg = "match() expects pattern of T, where T is String, Regexp, Regexp[r], Pattern[p], or Array[T]. Got #{obj.class}" raise ArgumentError, msg end
# File lib/puppet/functions/match.rb, line 80 def match_PPatternType(pattern_t, s) # Since we want the actual match result (not just a boolean), an iteration over # Pattern's regular expressions is needed. (They are of PRegexpType) result = nil pattern_t.patterns.find {|pattern| result = match(s, pattern) } result end
# File lib/puppet/functions/match.rb, line 75 def match_PRegexpType(regexp_t, s) raise ArgumentError, "Given Regexp Type has no regular expression" unless regexp_t.pattern do_match(s, regexp_t.regexp) end
# File lib/puppet/functions/match.rb, line 71 def match_Regexp(regexp, s) do_match(s, regexp) end
# File lib/puppet/functions/match.rb, line 67 def match_String(pattern_string, s) do_match(s, Regexp.new(pattern_string)) end
Does a given path match our glob patterns, if any? Return true if no patterns have been provided.
# File lib/puppet/type/tidy.rb, line 278 def matches?(path) return true unless self[:matches] basename = File.basename(path) flags = File::FNM_DOTMATCH | File::FNM_PATHNAME if self[:matches].find {|pattern| File.fnmatch(pattern, basename, flags) } return true else debug "No specified patterns match #{path}, not tidying" return false end end
# File lib/puppet/provider/mcx/mcxcontent.rb, line 110 def mcximport(ds_type, ds_name, val) ds_t = TypeMap[ds_type] ds_path = "/Local/Default/#{ds_t}/#{ds_name}" if has_mcx? Puppet.debug "Removing MCX from #{ds_path}" dscl 'localhost', '-mcxdelete', ds_path end tmp = Tempfile.new('puppet_mcx') begin tmp << val tmp.flush Puppet.debug "Importing MCX into #{ds_path}" dscl 'localhost', '-mcximport', ds_path, tmp.path ensure tmp.close tmp.unlink end end
# File lib/puppet/provider/group/windows_adsi.rb, line 58 def member_valid?(user_name) ! Puppet::Util::Windows::SID.name_to_sid_object(user_name).nil? end
# File lib/puppet/provider/group/windows_adsi.rb, line 66 def members group.members end
# File lib/puppet/provider/group/windows_adsi.rb, line 70 def members=(members) group.set_members(members, @resource[:auth_membership]) end
# File lib/puppet/provider/group/windows_adsi.rb, line 17 def members_insync?(current, should) return false unless current # By comparing account SIDs we don't have to worry about case # sensitivity, or canonicalization of account names. # Cannot use munge of the group property to canonicalize @should # since the default array_matching comparison is not commutative # dupes automatically weeded out when hashes built current_users = Puppet::Util::Windows::ADSI::Group.name_sid_hash(current) specified_users = Puppet::Util::Windows::ADSI::Group.name_sid_hash(should) if @resource[:auth_membership] current_users == specified_users else return true if specified_users.empty? (specified_users.keys.to_a & current_users.keys.to_a) == specified_users.keys.to_a end end
# File lib/puppet/provider/group/windows_adsi.rb, line 38 def members_to_s(users) return '' if users.nil? or !users.kind_of?(Array) users = users.map do |user_name| sid = Puppet::Util::Windows::SID.name_to_sid_object(user_name) if !sid resource.debug("#{user_name} (unresolvable to SID)") next user_name end if sid.account =~ /\/ account, _ = Puppet::Util::Windows::ADSI::User.parse_name(sid.account) else account = sid.account end resource.debug("#{sid.domain}\\#{account} (#{sid.to_s})") "#{sid.domain}\\#{account}" end return users.join(',') end
This method will merge in a given value using dscl
# File lib/puppet/provider/user/directoryservice.rb, line 499 def merge_attribute_with_dscl(path, username, keyname, value) begin dscl '.', '-merge', "/#{path}/#{username}", keyname, value rescue Puppet::ExecutionFailure => detail raise Puppet::Error, "Could not set the dscl #{keyname} key with value: #{value} - #{detail.inspect}", detail.backtrace end end
# File lib/puppet/functions/hiera_hash.rb, line 33 def merge_type :hash end
Adds methods to a #singleton_class
# File lib/puppet/util/metaid.rb, line 7 def meta_def(name, &blk) meta_eval { define_method name, &blk } end
# File lib/puppet/util/metaid.rb, line 4 def meta_eval(&blk); singleton_class.instance_eval(&blk); end
Remove #singleton_class methods.
# File lib/puppet/util/metaid.rb, line 12 def meta_undef(name, &blk) meta_eval { remove_method name } end
Make a file resource to remove a given file.
# File lib/puppet/type/tidy.rb, line 217 def mkfile(path) # Force deletion, so directories actually get deleted. Puppet::Type.type(:file).new :path => path, :backup => self[:backup], :ensure => :absent, :force => true end
# File lib/puppet/reports/rrdgraph.rb, line 46 def mkhtml images = Dir.entries(hostdir).find_all { |d| d =~ /\.png/ } periodorder = %w{daily weekly monthly yearly} periods = {} types = {} images.each do |n| type, period = n.sub(".png", '').split("-") periods[period] ||= [] types[type] ||= [] periods[period] << n types[type] << n end files = [] # Make the period html files periodorder.each do |period| unless ary = periods[period] raise Puppet::Error, "Could not find graphs for #{period}" end files << htmlfile(period, ary, :first) end # make the type html files types.sort { |a,b| a[0] <=> b[0] }.each do |type, ary| newary = [] periodorder.each do |period| if graph = ary.find { |g| g.include?("-#{period}.png") } newary << graph else raise "Could not find #{type}-#{period} graph" end end files << htmlfile(type, newary, :second) end File.open(File.join(hostdir, "index.html"), "w") do |of| of.puts "<html><head><title>Report graphs for #{host}</title></head><body>" files.each do |file| of.puts "<a href='#{File.basename(file)}'>#{File.basename(file).sub(".html",'').capitalize}</a><br/>" end of.puts "</body></html>" end end
# File lib/puppet/provider/file/windows.rb, line 63 def mode if resource.stat mode = get_mode(resource[:path]) mode ? mode.to_s(8) : :absent else :absent end end
# File lib/puppet/provider/file/windows.rb, line 72 def mode=(value) begin set_mode(value.to_i(8), resource[:path]) rescue => detail error = Puppet::Error.new("failed to set mode #{mode} on #{resource[:path]}: #{detail.message}") error.set_backtrace detail.backtrace raise error end :file_changed end
# File lib/puppet/provider/group/aix.rb, line 80 def modifycmd(hash = property_hash) args = self.hash2args(hash) return nil if args.empty? [self.class.command(:modify)] + self.get_ia_module_args + args + [@resource[:name]] end
# File lib/puppet/provider/scheduled_task/win32_taskscheduler.rb, line 556 def month_constant_to_number(constant) month_num = 1 while constant >> month_num - 1 > 1 month_num += 1 end month_num end
# File lib/puppet/provider/scheduled_task/win32_taskscheduler.rb, line 441 def months_from_bitfield(bitfield) months = [] scheduler_months.each do |month| if bitfield & month != 0 months << month_constant_to_number(month) end end months end
# File lib/puppet/provider/zone/solaris.rb, line 31 def multi_conf(name, should, &action) has = properties[name] has = [] if !has || has == :absent rms = has - should adds = should - has (rms.map{|o| action.call(:rm,o)} + adds.map{|o| action.call(:add,o)}).join("\n") end
# File lib/puppet/type/cron.rb, line 239 def munge(value) value.strip end
# File lib/puppet/type/macauthorization.rb, line 20 def munge_boolean(value) case value when true, "true", :true :true when false, "false", :false :false else fail("munge_boolean only takes booleans") end end
# File lib/puppet/type/macauthorization.rb, line 31 def munge_integer(value) Integer(value) rescue ArgumentError fail("munge_integer only takes integers") end
# File lib/puppet/provider/zone/solaris.rb, line 106 def my_properties [:path, :iptype, :autoboot, :pool, :shares, :ip, :dataset, :inherit] end
Determine if the account is valid, and if so, return the UID
# File lib/puppet/provider/file/windows.rb, line 15 def name2id(value) Puppet::Util::Windows::SID.name_to_sid(value) end
Determines if augeas actually needs to run.
# File lib/puppet/provider/augeas/augeas.rb, line 356 def need_to_run? force = resource[:force] return_value = true begin open_augeas filter = resource[:onlyif] unless filter == "" cmd_array = parse_commands(filter)[0] command = cmd_array[0]; begin case command when "get"; return_value = process_get(cmd_array) when "match"; return_value = process_match(cmd_array) end rescue SystemExit,NoMemoryError raise rescue Exception => e fail("Error sending command '#{command}' with params #{cmd_array[1..-1].inspect}/#{e.message}") end end unless force # If we have a verison of augeas which is at least 0.3.6 then we # can make the changes now and see if changes were made. if return_value and versioncmp(get_augeas_version, "0.3.6") >= 0 debug("Will attempt to save and only run if files changed") # Execute in NEWFILE mode so we can show a diff set_augeas_save_mode(SAVE_NEWFILE) do_execute_changes save_result = @aug.save unless save_result print_put_errors fail("Saving failed, see debug") end saved_files = @aug.match("/augeas/events/saved") if saved_files.size > 0 root = resource[:root].sub(/^\/$/, "") saved_files.map! {|key| @aug.get(key).sub(/^\/files/, root) } saved_files.uniq.each do |saved_file| if Puppet[:show_diff] && @resource[:show_diff] self.send(@resource[:loglevel], "\n" + diff(saved_file, saved_file + ".augnew")) end File.delete(saved_file + ".augnew") end debug("Files changed, should execute") return_value = true else debug("Skipping because no files were changed") return_value = false end end end ensure if not return_value or resource.noop? or not save_result close_augeas end end return_value end
This method returns a new StringIO object. Why does it exist? Well, StringIO objects have their own ‘serial number’, so when writing rspec tests it’s difficult to compare StringIO objects due to this serial number. If this action is wrapped in its own method, it can be mocked for easier testing.
# File lib/puppet/provider/user/directoryservice.rb, line 591 def new_stringio_object(value = '') StringIO.new(value) end
Create a new file or directory object as a child to the current object.
# File lib/puppet/type/file.rb, line 506 def newchild(path) full_path = ::File.join(self[:path], path) # Add some new values to our original arguments -- these are the ones # set at initialization. We specifically want to exclude any param # values set by the :source property or any default values. # LAK:NOTE This is kind of silly, because the whole point here is that # the values set at initialization should live as long as the resource # but values set by default or by :source should only live for the transaction # or so. Unfortunately, we don't have a straightforward way to manage # the different lifetimes of this data, so we kludge it like this. # The right-side hash wins in the merge. options = @original_parameters.merge(:path => full_path).reject { |param, value| value.nil? } # These should never be passed to our children. [:parent, :ensure, :recurse, :recurselimit, :target, :alias, :source].each do |param| options.delete(param) if options.include?(param) end self.class.new(options) end
Get the next available uid on the system by getting a list of user ids, sorting them, grabbing the last one, and adding a 1. Scientific stuff here.
# File lib/puppet/provider/user/directoryservice.rb, line 514 def next_system_id(min_id=20) dscl_output = dscl '.', '-list', '/Users', 'uid' # We're ok with throwing away negative uids here. Also, remove nil values. user_ids = dscl_output.split.compact.collect { |l| l.to_i if l.match(/^\d+$/) } ids = user_ids.compact!.sort! { |a,b| a.to_f <=> b.to_f } # We're just looking for an unused id in our sorted array. ids.each_index do |i| next_id = ids[i] + 1 return next_id if ids[i+1] != next_id and next_id >= min_id end end
# File lib/puppet/util/instrumentation/listeners/log.rb, line 13 def notify(label, event, data) return if event == :start log_line = "#{label} took #{data[:finished] - data[:started]}" (@last_logs[label] ||= []) << log_line @last_logs[label].shift if @last_logs[label].length > SIZE end
# File lib/puppet/provider/scheduled_task/win32_taskscheduler.rb, line 564 def occurrence_constant_to_name(constant) case constant when Win32::TaskScheduler::FIRST_WEEK; 'first' when Win32::TaskScheduler::SECOND_WEEK; 'second' when Win32::TaskScheduler::THIRD_WEEK; 'third' when Win32::TaskScheduler::FOURTH_WEEK; 'fourth' when Win32::TaskScheduler::LAST_WEEK; 'last' end end
# File lib/puppet/provider/scheduled_task/win32_taskscheduler.rb, line 574 def occurrence_name_to_constant(name) case name when 'first'; Win32::TaskScheduler::FIRST_WEEK when 'second'; Win32::TaskScheduler::SECOND_WEEK when 'third'; Win32::TaskScheduler::THIRD_WEEK when 'fourth'; Win32::TaskScheduler::FOURTH_WEEK when 'last'; Win32::TaskScheduler::LAST_WEEK end end
# File lib/puppet/provider/augeas/augeas.rb, line 145 def open_augeas unless @aug flags = Augeas::NONE flags = Augeas::TYPE_CHECK if resource[:type_check] == :true if resource[:incl] flags |= Augeas::NO_MODL_AUTOLOAD else flags |= Augeas::NO_LOAD end root = resource[:root] load_path = get_load_path(resource) debug("Opening augeas with root #{root}, lens path #{load_path}, flags #{flags}") @aug = Augeas::open(root, load_path,flags) debug("Augeas version #{get_augeas_version} is installed") if versioncmp(get_augeas_version, "0.3.6") >= 0 # Optimize loading if the context is given and it's a simple path, # requires the glob function from Augeas 0.8.2 or up glob_avail = !aug.match("/augeas/version/pathx/functions/glob").empty? opt_ctx = resource[:context].match("^/files/[^'\"\\[\\]]+$") if resource[:context] restricted = false if resource[:incl] aug.set("/augeas/load/Xfm/lens", resource[:lens]) aug.set("/augeas/load/Xfm/incl", resource[:incl]) restricted_metadata = "/augeas//error" elsif glob_avail and opt_ctx # Optimize loading if the context is given, requires the glob function # from Augeas 0.8.2 or up ctx_path = resource[:context].sub(/^\/files(.*?)\/?$/, '\1/') load_path = "/augeas/load/*['%s' !~ glob(incl) + regexp('/.*')]" % ctx_path if aug.match(load_path).size < aug.match("/augeas/load/*").size aug.rm(load_path) restricted_metadata = "/augeas/files#{ctx_path}/error" else # This will occur if the context is less specific than any glob debug("Unable to optimize files loaded by context path, no glob matches") end end aug.load print_load_errors(restricted_metadata) end @aug end
# File lib/puppet/provider/user/aix.rb, line 217 def open_security_passwd # helper method for tests File.open("/etc/security/passwd", 'r') end
Where is our override script?
# File lib/puppet/provider/service/upstart.rb, line 79 def overscript @overscript ||= initscript.gsub(/\.conf$/,".override") end
# File lib/puppet/provider/file/windows.rb, line 37 def owner return :absent unless resource.stat get_owner(resource[:path]) end
# File lib/puppet/provider/file/windows.rb, line 42 def owner=(should) begin set_owner(should, resolved_path) rescue => detail raise Puppet::Error, "Failed to set owner to '#{should}': #{detail}", detail.backtrace end end
The common package name format.
# File lib/puppet/provider/package/portage.rb, line 68 def package_name @resource[:category] ? "#{@resource[:category]}/#{@resource[:name]}" : @resource[:name] end
Load the config file
# File lib/puppet/reports/tagmail.rb, line 74 def parse(text) taglists = [] text.split("\n").each do |line| taglist = emails = nil case line.chomp when /^\s*#/; next when /^\s*$/; next when /^\s*(.+)\s*:\s*(.+)\s*$/ taglist = $1 emails = $2.sub(/#.*$/,'') else raise ArgumentError, "Invalid tagmail config file" end pos = [] neg = [] taglist.sub(/\s+$/,'').split(/\s*,\s*/).each do |tag| unless tag =~ /^!?[-\w\.]+$/ raise ArgumentError, "Invalid tag #{tag.inspect}" end case tag when /^\w+/; pos << tag when /^!\w+/; neg << tag.sub("!", '') else raise Puppet::Error, "Invalid tag '#{tag}'" end end # Now split the emails emails = emails.sub(/\s+$/,'').split(/\s*,\s*/) taglists << [emails, pos, neg] end taglists end
Extracts an 2 dimensional array of commands which are in the form of command path value. The input can be
A string with one command
A string with many commands per line
An array of strings.
# File lib/puppet/provider/augeas/augeas.rb, line 67 def parse_commands(data) context = resource[:context] # Add a trailing / if it is not there if (context.length > 0) context << "/" if context[-1, 1] != "/" end data = data.split($/) if data.is_a?(String) data = data.flatten args = [] data.each do |line| line.strip! next if line.nil? || line.empty? argline = [] sc = StringScanner.new(line) cmd = sc.scan(/\w+|==|!=/) formals = COMMANDS[cmd] fail("Unknown command #{cmd}") unless formals argline << cmd narg = 0 formals.each do |f| sc.skip(/\s+/) narg += 1 if f == :path start = sc.pos nbracket = 0 inSingleTick = false inDoubleTick = false begin sc.skip(/([^\]\[\s\'"]|\.)+/) ch = sc.getch nbracket += 1 if ch == "[" nbracket -= 1 if ch == "]" inSingleTick = !inSingleTick if ch == "'" inDoubleTick = !inDoubleTick if ch == "\"" fail("unmatched [") if nbracket < 0 end until ((nbracket == 0 && !inSingleTick && !inDoubleTick && (ch =~ /\s/)) || sc.eos?) len = sc.pos - start len -= 1 unless sc.eos? unless p = sc.string[start, len] fail("missing path argument #{narg} for #{cmd}") end # Rip off any ticks if they are there. p = p[1, (p.size - 2)] if p[0,1] == "'" || p[0,1] == "\"" p.chomp!("/") if p[0,1] != '$' && p[0,1] != "/" argline << context + p else argline << p end elsif f == :string delim = sc.peek(1) if delim == "'" || delim == "\"" sc.getch argline << sc.scan(/([^\#{delim}]|(\.))*/) sc.getch else argline << sc.scan(/[^\s]+/) end fail("missing string argument #{narg} for #{cmd}") unless argline[-1] elsif f == :comparator argline << sc.scan(/(==|!=|=~|<=|>=|<|>)/) unless argline[-1] puts sc.rest fail("invalid comparator for command #{cmd}") end elsif f == :int argline << sc.scan(/\d+/).to_i elsif f== :glob argline << sc.rest end end args << argline end args end
# File lib/puppet/provider/package/nim.rb, line 213 def parse_installp_package_string(package_string) unless match = package_string.match(self.class::INSTALLP_PACKAGE_REGEX) self.fail "Unable to parse output from nimclient showres: package string does not match expected installp package string format:\n'#{package_string}'" end package_name = match.captures[0] version = match.captures[1] [package_name, version, :installp] end
Given the resource name string, parse ds_name out.
# File lib/puppet/provider/mcx/mcxcontent.rb, line 148 def parse_name(name) ds_name = name.split('/')[2] unless ds_name raise MCXContentProviderException, "Could not parse ds_name from resource name '#{name}'. Specify with ds_name parameter." end ds_name end
# File lib/puppet/provider/package/openbsd.rb, line 119 def parse_pkgconf unless @resource[:source] if Puppet::FileSystem.exist?("/etc/pkg.conf") File.open("/etc/pkg.conf", "rb").readlines.each do |line| if matchdata = line.match(/^installpath\s*=\s*(.+)\s*$/) @resource[:source] = matchdata[1] elsif matchdata = line.match(/^installpath\s*\+=\s*(.+)\s*$/) if @resource[:source].nil? @resource[:source] = matchdata[1] else @resource[:source] += ":" + matchdata[1] end end end unless @resource[:source] raise Puppet::Error, "No valid installpath found in /etc/pkg.conf and no source was set" end else raise Puppet::Error, "You must specify a package source or configure an installpath in /etc/pkg.conf" end end end
# File lib/puppet/provider/package/pkgin.rb, line 53 def parse_pkgsearch_line packages = pkgin(:search, resource[:name]).split("\n") return [] if packages.length == 1 # Remove the last three lines of help text. packages.slice!(-4, 4) pkglist = packages.map{ |line| self.class.parse_pkgin_line(line) } pkglist.select{ |package| resource[:name] == package[:name] } end
# File lib/puppet/provider/package/nim.rb, line 222 def parse_rpm_package_string(package_string) unless match = package_string.match(self.class::RPM_PACKAGE_REGEX) self.fail "Unable to parse output from nimclient showres: package string does not match expected rpm package string format:\n'#{package_string}'" end package_name = match.captures[0] version = match.captures[1] [package_name, version, :rpm] end
# File lib/puppet/provider/package/nim.rb, line 203 def parse_showres_header_line(line) # This method doesn't produce any meaningful output; it's basically just # meant to validate that the header line for the package listing output # looks sane, so we know we're dealing with the kind of output that we # are capable of handling. unless line.match(self.class::HEADER_LINE_REGEX) self.fail "Unable to parse output from nimclient showres: line does not match expected package header format:\n'#{line}'" end end
Parse the output of a `nimclient -o showres` command. Returns a two-dimensional hash, where the first-level keys are package names, the second-level keys are version number strings for all of the available version numbers for a package, and the values indicate the package type (:rpm / :installp)
# File lib/puppet/provider/package/nim.rb, line 180 def parse_showres_output(showres_output) paragraphs = split_into_paragraphs(showres_output) packages = {} paragraphs.each do |para| lines = para.split(/$/) parse_showres_header_line(lines.shift) lines.each do |l| package, version, type = parse_showres_package_line(l) packages[package] ||= {} packages[package][version] = type end end packages end
# File lib/puppet/provider/package/nim.rb, line 231 def parse_showres_package_line(line) unless match = line.match(self.class::PACKAGE_LINE_REGEX) self.fail "Unable to parse output from nimclient showres: line does not match expected package line format:\n'#{line}'" end package_type_flag = match.captures[0] package_string = match.captures[1] case package_type_flag when "I" parse_installp_package_string(package_string) when "R" parse_rpm_package_string(package_string) else self.fail "Unrecognized package type specifier: '#{package_type_flag}' in package line:\n'#{line}'" end end
Given the resource name string, parse ds_type out.
# File lib/puppet/provider/mcx/mcxcontent.rb, line 132 def parse_type(name) ds_type = name.split('/')[1] unless ds_type raise MCXContentProviderException, "Coult not parse ds_type from resource name '#{name}'. Specify with ds_type parameter." end # De-pluralize and downcase. ds_type = ds_type.chop.downcase.to_sym unless TypeMap.key? ds_type raise MCXContentProviderException, "Coult not parse ds_type from resource name '#{name}'. Specify with ds_type parameter." end ds_type end
# File lib/puppet/provider/user/useradd.rb, line 194 def passcmd age_limits = [:password_min_age, :password_max_age].select { |property| @resource.should(property) } if age_limits.empty? nil else [command(:password),age_limits.collect { |property| [flag(property), @resource.should(property)]}, @resource[:name]].flatten end end
# File lib/puppet/provider/user/user_role_add.rb, line 169 def password return :absent unless shadow_entry shadow_entry[1] end
Read in /etc/shadow, find the line for our used and rewrite it with the new pw. Smooth like 80 grit sandpaper.
Now uses the `replace_file` mechanism to minimize the chance that we lose data, but it is still terrible. We still skip platform locking, so a concurrent `vipw -s` session will have no idea we risk data loss.
# File lib/puppet/provider/user/user_role_add.rb, line 190 def password=(cryptopw) begin shadow = File.read(target_file_path) # Go Mifune loves the race here where we can lose data because # /etc/shadow changed between reading it and writing it. # --daniel 2012-02-05 Puppet::Util.replace_file(target_file_path, 0640) do |fh| shadow.each_line do |line| line_arr = line.split(':') if line_arr[0] == @resource[:name] line_arr[1] = cryptopw line_arr[2] = (Date.today - Date.new(1970,1,1)).to_i.to_s line = line_arr.join(':') end fh.print line end end rescue => detail self.fail Puppet::Error, "Could not write replace #{target_file_path}: #{detail}", detail end end
# File lib/puppet/provider/user/user_role_add.rb, line 179 def password_max_age return :absent unless shadow_entry shadow_entry[4].empty? ? -1 : shadow_entry[4] end
# File lib/puppet/provider/user/user_role_add.rb, line 174 def password_min_age return :absent unless shadow_entry shadow_entry[3].empty? ? -1 : shadow_entry[3] end
Files handle paths specially, because they just lengthen their path names, rather than including the full parent’s title each time.
# File lib/puppet/type/file.rb, line 531 def pathbuilder # We specifically need to call the method here, so it looks # up our parent in the catalog graph. if parent = parent() # We only need to behave specially when our parent is also # a file if parent.is_a?(self.class) # Remove the parent file name list = parent.pathbuilder list.pop # remove the parent's path info return list << self.ref else return super end else return [self.ref] end end
# File lib/puppet/provider/service/init.rb, line 105 def paths @paths ||= @resource[:path].find_all do |path| if File.directory?(path) true else if Puppet::FileSystem.exist?(path) self.debug "Search path #{path} is not a directory" else self.debug "Search path #{path} does not exist" end false end end end
# File lib/puppet/type/file.rb, line 666 def perform_recursion(path) Puppet::FileServing::Metadata.indirection.search( path, :links => self[:links], :recurse => (self[:recurse] == :remote ? true : self[:recurse]), :recurselimit => self[:recurselimit], :ignore => self[:ignore], :checksum_type => (self[:source] || self[:content]) ? self[:checksum] : :none, :environment => catalog.environment_instance ) end
return an array of the currently enabled #pkg_scripts @api private
# File lib/puppet/provider/service/openbsd.rb, line 197 def pkg_scripts current = load_rcconf_local_array() if scripts = current.find{|l| l =~ /^pkg_scripts/ } if match = scripts.match(/^pkg_scripts="(.*)?"(.*)?$/) match[1].split(' ') else [] end else [] end end
return the array with the current resource added @api private
# File lib/puppet/provider/service/openbsd.rb, line 212 def pkg_scripts_append [pkg_scripts(), resource[:name]].flatten.uniq end
return the array without the current resource @api private
# File lib/puppet/provider/service/openbsd.rb, line 218 def pkg_scripts_remove pkg_scripts().reject {|s| s == resource[:name] } end
# File lib/puppet/provider/package/blastwave.rb, line 11 def pkgget_with_cat(*args) Puppet::Util.withenv(:PAGER => "/usr/bin/cat") { pkgget(*args) } end
Turn our pkgutil -c listing into a hash for a single package.
# File lib/puppet/provider/package/pkgutil.rb, line 79 def pkgsingle(resource) # The --single option speeds up the execution, because it queries # the package managament system for one package only. command = ["-c", "--single", resource[:name]] self.class.parse_pkglist(run_pkgutil(resource, command), { :justme => resource[:name] }) end
finds the path for a given label and returns the path and parsed plist as an array of [path, plist]. Note plist is really a Hash here.
# File lib/puppet/provider/service/launchd.rb, line 248 def plist_from_label(label) job = self.class.jobsearch(label) job_path = job[label] if FileTest.file?(job_path) job_plist = self.class.read_plist(job_path) else raise Puppet::Error.new("Unable to parse launchd plist at path: #{job_path}") end [job_path, job_plist] end
# File lib/puppet/functions/hiera_include.rb, line 46 def post_lookup(scope, key, value) raise Puppet::ParseError, "Could not find data item #{key}" if value.nil? call_function_with_scope(scope, 'include', value) unless value.empty? end
# File lib/puppet/provider/mailalias/aliases.rb, line 13 def post_parse(record) record[:recipient] = record[:recipient].split(/\s*,\s*/).collect { |d| d.gsub(/^['"]|['"]$/, '') } record end
# File lib/puppet/provider/cron/crontab.rb, line 56 def pre_gen(record) if record[:special] and record[:special] != :absent record[:special] = "@#{record[:special]}" end Puppet::Type::Cron::ProviderCrontab::TIME_FIELDS.each do |field| if vals = record[field] and vals.is_a?(Array) record[field] = vals.join(",") end end record end
# File lib/puppet/provider/package/sun.rb, line 117 def prepare_cmd(opt) [if_have_value('-a', opt[:adminfile]), if_have_value('-r', opt[:responsefile]), if_have_value('-d', opt[:source]), opt[:cmd_options] || [], ['-n', @resource[:name]]].flatten end
# File lib/puppet/type/file.rb, line 444 def present?(current_values) super && current_values[:ensure] != :false end
Return the principals
# File lib/puppet/type/k5login.rb, line 58 def principals(dummy_argument=:work_arround_for_ruby_GC_bug) if Puppet::FileSystem.exist?(@resource[:name]) File.readlines(@resource[:name]).collect { |line| line.chomp } else :absent end end
Write the principals out to the k5login file
# File lib/puppet/type/k5login.rb, line 67 def principals=(value) write(value) end
# File lib/puppet/provider/augeas/augeas.rb, line 344 def print_errors(errors) errors.each do |errnode| error = @aug.get(errnode) debug("#{errnode} = #{error}") unless error.nil? @aug.match("#{errnode}/*").each do |subnode| subvalue = @aug.get(subnode) debug("#{subnode} = #{subvalue}") end end end
# File lib/puppet/provider/augeas/augeas.rb, line 326 def print_load_errors(path) errors = @aug.match("/augeas//error") unless errors.empty? if path && !@aug.match(path).empty? warning("Loading failed for one or more files, see debug for /augeas//error output") else debug("Loading failed for one or more files, output from /augeas//error:") end end print_errors(errors) end
# File lib/puppet/provider/augeas/augeas.rb, line 338 def print_put_errors errors = @aug.match("/augeas//error[. = 'put_failed']") debug("Put failed on one or more files, output from /augeas//error:") unless errors.empty? print_errors(errors) end
# File lib/puppet/provider/mailalias/aliases.rb, line 18 def process(line) ret = {} records = line.split(':',2) ret[:name] = records[0].strip ret[:recipient] = records[1].strip ret end
Used by the need_to_run? method to process get filters. Returns true if there is a match, false if otherwise Assumes a syntax of get /files/path [COMPARATOR] value
# File lib/puppet/provider/augeas/augeas.rb, line 215 def process_get(cmd_array) return_value = false #validate and tear apart the command fail ("Invalid command: #{cmd_array.join(" ")}") if cmd_array.length < 4 cmd = cmd_array.shift path = cmd_array.shift comparator = cmd_array.shift arg = cmd_array.join(" ") #check the value in augeas result = @aug.get(path) || '' if ['<', '<=', '>=', '>'].include? comparator and is_numeric?(result) and is_numeric?(arg) resultf = result.to_f argf = arg.to_f return_value = (resultf.send(comparator, argf)) elsif comparator == "!=" return_value = (result != arg) elsif comparator == "=~" regex = Regexp.new(arg) return_value = (result =~ regex) else return_value = (result.send(comparator, arg)) end !!return_value end
Used by the need_to_run? method to process match filters. Returns true if there is a match, false if otherwise
# File lib/puppet/provider/augeas/augeas.rb, line 246 def process_match(cmd_array) return_value = false #validate and tear apart the command fail("Invalid command: #{cmd_array.join(" ")}") if cmd_array.length < 3 cmd = cmd_array.shift path = cmd_array.shift # Need to break apart the clause clause_array = parse_commands(cmd_array.shift)[0] verb = clause_array.shift #Get the values from augeas result = @aug.match(path) || [] fail("Error trying to match path '#{path}'") if (result == -1) # Now do the work case verb when "size" fail("Invalid command: #{cmd_array.join(" ")}") if clause_array.length != 2 comparator = clause_array.shift arg = clause_array.shift case comparator when "!=" return_value = !(result.size.send(:==, arg)) else return_value = (result.size.send(comparator, arg)) end when "include" arg = clause_array.shift return_value = result.include?(arg) when "not_include" arg = clause_array.shift return_value = !result.include?(arg) when "==" begin arg = clause_array.shift new_array = eval arg return_value = (result == new_array) rescue fail("Invalid array in command: #{cmd_array.join(" ")}") end when "!=" begin arg = clause_array.shift new_array = eval arg return_value = (result != new_array) rescue fail("Invalid array in command: #{cmd_array.join(" ")}") end end !!return_value end
# File lib/puppet/provider/zpool/zpool.rb, line 14 def process_zpool_data(pool_array) if pool_array == [] return Hash.new(:absent) end #get the name and get rid of it pool = Hash.new pool[:pool] = pool_array[0] pool_array.shift tmp = [] #order matters here :( pool_array.reverse.each do |value| sym = nil case value when "spares"; sym = :spare when "logs"; sym = :log when /^mirror|^raidz1|^raidz2/; sym = value =~ /^mirror/ ? :mirror : :raidz pool[:raid_parity] = "raidz2" if value =~ /^raidz2/ else tmp << value sym = :disk if value == pool_array.first end if sym pool[sym] = pool[sym] ? pool[sym].unshift(tmp.reverse.join(' ')) : [tmp.reverse.join(' ')] tmp.clear end end pool end
We need a way to test whether a zone is in process. Our ‘ensure’ property models the static states, but we need to handle the temporary ones.
# File lib/puppet/provider/zone/solaris.rb, line 189 def processing? hash = status return false unless hash ["incomplete", "ready", "shutting_down"].include? hash[:ensure] end
# File lib/puppet/provider/user/user_role_add.rb, line 114 def profiles user_attributes[:profiles] if user_attributes end
# File lib/puppet/provider/user/user_role_add.rb, line 118 def project user_attributes[:project] if user_attributes end
Look up the current status.
# File lib/puppet/provider/maillist/mailman.rb, line 84 def properties if @property_hash.empty? @property_hash = query || {:ensure => :absent} @property_hash[:ensure] = :absent if @property_hash.empty? end @property_hash.dup end
There are some cases where all of the work does not get done on file creation/modification, so we have to do some extra checking.
# File lib/puppet/type/file.rb, line 907 def property_fix properties.each do |thing| next unless [:mode, :owner, :group, :seluser, :selrole, :seltype, :selrange].include?(thing.name) # Make sure we get a new stat objct @stat = :needs_stat currentvalue = thing.retrieve thing.sync unless thing.safe_insync?(currentvalue) end end
# File lib/puppet/type/zone.rb, line 98 def provider_sync_send(method) warned = false while provider.processing? next if warned info "Waiting for zone to finish processing" warned = true sleep 1 end provider.send(method) provider.flush() end
Remove the list and its archives.
# File lib/puppet/provider/maillist/mailman.rb, line 93 def purge destroy(true) end
Marks the resource as “being purged”.
@api public
@note This overrides the Puppet::Type method in order to handle
an edge case that has so far been observed during testig only. Without forcing the should-value for the user property to be identical to the original cron file, purging from a fixture will not work, because the user property defaults to the user running the test. It is not clear whether this scenario can apply during normal operation.
@note Also, when not forcing the should-value for the target
property, unpurged file content (such as comments) can end up being written to the default target (i.e. the current login name).
# File lib/puppet/type/cron.rb, line 459 def purging self[:target] = provider.target self[:user] = provider.target super end
Pull the current state of the list from the full list. We’re getting some double entendre here.…
# File lib/puppet/provider/maillist/mailman.rb, line 99 def query self.class.instances.each do |list| if list.name == self.name or list.name.downcase == self.name return list.properties end end nil end
query for parity and set the right string
# File lib/puppet/provider/zpool/zpool.rb, line 78 def raidzarity @resource[:raid_parity] ? @resource[:raid_parity] : "raidz1" end
Add a new setting to the rc files
# File lib/puppet/provider/service/freebsd.rb, line 87 def rc_add(service, rcvar, yesno) append = "\# Added by Puppet\n#{rcvar}_enable=\"#{yesno}\"\n" # First, try the one-file-per-service style if Puppet::FileSystem.exist?(rcconf_dir) File.open(rcconf_dir + "/#{service}", File::WRONLY | File::APPEND | File::CREAT, 0644) { |f| f << append self.debug("Appended to #{f.path}") } else # Else, check the local rc file first, but don't create it if Puppet::FileSystem.exist?(rcconf_local) File.open(rcconf_local, File::WRONLY | File::APPEND) { |f| f << append self.debug("Appended to #{f.path}") } else # At last use the standard rc.conf file File.open(rcconf, File::WRONLY | File::APPEND | File::CREAT, 0644) { |f| f << append self.debug("Appended to #{f.path}") } end end end
Edit rc files and set the service to yes/no
# File lib/puppet/provider/service/freebsd.rb, line 61 def rc_edit(yesno) service = self.service_name rcvar = self.rcvar_name self.debug("Editing rc files: setting #{rcvar} to #{yesno} for #{service}") self.rc_add(service, rcvar, yesno) if not self.rc_replace(service, rcvar, yesno) end
Try to find an existing setting in the rc files and replace the value
# File lib/puppet/provider/service/freebsd.rb, line 70 def rc_replace(service, rcvar, yesno) success = false # Replace in all files, not just in the first found with a match [rcconf, rcconf_local, rcconf_dir + "/#{service}"].each do |filename| if Puppet::FileSystem.exist?(filename) s = File.read(filename) if s.gsub!(/^(#{rcvar}(_enable)?)=\"?(YES|NO)\"?/, "\\1=\"#{yesno}\"") File.open(filename, File::WRONLY) { |f| f << s } self.debug("Replaced in #{filename}") success = true end end end success end
# File lib/puppet/provider/service/freebsd.rb, line 8 def rcconf() '/etc/rc.conf' end
# File lib/puppet/provider/service/bsd.rb, line 12 def rcconf_dir '/etc/rc.conf.d' end
# File lib/puppet/provider/service/freebsd.rb, line 9 def rcconf_local() '/etc/rc.conf.local' end
Executing an init script with the ‘rcvar’ argument returns the service name, rcvar name and whether it’s enabled/disabled
# File lib/puppet/provider/service/freebsd.rb, line 22 def rcvar rcvar = execute([self.initscript, :rcvar], :failonfail => true, :combine => false, :squelch => false) rcvar = rcvar.split("\n") rcvar.delete_if {|str| str =~ /^#\s*$/} rcvar[1] = rcvar[1].gsub(/^\$/, '') rcvar end
@api private
# File lib/puppet/provider/service/openbsd.rb, line 134 def rcvar_name self.name + '_flags' end
Extract rcvar value
# File lib/puppet/provider/service/freebsd.rb, line 51 def rcvar_value value = self.rcvar[1] self.error("No rcvar value found in rcvar") if value.nil? value = value.gsub!(/(.*)(_enable)?="?(\w+)"?/, '\3') self.error("rcvar value is empty") if value.nil? self.debug("rcvar value is #{value}") value end
@return [String] The type of the current file, cast to a string.
# File lib/puppet/type/file.rb, line 822 def read_current_type stat_info = stat if stat_info stat_info.ftype.to_s else nil end end
# File lib/puppet/provider/service/upstart.rb, line 277 def read_override_file if Puppet::FileSystem.exist?(overscript) read_script_from(overscript) else "" end end
@api private
# File lib/puppet/provider/service/openbsd.rb, line 139 def read_rcconf_local_text() if File.exists?(self.class.rcconf_local()) File.read(self.class.rcconf_local()) else [] end end
# File lib/puppet/provider/service/upstart.rb, line 348 def read_script_from(filename) File.open(filename) do |file| file.read end end
# File lib/puppet/provider/zone/solaris.rb, line 297 def ready zoneadm :ready end
Recursively generate a list of file resources, which will be used to copy remote files, manage local files, and/or make links to map to another directory.
# File lib/puppet/type/file.rb, line 553 def recurse children = (self[:recurse] == :remote) ? {} : recurse_local if self[:target] recurse_link(children) elsif self[:source] recurse_remote(children) end # If we're purging resources, then delete any resource that isn't on the # remote system. mark_children_for_purging(children) if self.purge? # REVISIT: sort_by is more efficient? result = children.values.sort { |a, b| a[:path] <=> b[:path] } remove_less_specific_files(result) end
A simple method for determining whether we should be recursing.
# File lib/puppet/type/file.rb, line 592 def recurse? self[:recurse] == true or self[:recurse] == :remote end
Recurse the target of the link.
# File lib/puppet/type/file.rb, line 597 def recurse_link(children) perform_recursion(self[:target]).each do |meta| if meta.relative_path == "." self[:ensure] = :directory next end children[meta.relative_path] ||= newchild(meta.relative_path) if meta.ftype == "directory" children[meta.relative_path][:ensure] = :directory else children[meta.relative_path][:ensure] = :link children[meta.relative_path][:target] = meta.full_path end end children end
Recurse the file itself, returning a Metadata instance for every found file.
# File lib/puppet/type/file.rb, line 616 def recurse_local result = perform_recursion(self[:path]) return {} unless result result.inject({}) do |hash, meta| next hash if meta.relative_path == "." hash[meta.relative_path] = newchild(meta.relative_path) hash end end
Recurse against our remote file.
# File lib/puppet/type/file.rb, line 628 def recurse_remote(children) sourceselect = self[:sourceselect] total = self[:source].collect do |source| next unless result = perform_recursion(source) return if top = result.find { |r| r.relative_path == "." } and top.ftype != "directory" result.each { |data| data.source = "#{source}/#{data.relative_path}" } break result if result and ! result.empty? and sourceselect == :first result end.flatten.compact # This only happens if we have sourceselect == :all unless sourceselect == :first found = [] total.reject! do |data| result = found.include?(data.relative_path) found << data.relative_path unless found.include?(data.relative_path) result end end total.each do |meta| if meta.relative_path == "." parameter(:source).metadata = meta next end children[meta.relative_path] ||= newchild(meta.relative_path) children[meta.relative_path][:source] = meta.source if meta.ftype == "file" children[meta.relative_path][:checksum] = Puppet[:digest_algorithm].to_sym end children[meta.relative_path].parameter(:source).metadata = meta end children end
# File lib/puppet/functions/reduce.rb, line 82 def reduce_with_memo(enumerable, given_memo) enum = asserted_enumerable(enumerable) enum.reduce(given_memo) {|memo, x| yield(memo, x) } end
# File lib/puppet/functions/reduce.rb, line 77 def reduce_without_memo(enumerable) enum = asserted_enumerable(enumerable) enum.reduce {|memo, x| yield(memo, x) } end
# File lib/puppet/type/component.rb, line 48 def ref reference.to_s end
# File lib/puppet/type/whit.rb, line 30 def refresh # We don't do anything with them, but we need this to show that we are # "refresh aware" and not break the chain of propagation. end
@api private
# File lib/puppet/provider/service/openbsd.rb, line 191 def remove_content_flags(content) content.reject {|l| l =~ /#{resource[:name]}_flags/ } end
@return [Boolean] True if the directory was removed @api private
# File lib/puppet/type/file.rb, line 844 def remove_directory(wanted_type) if force? debug "Removing existing directory for replacement with #{wanted_type}" FileUtils.rmtree(self[:path]) stat_needed true else notice "Not removing directory; use 'force' to override" false end end
Back up and remove the file or directory at `self`.
@param [Symbol] should The file type replacing the current content. @return [Boolean] True if the file was removed, else False @raises [fail???] If the current file isn’t one of %w{file link directory} and can’t be removed.
# File lib/puppet/type/file.rb, line 683 def remove_existing(should) wanted_type = should.to_s current_type = read_current_type if current_type.nil? return false end if can_backup?(current_type) backup_existing end if wanted_type != "link" and current_type == wanted_type return false end case current_type when "directory" return remove_directory(wanted_type) when "link", "file" return remove_file(current_type, wanted_type) else self.fail "Could not back up files of type #{current_type}" end end
@return [Boolean] if the file was removed (which is always true currently) @api private
# File lib/puppet/type/file.rb, line 858 def remove_file(current_type, wanted_type) debug "Removing existing #{current_type} for replacement with #{wanted_type}" Puppet::FileSystem.unlink(self[:path]) stat_needed true end
This is to fix bug #2296, where two files recurse over the same set of files. It’s a rare case, and when it does happen you’re not likely to have many actual conflicts, which is good, because this is a pretty inefficient implementation.
# File lib/puppet/type/file.rb, line 575 def remove_less_specific_files(files) # REVISIT: is this Windows safe? AltSeparator? mypath = self[:path].split(::File::Separator) other_paths = catalog.vertices. select { |r| r.is_a?(self.class) and r[:path] != self[:path] }. collect { |r| r[:path].split(::File::Separator) }. select { |p| p[0,mypath.length] == mypath } return files if other_paths.empty? files.reject { |file| path = file[:path].split(::File::Separator) other_paths.any? { |p| path[0,p.length] == p } } end
# File lib/puppet/provider/user/user_role_add.rb, line 126 def remove_managed_attributes managed = managed_attributes user_attributes.select { |k,v| !managed.include?(k) }.inject({}) { |hash, array| hash[array[0]] = array[1]; hash } end
# File lib/puppet/provider/service/upstart.rb, line 301 def remove_manual_from(text) text.gsub(MANUAL, "") end
# File lib/puppet/provider/service/upstart.rb, line 293 def remove_trailing_comments_from(line) line.gsub(/^(\s*[^#]*).*/, '\1') end
# File lib/puppet/provider/service/upstart.rb, line 289 def remove_trailing_comments_from_commented_line_of(line) line.gsub(/^(\s*#+\s*[^#]*).*/, '\1') end
# File lib/puppet/network/formats.rb, line 51 def render(instance) instance.to_yaml end
# File lib/puppet/face/help.rb, line 78 def render_application_help(applicationname) return Puppet::Application[applicationname].help end
# File lib/puppet/face/help.rb, line 82 def render_face_help(facename, actionname, version) face, action = load_face_help(facename, actionname, version) return template_for(face, action).result(binding) end
# File lib/puppet/network/formats.rb, line 19 def render_multiple(instances) instances.to_msgpack end
# File lib/puppet/network/formats.rb, line 75 def requiring_zlib if use_zlib? yield else raise Puppet::Error, "the zlib library is not installed or is disabled." end end
# File lib/puppet/provider/file/windows.rb, line 95 def resolved_path path = file() # under POSIX, :manage means use lchown - i.e. operate on the link return path.to_s if resource[:links] == :manage # otherwise, use chown -- that will resolve the link IFF it is a link # otherwise it will operate on the path Puppet::FileSystem.symlink?(path) ? Puppet::FileSystem.readlink(path) : path.to_s end
# File lib/puppet/type/resources.rb, line 127 def resource_type unless defined?(@resource_type) unless type = Puppet::Type.type(self[:name]) raise Puppet::DevError, "Could not find resource type" end @resource_type = type end @resource_type end
# File lib/puppet/provider/service/src.rb, line 66 def restart execute([command(:lssrc), "-Ss", @resource[:name]]).each_line do |line| args = line.split(":") next unless args[0] == @resource[:name] # Subsystems with the -K flag can get refreshed (HUPed) # While subsystems with -S (signals) must be stopped/started method = args[11] do_refresh = case method when "-K" then :true when "-S" then :false else self.fail("Unknown service communication method #{method}") end begin if do_refresh == :true execute([command(:refresh), "-s", @resource[:name]]) else self.stop self.start end return :true rescue Puppet::ExecutionFailure => detail raise Puppet::Error.new("Unable to restart service #{@resource[:name]}, error was: #{detail}", detail ) end end self.fail("No such service found") rescue Puppet::ExecutionFailure => detail raise Puppet::Error.new("Cannot get status of #{@resource[:name]}, error was: #{detail}", detail ) end
# File lib/puppet/provider/service/systemd.rb, line 55 def restartcmd [command(:systemctl), "restart", @resource[:name]] end
# File lib/puppet/type/tidy.rb, line 222 def retrieve # Our ensure property knows how to retrieve everything for us. if obj = @parameters[:ensure] return obj.retrieve else return {} end end
# File lib/puppet/provider/macauthorization/macauthorization.rb, line 241 def retrieve_value(resource_name, attribute) # We set boolean values to symbols when retrieving values raise Puppet::Error.new("Cannot find #{resource_name} in auth db") if not self.class.parsed_auth_db.has_key?(resource_name) if PuppetToNativeAttributeMap.has_key?(attribute) native_attribute = PuppetToNativeAttributeMap[attribute] else native_attribute = attribute.to_s end if self.class.parsed_auth_db[resource_name].has_key?(native_attribute) value = self.class.parsed_auth_db[resource_name][native_attribute] case value when true, :true value = :true when false, :false value = :false end @property_hash[attribute] = value return value else @property_hash.delete(attribute) return "" # so ralsh doesn't display it. end end
# File lib/puppet/provider/user/user_role_add.rb, line 106 def roles user_attributes[:roles] if user_attributes end
# File lib/puppet/provider/exec/shell.rb, line 18 def run(command, check = false) super(['/bin/sh', '-c', command], check) end
# File lib/puppet/provider/package/pkgutil.rb, line 150 def run_pkgutil(resource, *args) # Allow source to be one or more URLs pointing to a repository that all # get passed to pkgutil via one or more -t options if resource[:source] sources = [resource[:source]].flatten pkguti *[sources.map{|src| [ "-t", src ]}, *args].flatten else pkguti *args.flatten end end
preseeds answers to dpkg-set-selection from the “responsefile”
# File lib/puppet/provider/package/fink.rb, line 58 def run_preseed if response = @resource[:responsefile] and Puppet::FileSystem.exist?(response) self.info("Preseeding #{response} to debconf-set-selections") preseed response else self.info "No responsefile specified or non existant, not preseeding anything" end end
# File lib/puppet/vendor/safe_yaml/spec/safe_yaml_spec.rb, line 14 def safe_load_round_trip(object, options={}) yaml = object.to_yaml if SafeYAML::YAML_ENGINE == "psych" YAML.safe_load(yaml, nil, options) else YAML.safe_load(yaml, options) end end
The iterations and salt properties, like the password property, can only be modified by directly changing the user’s plist. Because of this fact, we have to treat the ds cache just like you would in the password= method.
# File lib/puppet/provider/user/directoryservice.rb, line 425 def salt=(value) if (Puppet::Util::Package.versioncmp(self.class.get_os_version, '10.7') > 0) assert_full_pbkdf2_password sleep 2 flush_dscl_cache users_plist = get_users_plist(@resource.name) shadow_hash_data = get_shadow_hash_data(users_plist) set_salted_pbkdf2(users_plist, shadow_hash_data, 'salt', value) flush_dscl_cache end end
@override
# File lib/puppet/vendor/semantic/spec/unit/semantic/dependency/graph_node_spec.rb, line 18 def satisfies_dependency?(node) @satisfying.include?(node) end
Scan a structure that looks like the package type ‘#install_options’ structure for all hashes that have a specific key.
@api private @param options [Array<String | Hash>, nil] The options structure. If the
options are nil an empty array will be returned.
@param key [String] The key to look for in all contained hashes @return [Array<String>] All hash values with the given key.
# File lib/puppet/provider/package/yum.rb, line 190 def scan_options(options, key) return [] if options.nil? options.inject([]) do |repos, opt| if opt.is_a? Hash and opt[key] repos << opt[key] end repos end end
# File lib/puppet/functions/scanf.rb, line 39 def scanf(data, format) result = data.scanf(format) if block_given? result = yield(result) end result end
# File lib/puppet/provider/scheduled_task/win32_taskscheduler.rb, line 493 def scheduler_days_of_week [ Win32::TaskScheduler::SUNDAY, Win32::TaskScheduler::MONDAY, Win32::TaskScheduler::TUESDAY, Win32::TaskScheduler::WEDNESDAY, Win32::TaskScheduler::THURSDAY, Win32::TaskScheduler::FRIDAY, Win32::TaskScheduler::SATURDAY ] end
# File lib/puppet/provider/scheduled_task/win32_taskscheduler.rb, line 505 def scheduler_months [ Win32::TaskScheduler::JANUARY, Win32::TaskScheduler::FEBRUARY, Win32::TaskScheduler::MARCH, Win32::TaskScheduler::APRIL, Win32::TaskScheduler::MAY, Win32::TaskScheduler::JUNE, Win32::TaskScheduler::JULY, Win32::TaskScheduler::AUGUST, Win32::TaskScheduler::SEPTEMBER, Win32::TaskScheduler::OCTOBER, Win32::TaskScheduler::NOVEMBER, Win32::TaskScheduler::DECEMBER ] end
# File lib/puppet/provider/scheduled_task/win32_taskscheduler.rb, line 522 def scheduler_occurrences [ Win32::TaskScheduler::FIRST_WEEK, Win32::TaskScheduler::SECOND_WEEK, Win32::TaskScheduler::THIRD_WEEK, Win32::TaskScheduler::FOURTH_WEEK, Win32::TaskScheduler::LAST_WEEK ] end
# File lib/puppet/provider/scheduled_task/win32_taskscheduler.rb, line 483 def scheduler_trigger_types [ Win32::TaskScheduler::TASK_TIME_TRIGGER_DAILY, Win32::TaskScheduler::TASK_TIME_TRIGGER_WEEKLY, Win32::TaskScheduler::TASK_TIME_TRIGGER_MONTHLYDATE, Win32::TaskScheduler::TASK_TIME_TRIGGER_MONTHLYDOW, Win32::TaskScheduler::TASK_TIME_TRIGGER_ONCE ] end
# File lib/puppet/provider/service/init.rb, line 120 def search(name) paths.each do |path| fqname = File.join(path,name) if Puppet::FileSystem.exist? fqname return fqname else self.debug("Could not find #{name} in #{path}") end end paths.each do |path| fqname_sh = File.join(path,"#{name}.sh") if Puppet::FileSystem.exist? fqname_sh return fqname_sh else self.debug("Could not find #{name}.sh in #{path}") end end raise Puppet::Error, "Could not find init script for '#{name}'" end
# File lib/puppet/provider/yumrepo/inifile.rb, line 296 def section(name) self.class.section(name) end
# File lib/puppet/provider/selmodule/semodule.rb, line 67 def selmod_name_to_filename if @resource[:selmodulepath] return @resource[:selmodulepath] else return "#{@resource[:selmoduledir]}/#{@resource[:name]}.pp" end end
# File lib/puppet/provider/selmodule/semodule.rb, line 75 def selmod_readnext (handle) len = handle.read(4).unpack('V')[0] handle.read(len) end
# File lib/puppet/provider/selmodule/semodule.rb, line 80 def selmodversion_file magic = 0xF97CFF8F filename = selmod_name_to_filename mod = File.new(filename, "r") (hdr, ver, numsec) = mod.read(12).unpack('VVV') raise Puppet::Error, "Found #{hdr} instead of magic #{magic} in #{filename}" if hdr != magic raise Puppet::Error, "Unknown policy file version #{ver} in #{filename}" if ver != 1 # Read through (and throw away) the file section offsets, and also # the magic header for the first section. mod.read((numsec + 1) * 4) ## Section 1 should be "SE Linux Module" selmod_readnext(mod) selmod_readnext(mod) # Skip past the section headers mod.read(14) # Module name selmod_readnext(mod) # At last! the version v = selmod_readnext(mod) self.debug "file version #{v}" v end
# File lib/puppet/provider/selmodule/semodule.rb, line 116 def selmodversion_loaded lines = () begin execpipe("#{command(:semodule)} --list") do |output| output.each_line do |line| line.chomp! bits = line.split if bits[0] == @resource[:name] self.debug "load version #{bits[1]}" return bits[1] end end end rescue Puppet::ExecutionFailure raise Puppet::ExecutionFailure, "Could not list policy modules: #{lines.join(' ').chomp!}", $!.backtrace end nil end
Send the email reports.
# File lib/puppet/reports/tagmail.rb, line 132 def send(reports) pid = Puppet::Util.safe_posix_fork do if Puppet[:smtpserver] != "none" begin Net::SMTP.start(Puppet[:smtpserver], Puppet[:smtpport], Puppet[:smtphelo]) do |smtp| reports.each do |emails, messages| smtp.open_message_stream(Puppet[:reportfrom], *emails) do |p| p.puts "From: #{Puppet[:reportfrom]}" p.puts "Subject: Puppet Report for #{self.host}" p.puts "To: " + emails.join(", ") p.puts "Date: #{Time.now.rfc2822}" p.puts p.puts messages end end end rescue => detail message = "Could not send report emails through smtp: #{detail}" Puppet.log_exception(detail, message) raise Puppet::Error, message, detail.backtrace end elsif Puppet[:sendmail] != "" begin reports.each do |emails, messages| # We need to open a separate process for every set of email addresses IO.popen(Puppet[:sendmail] + " " + emails.join(" "), "w") do |p| p.puts "From: #{Puppet[:reportfrom]}" p.puts "Subject: Puppet Report for #{self.host}" p.puts "To: " + emails.join(", ") p.puts p.puts messages end end rescue => detail message = "Could not send report emails via sendmail: #{detail}" Puppet.log_exception(detail, message) raise Puppet::Error, message, detail.backtrace end else raise Puppet::Error, "SMTP server is unset and could not find sendmail" end end # Don't bother waiting for the pid to return. Process.detach(pid) end
returns the full path of this service when enabled (ie in the service directory)
# File lib/puppet/provider/service/daemontools.rb, line 104 def service File.join(self.servicedir, resource[:name]) end
Extract service name
# File lib/puppet/provider/service/freebsd.rb, line 41 def service_name extract_value_name('service', 0, /# (.*)/, '\1') end
find the service dir on this node
# File lib/puppet/provider/service/runit.rb, line 57 def servicedir unless @servicedir ["/service", "/etc/service","/var/service"].each do |path| if Puppet::FileSystem.exist?(path) @servicedir = path break end end raise "Could not find service directory" unless @servicedir end @servicedir end
# File lib/puppet/provider/augeas/augeas.rb, line 322 def set_augeas_save_mode(mode) @aug.set("/augeas/save", mode) end
@api private
# File lib/puppet/provider/service/openbsd.rb, line 166 def set_content_flags(content,flags) unless content.is_a? Array debug "content must be an array at flags" return "" else content.reject! {|l| l.nil? } end if flags.nil? or flags.size == 0 if in_base? append = resource[:name] + '_flags=""' end else append = resource[:name] + '_flags="' + flags + '"' end if content.find {|l| l =~ /#{resource[:name]}_flags/ }.nil? content << append else content.map {|l| l.gsub!(/^#{resource[:name]}_flags="(.*)?"(.*)?$/, append) } end content end
Modify the content array to contain the requsted #pkg_scripts line and retun the resulting array @api private
# File lib/puppet/provider/service/openbsd.rb, line 225 def set_content_scripts(content,scripts) unless content.is_a? Array debug "content must be an array at scripts" return "" else content.reject! {|l| l.nil? } end scripts_line = 'pkg_scripts="' + scripts.join(' ') + '"' if content.find {|l| l =~ /^pkg_scripts/ }.nil? content << scripts_line else # Replace the found pkg_scripts line with our own content.each_with_index {|l,i| if l =~ /^pkg_scripts/ content[i] = scripts_line end } end content end
# File lib/puppet/provider/yumrepo/inifile.rb, line 290 def set_property(property, value) value = (value == :absent ? nil : value) current_section[property.to_s] = value @property_hash[property] = value end
# File lib/puppet/provider/macauthorization/macauthorization.rb, line 179 def set_right(name, values) # Both creates and modifies rights as it simply overwrites them. # The security binary only allows for writes using stdin, so we # dump the values to a tempfile. values = convert_plist_to_native_attributes(values) tmp = Tempfile.new('puppet_macauthorization') begin Plist::Emit.save_plist(values, tmp.path) cmds = [] cmds << :security << "authorizationdb" << "write" << name execute(cmds, :failonfail => false, :combine => false, :stdinfile => tmp.path.to_s) rescue Errno::EACCES => e raise Puppet::Error.new("Cannot save right to #{tmp.path}: #{e}", e) ensure tmp.close tmp.unlink end end
# File lib/puppet/provider/macauthorization/macauthorization.rb, line 198 def set_rule(name, values) # Both creates and modifies rules as it overwrites the entry in the # rules dictionary. Unfortunately the security binary doesn't # support modifying rules at all so we have to twiddle the whole # plist... :( See Apple Bug #6386000 values = convert_plist_to_native_attributes(values) authdb = Plist::parse_xml(AuthDB) authdb["rules"][name] = values begin Plist::Emit.save_plist(authdb, AuthDB) rescue raise Puppet::Error.new("Error writing to: #{AuthDB}") end end
This method accepts a passed value and one of three fields: ‘salt’, ‘entropy’, or ‘iterations’. These fields correspond with the fields utilized in a PBKDF2 password hashing system (see en.wikipedia.org/wiki/PBKDF2 ) where ‘entropy’ is the password hash, ‘salt’ is the password hash salt value, and ‘iterations’ is an integer recommended to be > 10,000. The remaining arguments are the user’s plist itself, and the shadow_hash_data hash containing the existing PBKDF2 values.
# File lib/puppet/provider/user/directoryservice.rb, line 624 def set_salted_pbkdf2(users_plist, shadow_hash_data, field, value) shadow_hash_data = Hash.new unless shadow_hash_data shadow_hash_data['SALTED-SHA512-PBKDF2'] = Hash.new unless shadow_hash_data['SALTED-SHA512-PBKDF2'] case field when 'salt', 'entropy' shadow_hash_data['SALTED-SHA512-PBKDF2'][field] = new_stringio_object unless shadow_hash_data['SALTED-SHA512-PBKDF2'][field] shadow_hash_data['SALTED-SHA512-PBKDF2'][field].string = base64_decode_string(value) when 'iterations' shadow_hash_data['SALTED-SHA512-PBKDF2'][field] = Integer(value) else raise Puppet::Error "Puppet has tried to set an incorrect field for the 'SALTED-SHA512-PBKDF2' hash. Acceptable fields are 'salt', 'entropy', or 'iterations'." end # on 10.8, this field *must* contain 8 stars, or authentication will # fail. users_plist['passwd'] = ('*' * 8) # Convert shadow_hash_data to a binary plist, and call the # set_shadow_hash_data method to serialize and write the data # back to the user's plist. binary_plist = self.class.convert_xml_to_binary(shadow_hash_data) set_shadow_hash_data(users_plist, binary_plist) end
Puppet requires a salted-sha512 password hash for 10.7 users to be passed in Hex, but the embedded plist stores that value as a Base64 encoded string. This method converts the string and calls the #set_shadow_hash_data method to serialize and write the plist to disk.
# File lib/puppet/provider/user/directoryservice.rb, line 606 def set_salted_sha512(users_plist, shadow_hash_data, value) unless shadow_hash_data shadow_hash_data = Hash.new shadow_hash_data['SALTED-SHA512'] = new_stringio_object end shadow_hash_data['SALTED-SHA512'].string = base64_decode_string(value) binary_plist = self.class.convert_xml_to_binary(shadow_hash_data) set_shadow_hash_data(users_plist, binary_plist) end
This method will embed the binary plist data comprising the user’s password hash (and Salt/Iterations value if the OS is 10.8 or greater) into the ShadowHashData key of the user’s plist.
# File lib/puppet/provider/user/directoryservice.rb, line 577 def set_shadow_hash_data(users_plist, binary_plist) if users_plist.has_key?('ShadowHashData') users_plist['ShadowHashData'][0].string = binary_plist else users_plist['ShadowHashData'] = [new_stringio_object(binary_plist)] end write_users_plist_to_disk(users_plist) end
Set the checksum, from another property. There are multiple properties that modify the contents of a file, and they need the ability to make sure that the checksum value is in sync.
# File lib/puppet/type/file.rb, line 719 def setchecksum(sum = nil) if @parameters.include? :checksum if sum @parameters[:checksum].checksum = sum else # If they didn't pass in a sum, then tell checksum to # figure it out. currentvalue = @parameters[:checksum].retrieve @parameters[:checksum].checksum = currentvalue end end end
Execute a configuration string. Can’t be private because it’s called by the properties.
# File lib/puppet/provider/zone/solaris.rb, line 249 def setconfig(str) add_cmd str end
Take the results of a listing and set everything appropriately.
# File lib/puppet/type/zone.rb, line 367 def setstatus(hash) prophash = {} hash.each do |param, value| next if param == :name case self.class.attrtype(param) when :property # Only try to provide values for the properties we're managing prop = self.property(param) prophash[prop] = value if prop else self[param] = value end end prophash end
JJM Yes, this is not DRY at all. Because of the code blocks autorequire must be done this way. I think.
# File lib/puppet/type/mcx.rb, line 74 def setup_autorequire(type) # value returns a Symbol ds_type = value(:ds_type) ds_name = value(:ds_name) if ds_type == type rval = [ ds_name.to_s ] else rval = [ ] end rval end
# File lib/puppet/provider/service/smf.rb, line 22 def setupservice if resource[:manifest] [command(:svcs), "-l", @resource[:name]] if $CHILD_STATUS.exitstatus == 1 Puppet.notice "Importing #{@resource[:manifest]} for #{@resource[:name]}" svccfg :import, resource[:manifest] end end rescue Puppet::ExecutionFailure => detail raise Puppet::Error.new( "Cannot config #{self.name} to enable it: #{detail}", detail ) end
Read in /etc/shadow, find the line for this user (skipping comments, because who knows) and return it No abstraction, all esoteric knowledge of file formats, yay
# File lib/puppet/provider/user/user_role_add.rb, line 160 def shadow_entry return @shadow_entry if defined? @shadow_entry @shadow_entry = File.readlines(target_file_path). reject { |r| r =~ /^[^\w]/ }. # PUP-229 dont suppress the empty fields collect { |l| l.chomp.split(':', -1) }. find { |user, _| user == @resource[:name] } end
# File lib/puppet/provider/user/useradd.rb, line 83 def shell=(value) check_valid_shell set("shell", value) end
# File lib/puppet/provider/package/msi.rb, line 122 def shell_quote(value) value.include?(' ') ? %Q["#{value.gsub(/"/, '\"')}"] : value end
# File lib/puppet/type/cron.rb, line 227 def should if @should if @should.is_a? Array @should[0] else devfail "command is not an array" end else nil end end
Should this thing be a normal file? This is a relatively complex way of determining whether we’re trying to create a normal file, and it’s here so that the logic isn’t visible in the content property.
# File lib/puppet/type/file.rb, line 735 def should_be_file? return true if self[:ensure] == :file # I.e., it's set to something like "directory" return false if e = self[:ensure] and e != :present # The user doesn't really care, apparently if self[:ensure] == :present return true unless s = stat return(s.ftype == "file" ? true : false) end # If we've gotten here, then :ensure isn't set return true if self[:content] return true if stat and stat.ftype == "file" false end
# File lib/puppet/provider/user/aix.rb, line 285 def should_include?(key, managed_keys) !self.class.attribute_mapping_from.include?(key) and !self.class.attribute_ignore.include?(key) and managed_keys.include?(key) end
# File lib/puppet/type/cron.rb, line 357 def should_to_s(newvalue = @should) if newvalue newvalue.join(",") else nil end end
Essentially stolen from: github.com/rails/rails/blob/3-2-stable/activesupport/lib/active_support/core_ext/kernel/reporting.rb#L10-25
# File lib/puppet/vendor/safe_yaml/spec/safe_yaml_spec.rb, line 8 def silence_warnings $VERBOSE = nil; yield ensure $VERBOSE = true end
The hidden singleton lurks behind everyone
# File lib/puppet/util/metaid.rb, line 3 def singleton_class; class << self; self; end; end
# File lib/puppet/functions/slice.rb, line 65 def slice_Common(o, slice_size, filler, pblock) serving_size = asserted_slice_serving_size(pblock, slice_size) enumerator = o.each_slice(slice_size) result = [] if serving_size == 1 begin if pblock loop do pblock.call(enumerator.next) end else loop do result << enumerator.next end end rescue StopIteration end else begin loop do a = enumerator.next if a.size < serving_size a = a.dup.fill(filler, a.length...serving_size) end pblock.call(*a) end rescue StopIteration end end if pblock o else result end end
# File lib/puppet/functions/slice.rb, line 59 def slice_Enumerable(enumerable, slice_size, &pblock) enum = asserted_enumerable(enumerable) result = slice_Common(enum, slice_size, nil, block_given? ? pblock : nil) block_given? ? enumerable : result end
# File lib/puppet/functions/slice.rb, line 54 def slice_Hash(hash, slice_size, &pblock) result = slice_Common(hash, slice_size, [], block_given? ? pblock : nil) block_given? ? hash : result end
# File lib/puppet/vendor/semantic/spec/unit/semantic/dependency/module_release_spec.rb, line 5 def source @source ||= Semantic::Dependency::Source.new end
# File lib/puppet/type/cron.rb, line 250 def specials %w{reboot yearly annually monthly weekly daily midnight hourly absent} + [ :absent ] end
This method basically just splits the multi-line input string into chunks based on lines that contain nothing but whitespace. It also strips any leading or trailing whitespace (including newlines) from the resulting strings and then returns them as an array.
# File lib/puppet/provider/package/nim.rb, line 199 def split_into_paragraphs(showres_output) showres_output.split(/^\s*$/).map { |p| p.strip! } end
# File lib/puppet/provider/package/hpux.rb, line 41 def standard_args ["-x", "mount_all_filesystems=false"] end
Run the ‘start’ parameter command, or the specified ‘startcmd’.
# File lib/puppet/provider/service/base.rb, line 64 def start ucommand(:start) end
# File lib/puppet/provider/service/systemd.rb, line 59 def startcmd [command(:systemctl), "start", @resource[:name]] end
# File lib/puppet/type/tidy.rb, line 313 def stat(path) begin Puppet::FileSystem.lstat(path) rescue Errno::ENOENT => error info "File does not exist" return nil rescue Errno::EACCES => error warning "Could not stat; permission denied" return nil end end
# File lib/puppet/type/file.rb, line 865 def stat_needed @stat = :needs_stat end
# File lib/puppet/provider/service/systemd.rb, line 40 def status begin systemctl("is-active", @resource[:name]) rescue Puppet::ExecutionFailure return :stopped end return :running end
There is no default command, which causes other methods to be used
# File lib/puppet/provider/service/base.rb, line 60 def statuscmd end
Stop the service. If a ‘stop’ parameter is specified, it takes precedence; otherwise checks if the object responds to a ‘stopcmd’ method, and if so runs that; otherwise, looks for the process in the process table. This method will generally not be overridden by submodules.
# File lib/puppet/provider/service/base.rb, line 84 def stop if @resource[:stop] or stopcmd ucommand(:stop) else pid = getpid unless pid self.info "#{self.name} is not running" return false end begin output = kill pid rescue Puppet::ExecutionFailure @resource.fail Puppet::Error, "Could not kill #{self.name}, PID #{pid}: #{output}", $! end return true end end
# File lib/puppet/provider/service/systemd.rb, line 63 def stopcmd [command(:systemctl), "stop", @resource[:name]] end
# File lib/puppet/vendor/semantic/spec/unit/semantic/version_spec.rb, line 6 def subject(str) Semantic::Version.parse(str) end
# File lib/puppet/type/file/checksum.rb, line 18 def sum(content) type = digest_algorithm() "{#{type}}" + send(type, content) end
# File lib/puppet/type/file/checksum.rb, line 23 def sum_file(path) type = digest_algorithm() method = type.to_s + "_file" "{#{type}}" + send(method, path).to_s end
# File lib/puppet/type/file/checksum.rb, line 29 def sum_stream(&block) type = digest_algorithm() method = type.to_s + "_stream" checksum = send(method, &block) "{#{type}}#{checksum}" end
# File lib/puppet/network/formats.rb, line 60 def supported?(klass) true end
Actually execute the command.
# File lib/puppet/type/augeas.rb, line 196 def sync @resource.provider.execute_changes end
# File lib/puppet/provider/selmodule/semodule.rb, line 33 def syncversion self.debug "Checking syncversion on #{@resource[:name]}" loadver = selmodversion_loaded if(loadver) then filever = selmodversion_file if (filever == loadver) return :true end end :false end
# File lib/puppet/provider/selmodule/semodule.rb, line 47 def syncversion= (dosync) execoutput("#{command(:semodule)} --upgrade #{selmod_name_to_filename}") rescue Puppet::ExecutionFailure => detail raise Puppet::Error, "Could not upgrade policy module: #{detail}", detail.backtrace end
# File lib/puppet/type/resources.rb, line 159 def system_users %w{root nobody bin noaccess daemon sys} end
This helper makes it possible to test this on stub data without having to do too many crazy things!
# File lib/puppet/provider/user/user_role_add.rb, line 153 def target_file_path "/etc/shadow" end
# File lib/puppet/provider/scheduled_task/win32_taskscheduler.rb, line 30 def task return @task if @task @task ||= Win32::TaskScheduler.new @task.activate(resource[:name] + '.job') if exists? @task end
# File lib/puppet/face/help.rb, line 109 def template_for(face, action) if action.nil? erb('face.erb') else erb('action.erb') end end
A simple wrapper so execution failures are a bit more informative.
# File lib/puppet/provider/service/service.rb, line 23 def texecute(type, command, fof = true, squelch = false, combine = true) begin execute(command, :failonfail => fof, :override_locale => false, :squelch => squelch, :combine => combine) rescue Puppet::ExecutionFailure => detail @resource.fail Puppet::Error, "Could not #{type} #{@resource.ref}: #{detail}", detail end nil end
Does a given path match our glob patterns, if any? Return true if no patterns have been provided.
# File lib/puppet/type/tidy.rb, line 85 def tidy?(path, stat) basename = File.basename(path) flags = File::FNM_DOTMATCH | File::FNM_PATHNAME return(value.find {|pattern| File.fnmatch(pattern, basename, flags) } ? true : false) end
Unfortunately, RRD does not deal well with changing lists of values, so we have to pick a list of values and stick with it. In this case, that means we record the total time, the config time, and that’s about it. We should probably send each type’s time as a separate metric.
# File lib/puppet/reports/rrdgraph.rb, line 124 def timeclean(metric) metric.values = metric.values.find_all { |name, label, value| ['total', 'config_retrieval'].include?(name.to_s) } end
We want our title to just be the whole reference, rather than @title.
# File lib/puppet/type/component.rb, line 53 def title ref end
# File lib/puppet/type/component.rb, line 57 def title=(str) @reference = Puppet::Resource.new(str) end
# File lib/puppet/provider/mailalias/aliases.rb, line 26 def to_line(record) dest = record[:recipient].collect do |d| # Quote aliases that have non-alpha chars if d =~ /[^-\w@.]/ '"%s"' % d else d end end.join(",") "#{record[:name]}: #{dest}" end
# File lib/puppet/util/log/destinations.rb, line 225 def to_native(level) case level when :debug,:info,:notice [self.class::EVENTLOG_INFORMATION_TYPE, 0x01] when :warning [self.class::EVENTLOG_WARNING_TYPE, 0x02] when :err,:alert,:emerg,:crit [self.class::EVENTLOG_ERROR_TYPE, 0x03] end end
# File lib/puppet/type/file.rb, line 783 def to_resource resource = super resource.delete(:target) if resource[:target] == :notlink resource end
Hide the fact that we’re a whit from logs.
I hate you, milkman whit. You are so painful, so often.
In this case the memoized version means we generate a new string about 1.9 percent of the time, and we allocate about 1.6MB less memory, and generate a whole lot less GC churn.
That number probably goes up at least O(n) with the complexity of your catalog, and I suspect beyond that, because that is, like, 10,000 calls for 200 distinct objects. Even with just linear, that is a constant factor of, like, 50n. –daniel 2012-07-17
# File lib/puppet/type/whit.rb, line 25 def to_s @to_s ||= name.sub(/^completed_|^admissible_/, "") end
# File lib/puppet/util/monkey_patches.rb, line 37 def to_yaml(ignored=nil) ZAML.dump(self) end
# File lib/puppet/util/zaml.rb, line 177 def to_yaml_properties instance_variables.map(&:to_sym) end
# File lib/puppet/util/zaml.rb, line 195 def to_zaml(z) z.first_time_only(self) { z.emit(zamlized_class_name(Object)) z.nested { instance_variables = to_yaml_properties if instance_variables.empty? z.emit(" {}") else instance_variables.each { |v| z.nl v.to_s[1..-1].to_zaml(z) # Remove leading '@' z.emit(': ') yaml_property_munge(instance_variable_get(v)).to_zaml(z) } end } } end
# File lib/puppet/provider/user/user_role_add.rb, line 74 def transition(type) cmd = [command(:modify)] cmd << "-K" << "type=#{type}" cmd += add_properties cmd << @resource[:name] end
# File lib/puppet/provider/scheduled_task/win32_taskscheduler.rb, line 276 def translate_hash_to_trigger(puppet_trigger) trigger = dummy_time_trigger if puppet_trigger['enabled'] == false trigger['flags'] |= Win32::TaskScheduler::TASK_TRIGGER_FLAG_DISABLED else trigger['flags'] &= ~Win32::TaskScheduler::TASK_TRIGGER_FLAG_DISABLED end extra_keys = puppet_trigger.keys.sort - ['index', 'enabled', 'schedule', 'start_date', 'start_time', 'every', 'months', 'on', 'which_occurrence', 'day_of_week', 'minutes_interval', 'minutes_duration'] self.fail "Unknown trigger option(s): #{Puppet::Parameter.format_value_for_display(extra_keys)}" unless extra_keys.empty? self.fail "Must specify 'start_time' when defining a trigger" unless puppet_trigger['start_time'] case puppet_trigger['schedule'] when 'daily' trigger['trigger_type'] = Win32::TaskScheduler::DAILY trigger['type'] = { 'days_interval' => Integer(puppet_trigger['every'] || 1) } when 'weekly' trigger['trigger_type'] = Win32::TaskScheduler::WEEKLY trigger['type'] = { 'weeks_interval' => Integer(puppet_trigger['every'] || 1) } trigger['type']['days_of_week'] = if puppet_trigger['day_of_week'] bitfield_from_days_of_week(puppet_trigger['day_of_week']) else scheduler_days_of_week.inject(0) {|day_flags,day| day_flags |= day} end when 'monthly' trigger['type'] = { 'months' => bitfield_from_months(puppet_trigger['months'] || (1..12).to_a), } if puppet_trigger.keys.include?('on') if puppet_trigger.has_key?('day_of_week') or puppet_trigger.has_key?('which_occurrence') self.fail "Neither 'day_of_week' nor 'which_occurrence' can be specified when creating a monthly date-based trigger" end trigger['trigger_type'] = Win32::TaskScheduler::MONTHLYDATE trigger['type']['days'] = bitfield_from_days(puppet_trigger['on']) elsif puppet_trigger.keys.include?('which_occurrence') or puppet_trigger.keys.include?('day_of_week') self.fail 'which_occurrence cannot be specified as an array' if puppet_trigger['which_occurrence'].is_a?(Array) %w{day_of_week which_occurrence}.each do |field| self.fail "#{field} must be specified when creating a monthly day-of-week based trigger" unless puppet_trigger.has_key?(field) end trigger['trigger_type'] = Win32::TaskScheduler::MONTHLYDOW trigger['type']['weeks'] = occurrence_name_to_constant(puppet_trigger['which_occurrence']) trigger['type']['days_of_week'] = bitfield_from_days_of_week(puppet_trigger['day_of_week']) else self.fail "Don't know how to create a 'monthly' schedule with the options: #{puppet_trigger.keys.sort.join(', ')}" end when 'once' self.fail "Must specify 'start_date' when defining a one-time trigger" unless puppet_trigger['start_date'] trigger['trigger_type'] = Win32::TaskScheduler::ONCE else self.fail "Unknown schedule type: #{puppet_trigger["schedule"].inspect}" end integer_interval = -1 if puppet_trigger['minutes_interval'] integer_interval = Integer(puppet_trigger['minutes_interval']) self.fail 'minutes_interval must be an integer greater or equal to 0' if integer_interval < 0 trigger['minutes_interval'] = integer_interval end integer_duration = -1 if puppet_trigger['minutes_duration'] integer_duration = Integer(puppet_trigger['minutes_duration']) self.fail 'minutes_duration must be an integer greater than minutes_interval and equal to or greater than 0' if integer_duration <= integer_interval && integer_duration != 0 trigger['minutes_duration'] = integer_duration end if integer_interval > 0 && integer_duration == -1 integer_duration = MINUTES_IN_DAY trigger['minutes_duration'] = MINUTES_IN_DAY end if integer_interval >= integer_duration && integer_interval > 0 self.fail 'minutes_interval cannot be set without minutes_duration also being set to a number greater than 0' end if start_date = puppet_trigger['start_date'] start_date = Date.parse(start_date) self.fail "start_date must be on or after 1753-01-01" unless start_date >= Date.new(1753, 1, 1) trigger['start_year'] = start_date.year trigger['start_month'] = start_date.month trigger['start_day'] = start_date.day end start_time = Time.parse(puppet_trigger['start_time']) trigger['start_hour'] = start_time.hour trigger['start_minute'] = start_time.min trigger end
# File lib/puppet/provider/scheduled_task/win32_taskscheduler.rb, line 66 def trigger return @triggers if @triggers @triggers = [] task.trigger_count.times do |i| trigger = begin task.trigger(i) rescue Win32::TaskScheduler::Error # Win32::TaskScheduler can't handle all of the # trigger types Windows uses, so we need to skip the # unhandled types to prevent "puppet resource" from # blowing up. nil end next unless trigger and scheduler_trigger_types.include?(trigger['trigger_type']) puppet_trigger = {} case trigger['trigger_type'] when Win32::TaskScheduler::TASK_TIME_TRIGGER_DAILY puppet_trigger['schedule'] = 'daily' puppet_trigger['every'] = trigger['type']['days_interval'].to_s when Win32::TaskScheduler::TASK_TIME_TRIGGER_WEEKLY puppet_trigger['schedule'] = 'weekly' puppet_trigger['every'] = trigger['type']['weeks_interval'].to_s puppet_trigger['day_of_week'] = days_of_week_from_bitfield(trigger['type']['days_of_week']) when Win32::TaskScheduler::TASK_TIME_TRIGGER_MONTHLYDATE puppet_trigger['schedule'] = 'monthly' puppet_trigger['months'] = months_from_bitfield(trigger['type']['months']) puppet_trigger['on'] = days_from_bitfield(trigger['type']['days']) when Win32::TaskScheduler::TASK_TIME_TRIGGER_MONTHLYDOW puppet_trigger['schedule'] = 'monthly' puppet_trigger['months'] = months_from_bitfield(trigger['type']['months']) puppet_trigger['which_occurrence'] = occurrence_constant_to_name(trigger['type']['weeks']) puppet_trigger['day_of_week'] = days_of_week_from_bitfield(trigger['type']['days_of_week']) when Win32::TaskScheduler::TASK_TIME_TRIGGER_ONCE puppet_trigger['schedule'] = 'once' end puppet_trigger['start_date'] = self.class.normalized_date("#{trigger['start_year']}-#{trigger['start_month']}-#{trigger['start_day']}") puppet_trigger['start_time'] = self.class.normalized_time("#{trigger['start_hour']}:#{trigger['start_minute']}") puppet_trigger['enabled'] = trigger['flags'] & Win32::TaskScheduler::TASK_TRIGGER_FLAG_DISABLED == 0 puppet_trigger['minutes_interval'] = trigger['minutes_interval'] ||= 0 puppet_trigger['minutes_duration'] = trigger['minutes_duration'] ||= 0 puppet_trigger['index'] = i @triggers << puppet_trigger end @triggers end
# File lib/puppet/provider/scheduled_task/win32_taskscheduler.rb, line 163 def trigger=(value) desired_triggers = value.is_a?(Array) ? value : [value] current_triggers = trigger.is_a?(Array) ? trigger : [trigger] extra_triggers = [] desired_to_search = desired_triggers.dup current_triggers.each do |current| if found = desired_to_search.find {|desired| triggers_same?(current, desired)} desired_to_search.delete(found) else extra_triggers << current['index'] end end needed_triggers = [] current_to_search = current_triggers.dup desired_triggers.each do |desired| if found = current_to_search.find {|current| triggers_same?(current, desired)} current_to_search.delete(found) else needed_triggers << desired end end extra_triggers.reverse_each do |index| task.delete_trigger(index) end needed_triggers.each do |trigger_hash| # Even though this is an assignment, the API for # Win32::TaskScheduler ends up appending this trigger to the # list of triggers for the task, while #add_trigger is only able # to replace existing triggers. *shrug* task.trigger = translate_hash_to_trigger(trigger_hash) end end
# File lib/puppet/provider/scheduled_task/win32_taskscheduler.rb, line 127 def trigger_insync?(current, should) should = [should] unless should.is_a?(Array) current = [current] unless current.is_a?(Array) return false unless current.length == should.length current_in_sync = current.all? do |c| should.any? {|s| triggers_same?(c, s)} end should_in_sync = should.all? do |s| current.any? {|c| triggers_same?(c,s)} end current_in_sync && should_in_sync end
# File lib/puppet/provider/scheduled_task/win32_taskscheduler.rb, line 234 def triggers_same?(current_trigger, desired_trigger) return false unless current_trigger['schedule'] == desired_trigger['schedule'] return false if current_trigger.has_key?('enabled') && !current_trigger['enabled'] desired = desired_trigger.dup desired['start_date'] ||= current_trigger['start_date'] if current_trigger.has_key?('start_date') desired['every'] ||= current_trigger['every'] if current_trigger.has_key?('every') desired['months'] ||= current_trigger['months'] if current_trigger.has_key?('months') desired['on'] ||= current_trigger['on'] if current_trigger.has_key?('on') desired['day_of_week'] ||= current_trigger['day_of_week'] if current_trigger.has_key?('day_of_week') translate_hash_to_trigger(current_trigger) == translate_hash_to_trigger(desired) end
# File lib/puppet/face/node/clean.rb, line 150 def type_is_ensurable(resource) if (type = Puppet::Type.type(resource.restype)) && type.validattr?(:ensure) return true else type = environment.known_resource_types.find_definition('', resource.restype) return true if type && type.arguments.keys.include?('ensure') end return false end
Use either a specified command or the default for our provider.
# File lib/puppet/provider/service/service.rb, line 33 def ucommand(type, fof = true) if c = @resource[type] cmd = [c] else cmd = [send("#{type}cmd")].flatten end texecute(type, cmd, fof) end
# File lib/puppet/provider/user/windows_adsi.rb, line 88 def uid Puppet::Util::Windows::SID.name_to_sid(@resource[:name]) end
We use users and groups interchangeably, so use the same methods for both (the type expects different methods, so we have to oblige).
# File lib/puppet/provider/user/windows_adsi.rb, line 92 def uid=(value) fail "uid is read-only" end
# File lib/puppet/provider/service/upstart.rb, line 297 def unbalanced_parens_on(line) line.count('(') - line.count(')') end
# File lib/puppet/provider/service/upstart.rb, line 285 def uncomment(line) line.gsub(/^(\s*)#+/, '\1') end
# File lib/puppet/provider/service/upstart.rb, line 318 def uncomment_start_block_in(text) parens = 0 text.lines.map do |line| if line.match(COMMENTED_START_ON) || parens > 0 parens += unbalanced_parens_on(remove_trailing_comments_from_commented_line_of(line)) uncomment(line) else line end end.join('') end
# File lib/puppet/provider/zone/solaris.rb, line 305 def unconfigure zonecfg :delete, "-F" end
# File lib/puppet/face/node/clean.rb, line 118 def unexport(node) # fetch all exported resource query = {:include => {:param_values => :param_name}} query[:conditions] = [ "exported=? AND host_id=?", true, node.id ] Puppet::Rails::Resource.find(:all, query).each do |resource| if type_is_ensurable(resource) line = 0 param_name = Puppet::Rails::ParamName.find_or_create_by_name("ensure") if ensure_param = resource.param_values.find( :first, :conditions => [ 'param_name_id = ?', param_name.id ] ) line = ensure_param.line.to_i Puppet::Rails::ParamValue.delete(ensure_param.id); end # force ensure parameter to "absent" resource.param_values.create( :value => "absent", :line => line, :param_name => param_name ) Puppet.info("#{resource.name} has been marked as \"absent\"") end end end
# File lib/puppet/provider/package/dpkg.rb, line 157 def unhold Tempfile.open('puppet_dpkg_set_selection') do |tmpfile| tmpfile.write("#{@resource[:name]} install\n") tmpfile.flush execute([:dpkg, "--set-selections"], :failonfail => false, :combine => false, :stdinfile => tmpfile.path.to_s) end end
# File lib/puppet/provider/package/macports.rb, line 100 def uninstall port("-q", :uninstall, @resource[:name]) end
# File lib/puppet/provider/package/windows.rb, line 110 def uninstall_options join_options(resource[:uninstall_options]) end
Are we moving up the property tree?
# File lib/puppet/type/zone.rb, line 126 def up? self.class.fsm.cmp?(self.retrieve, self.should) end
# File lib/puppet/provider/package/yum.rb, line 151 def update # Install in yum can be used for update, too self.install end
# File lib/puppet/provider/service/upstart.rb, line 74 def upstart_version @upstart_version ||= initctl("--version").match(/initctl \(upstart ([^\)]*)\)/)[1] end
# File lib/puppet/network/formats.rb, line 71 def use_zlib? Puppet.features.zlib? && Puppet[:zlib] end
# File lib/puppet/provider/cron/crontab.rb, line 256 def user @property_hash[:user] || @property_hash[:target] end
# File lib/puppet/provider/cron/crontab.rb, line 247 def user=(user) # we have to mark the target as modified first, to make sure that if # we move a cronjob from userA to userB, userA's crontab will also # be rewritten mark_target_modified @property_hash[:user] = user @property_hash[:target] = user end
# File lib/puppet/provider/user/user_role_add.rb, line 51 def user_attributes @user_attributes ||= UserAttr.get_attributes_by_name(@resource[:name]) end
Make sure we don’t purge users with specific uids
# File lib/puppet/type/resources.rb, line 145 def user_check(resource) return true unless self[:name] == "user" return true unless self[:unless_system_user] resource[:audit] = :uid current_values = resource.retrieve_resource current_uid = current_values[resource.property(:uid)] unless_uids = self[:unless_uid] return false if system_users.include?(resource[:name]) return false if unless_uids && unless_uids.include?(current_uid) current_uid > self[:unless_system_user] end
# File lib/puppet/provider/scheduled_task/win32_taskscheduler.rb, line 115 def user_insync?(current, should) return false unless current # Win32::TaskScheduler can return the 'SYSTEM' account as the # empty string. current = 'system' if current == '' # By comparing account SIDs we don't have to worry about case # sensitivity, or canonicalization of the account name. Puppet::Util::Windows::SID.name_to_sid(current) == Puppet::Util::Windows::SID.name_to_sid(should[0]) end
Force convert users it a list.
# File lib/puppet/provider/group/aix.rb, line 136 def users_from_attr(value) (value.is_a? String) ? value.split(',') : value end
# File lib/puppet/provider/user/directoryservice.rb, line 490 def users_plist_dir '/var/db/dslocal/nodes/Default/users' end
# File lib/puppet/provider/file/windows.rb, line 83 def validate if [:owner, :group, :mode].any?{|p| resource[p]} and !supports_acl?(resource[:path]) resource.fail("Can only manage owner, group, and mode on filesystems that support Windows ACLs, such as NTFS") end end
Should we validate the checksum of the file we’re writing?
# File lib/puppet/type/file.rb, line 880 def validate_checksum? self[:checksum] !~ /time/ end
# File lib/puppet/type/zone.rb, line 333 def validate_exclusive(interface, address, router) return if !interface.nil? and address.nil? self.fail "only interface may be specified when using exclusive IP stack: #{interface}:#{address}" end
# File lib/puppet/reports/store.rb, line 62 def validate_host(host) if host =~ Regexp.union(/[#{SEPARATOR}]/, /\A\.\.?\Z/) raise ArgumentError, "Invalid node name #{host.inspect}" end end
# File lib/puppet/type/zone.rb, line 327 def validate_ip(ip, name) IPAddr.new(ip) if ip rescue ArgumentError self.fail Puppet::Error, "'#{ip}' is an invalid #{name}", $! end
@api private
# File lib/puppet/face/parser.rb, line 149 def validate_manifest(manifest = nil) env = Puppet.lookup(:current_environment) validation_environment = manifest ? env.override_with(:manifest => manifest) : env validation_environment.check_for_reparse validation_environment.known_resource_types.clear rescue => detail Puppet.log_exception(detail) exit(1) end
This only gets called if there is a value to validate, but not if it’s absent
# File lib/puppet/provider/package/windows.rb, line 102 def validate_source(value) fail("The source parameter cannot be empty when using the Windows provider.") if value.empty? end
# File lib/puppet/provider/scheduled_task/win32_taskscheduler.rb, line 377 def validate_trigger(value) value = [value] unless value.is_a?(Array) value.each do |t| if t.has_key?('index') self.fail "'index' is read-only on scheduled_task triggers and should be removed ('index' is usually provided in puppet resource scheduled_task)." end if t.has_key?('enabled') self.fail "'enabled' is read-only on scheduled_task triggers and should be removed ('enabled' is usually provided in puppet resource scheduled_task)." end translate_hash_to_trigger(t) end true end
# File lib/puppet/provider/exec/shell.rb, line 22 def validatecmd(command) true end
# File lib/puppet/provider/selboolean/getsetsebool.rb, line 22 def value=(new) persist = "" if @resource[:persistent] == :true self.debug "Enabling persistence" persist = "-P" end execoutput("#{command(:setsebool)} #{persist} #{@resource[:name]} #{new}") :file_changed end
# File lib/puppet/type/interface.rb, line 101 def value_to_s(value) value = [value] unless value.is_a?(Array) value.map{ |v| "#{v[1].to_s}/#{v[0]} #{v[2]}"}.join(",") end
Check that a group exists and is valid
# File lib/puppet/provider/user/aix.rb, line 169 def verify_group(value) if value.is_a? Integer or value.is_a? Fixnum groupname = groupname_by_id(value) raise ArgumentError, "AIX group must be a valid existing group" unless groupname else raise ArgumentError, "AIX group must be a valid existing group" unless groupid_by_name(value) groupname = value end groupname end
# File lib/puppet/provider/service/upstart.rb, line 181 def version_is_post_0_9_0 Puppet::Util::Package.versioncmp(upstart_version, "0.9.0") >= 0 end
# File lib/puppet/provider/service/upstart.rb, line 173 def version_is_pre_0_6_7 Puppet::Util::Package.versioncmp(upstart_version, "0.6.7") == -1 end
# File lib/puppet/provider/service/upstart.rb, line 177 def version_is_pre_0_9_0 Puppet::Util::Package.versioncmp(upstart_version, "0.9.0") == -1 end
# File lib/puppet/face/module/list.rb, line 105 def warn_unmet_dependencies(environment) error_types = { :non_semantic_version => { :title => "Non semantic version dependency" }, :missing => { :title => "Missing dependency" }, :version_mismatch => { :title => "Module '%s' (v%s) fails to meet some dependencies:" } } @unmet_deps = {} error_types.each_key do |type| @unmet_deps[type] = Hash.new do |hash, key| hash[key] = { :errors => [], :parent => nil } end end # Prepare the unmet dependencies for display on the console. environment.modules.sort_by {|mod| mod.name}.each do |mod| unmet_grouped = Hash.new { |h,k| h[k] = [] } unmet_grouped = mod.unmet_dependencies.inject(unmet_grouped) do |acc, dep| acc[dep[:reason]] << dep acc end unmet_grouped.each do |type, deps| unless deps.empty? unmet_grouped[type].sort_by { |dep| dep[:name] }.each do |dep| dep_name = dep[:name].gsub('/', '-') installed_version = dep[:mod_details][:installed_version] version_constraint = dep[:version_constraint] parent_name = dep[:parent][:name].gsub('/', '-') parent_version = dep[:parent][:version] msg = "'#{parent_name}' (#{parent_version})" msg << " requires '#{dep_name}' (#{version_constraint})" @unmet_deps[type][dep[:name]][:errors] << msg @unmet_deps[type][dep[:name]][:parent] = { :name => dep[:parent][:name], :version => parent_version } @unmet_deps[type][dep[:name]][:version] = installed_version end end end end # Display unmet dependencies by category. error_display_order = [:non_semantic_version, :version_mismatch, :missing] error_display_order.each do |type| unless @unmet_deps[type].empty? @unmet_deps[type].keys.sort_by {|dep| dep }.each do |dep| name = dep.gsub('/', '-') title = error_types[type][:title] errors = @unmet_deps[type][dep][:errors] version = @unmet_deps[type][dep][:version] msg = case type when :version_mismatch title % [name, version] + "\n" when :non_semantic_version title + " '#{name}' (v#{version}):\n" else title + " '#{name}':\n" end errors.each { |error_string| msg << " #{error_string}\n" } Puppet.warning msg.chomp end end end end
# File lib/puppet/functions/with.rb, line 19 def with(*args) yield(*args) end
# File lib/puppet/vendor/safe_yaml/spec/transform/to_symbol_spec.rb, line 14 def with_symbol_deserialization(&block) with_symbol_deserialization_value(true, &block) end
# File lib/puppet/vendor/safe_yaml/spec/transform/to_symbol_spec.rb, line 4 def with_symbol_deserialization_value(value) symbol_deserialization_flag = SafeYAML::OPTIONS[:deserialize_symbols] SafeYAML::OPTIONS[:deserialize_symbols] = value yield ensure SafeYAML::OPTIONS[:deserialize_symbols] = symbol_deserialization_flag end
# File lib/puppet/vendor/safe_yaml/spec/transform/to_symbol_spec.rb, line 18 def without_symbol_deserialization(&block) with_symbol_deserialization_value(false, &block) end
# File lib/puppet/provider/scheduled_task/win32_taskscheduler.rb, line 56 def working_dir task.working_directory end
# File lib/puppet/provider/scheduled_task/win32_taskscheduler.rb, line 151 def working_dir=(value) task.working_directory = value end
Write out the file. Requires the property name for logging. Write will be done by the content property, along with checksum computation
# File lib/puppet/type/file.rb, line 791 def write(property) remove_existing(:file) mode = self.should(:mode) # might be nil mode_int = mode ? symbolic_mode_to_int(mode, Puppet::Util::DEFAULT_POSIX_MODE) : nil if write_temporary_file? Puppet::Util.replace_file(self[:path], mode_int) do |file| file.binmode content_checksum = write_content(file) file.flush fail_if_checksum_is_wrong(file.path, content_checksum) if validate_checksum? if self[:validate_cmd] output = Puppet::Util::Execution.execute(self[:validate_cmd].gsub(self[:validate_replacement], file.path), :failonfail => true, :combine => true) output.split(/\n/).each { |line| self.debug(line) } end end else umask = mode ? 000 : 022 Puppet::Util.withumask(umask) { ::File.open(self[:path], 'wb', mode_int ) { |f| write_content(f) } } end # make sure all of the modes are actually correct property_fix end
write the current content. Note that if there is no content property simply opening the file with ‘w’ as done in write is enough to truncate or write an empty length file.
# File lib/puppet/type/file.rb, line 895 def write_content(file) (content = property(:content)) && content.write(file) end
This method is only called on version 10.7 or greater. On 10.7 machines, passwords are set using a salted-SHA512 hash, and on 10.8 machines, passwords are set using PBKDF2. It’s possible to have users on 10.8 who have upgraded from 10.7 and thus have a salted-SHA512 password hash. If we encounter this, do what 10.8 does - remove that key and give them a 10.8-style PBKDF2 password.
# File lib/puppet/provider/user/directoryservice.rb, line 532 def write_password_to_users_plist(value) users_plist = get_users_plist(@resource.name) shadow_hash_data = get_shadow_hash_data(users_plist) if self.class.get_os_version == '10.7' set_salted_sha512(users_plist, shadow_hash_data, value) else # It's possible that a user could exist on the system and NOT have # a ShadowHashData key (especially if the system was upgraded from 10.6). # In this case, a conditional check is needed to determine if the # shadow_hash_data variable is a Hash (it would be false if the key # didn't exist for this user on the system). If the shadow_hash_data # variable IS a Hash and contains the 'SALTED-SHA512' key (indicating an # older 10.7-style password hash), it will be deleted and a newer # 10.8-style (PBKDF2) password hash will be generated. if (shadow_hash_data.class == Hash) && (shadow_hash_data.has_key?('SALTED-SHA512')) shadow_hash_data.delete('SALTED-SHA512') end set_salted_pbkdf2(users_plist, shadow_hash_data, 'entropy', value) end end
@api private
# File lib/puppet/provider/service/openbsd.rb, line 159 def write_rc_contents(file, text) Puppet::Util.replace_file(file, 0644) do |f| f.write(text) end end
# File lib/puppet/provider/service/upstart.rb, line 354 def write_script_to(file, text) Puppet::Util.replace_file(file, 0644) do |file| file.write(text) end end
# File lib/puppet/provider/user/directoryservice.rb, line 664 def write_sha1_hash(value) users_guid = self.class.get_attribute_from_dscl('Users', @resource.name, 'GeneratedUID')['dsAttrTypeStandard:GeneratedUID'][0] password_hash_file = "#{self.class.password_hash_dir}/#{users_guid}" write_to_file(password_hash_file, value) # NBK: For shadow hashes, the user AuthenticationAuthority must contain a value of # ";ShadowHash;". The LKDC in 10.5 makes this more interesting though as it # will dynamically generate ;Kerberosv5;;username@LKDC:SHA1 attributes if # missing. Thus we make sure we only set ;ShadowHash; if it is missing, and # we can do this with the merge command. This allows people to continue to # use other custom AuthenticationAuthority attributes without stomping on them. # # There is a potential problem here in that we're only doing this when setting # the password, and the attribute could get modified at other times while the # hash doesn't change and so this doesn't get called at all... but # without switching all the other attributes to merge instead of create I can't # see a simple enough solution for this that doesn't modify the user record # every single time. This should be a rather rare edge case. (famous last words) merge_attribute_with_dscl('Users', @resource.name, 'AuthenticationAuthority', ';ShadowHash;') end
# File lib/puppet/type/file.rb, line 899 def write_temporary_file? # unfortunately we don't know the source file size before fetching it # so let's assume the file won't be empty (c = property(:content) and c.length) || @parameters[:source] end
This is a simple wrapper method for writing values to a file.
# File lib/puppet/provider/user/directoryservice.rb, line 656 def write_to_file(filename, value) begin File.open(filename, 'w') { |f| f.write(value)} rescue Errno::EACCES => detail raise Puppet::Error, "Could not write to file #{filename}: #{detail}", detail.backtrace end end
This method will accept a plist in XML format, save it to disk, convert the plist to a binary format, and flush the dscl cache.
# File lib/puppet/provider/user/directoryservice.rb, line 650 def write_users_plist_to_disk(users_plist) Plist::Emit.save_plist(users_plist, "#{users_plist_dir}/#{@resource.name}.plist") plutil'-convert', 'binary1', "#{users_plist_dir}/#{@resource.name}.plist" end
# File lib/puppet/util/zaml.rb, line 186 def yaml_property_munge(x) x end
If yaourt is installed, we can make use of it
# File lib/puppet/provider/package/pacman.rb, line 23 def yaourt? return Puppet::FileSystem.exist?('/usr/bin/yaourt') end
# File lib/puppet/util/zaml.rb, line 190 def zamlized_class_name(root) cls = self.class "!ruby/#{root.name.downcase}#{cls == root ? '' : ":#{cls.respond_to?(:name) ? cls.name : cls}"}" end
# File lib/puppet/provider/zone/solaris.rb, line 345 def zoneadm(*cmd) adm("-z", @resource[:name], *cmd) rescue Puppet::ExecutionFailure => detail self.fail Puppet::Error, "Could not #{cmd[0]} zone: #{detail}", detail end
# File lib/puppet/provider/zone/solaris.rb, line 351 def zonecfg(*cmd) # You apparently can't get the configuration of the global zone (strictly in solaris11) return "" if self.name == "global" begin cfg("-z", self.name, *cmd) rescue Puppet::ExecutionFailure => detail self.fail Puppet::Error, "Could not #{cmd[0]} zone: #{detail}", detail end end
on zypper versions <1.0, the version option returns 1 some versions of zypper output on stderr
# File lib/puppet/provider/package/zypper.rb, line 40 def zypper_version cmd = [self.class.command(:zypper),"--version"] execute(cmd, { :failonfail => false, :combine => true}) end
# File lib/puppet/provider/selboolean/getsetsebool.rb, line 7 def value self.debug "Retrieving value of selboolean #{@resource[:name]}" status = getsebool(@resource[:name]) if status =~ / off$/ return :off elsif status =~ / on$/ then return :on else status.chomp! raise Puppet::Error, "Invalid response '#{status}' returned from getsebool" end end
# File lib/puppet/type/file.rb, line 387 def self.[](path) return nil unless path super(path.gsub(/\/+/, '/').sub(/\/$/, '')) end
# File lib/puppet/type/zone.rb, line 65 def self.alias_state(values) values.each do |k,v| fsm.alias_state(k,v) end end
Group attributes to ignore
# File lib/puppet/provider/group/aix.rb, line 27 def self.attribute_ignore [] end
Turns a pkgutil -a listing into hashes with the common alias, full package name and available version
# File lib/puppet/provider/package/pkgutil.rb, line 63 def self.availlist output = pkguti ["-a"] output.split("\n").collect do |line| next if line =~ /^common\s+package/ # header of package list next if noise?(line) if line =~ /\s*(\S+)\s+(\S+)\s+(.*)/ { :alias => $1, :name => $2, :avail => $3 } else Puppet.warning "Cannot match %s" % line end end.reject { |h| h.nil? } end
Turn our blastwave listing into a bunch of hashes.
# File lib/puppet/provider/package/blastwave.rb, line 35 def self.blastlist(hash) command = ["-c"] command << hash[:justme] if hash[:justme] output = Puppet::Util.withenv(:PAGER => "/usr/bin/cat") { pkgget command } list = output.split("\n").collect do |line| next if line =~ /^#/ next if line =~ /^WARNING/ next if line =~ /localrev\s+remoterev/ blastsplit(line) end.reject { |h| h.nil? } if hash[:justme] return list[0] else list.reject! { |h| h[:ensure] == :absent } return list end end
Split the different lines into hashes.
# File lib/puppet/provider/package/blastwave.rb, line 62 def self.blastsplit(line) if line =~ /\s*(\S+)\s+((\[Not installed\])|(\S+))\s+(\S+)/ hash = {} hash[:name] = $1 hash[:ensure] = if $2 == "[Not installed]" :absent else $2 end hash[:avail] = $5 hash[:avail] = hash[:ensure] if hash[:avail] == "SAME" # Use the name method, so it works with subclasses. hash[:provider] = self.name return hash else Puppet.warning "Cannot match #{line}" return nil end end
Used for testing only @api private
# File lib/puppet/provider/yumrepo/inifile.rb, line 92 def self.clear @virtual = nil end
# File lib/puppet/provider/package/pip.rb, line 39 def self.cmd if Facter.value(:osfamily) == "RedHat" and Facter.value(:operatingsystemmajrelease).to_i < 7 "pip-python" else "pip" end end
This method will accept a binary plist (as a string) and convert it to a hash via Plist::parse_xml.
# File lib/puppet/provider/user/directoryservice.rb, line 204 def self.convert_binary_to_xml(plist_data) Puppet.debug('Converting binary plist to XML') Puppet.debug('Executing: \plutil -convert xml1 -o - -\') IO.popen('plutil -convert xml1 -o - -', 'r+') do |io| io.write plist_data io.close_write @converted_plist = io.read end Puppet.debug('Converting XML values to a hash.') Plist::parse_xml(@converted_plist) end
This method will accept a hash that has been returned from Plist::parse_xml and convert it to a binary plist (string value).
# File lib/puppet/provider/user/directoryservice.rb, line 191 def self.convert_xml_to_binary(plist_data) Puppet.debug('Converting XML plist to binary') Puppet.debug('Executing: \plutil -convert binary1 -o - -\') IO.popen('plutil -convert binary1 -o - -', 'r+') do |io| io.write Plist::Emit.dump(plist_data) io.close_write @converted_plist = io.read end @converted_plist end
# File lib/puppet/provider/package/rpm.rb, line 37 def self.current_version return @current_version unless @current_version.nil? output = rpm "--version" @current_version = output.gsub('RPM version ', '').strip end
returns the daemon dir on this node
# File lib/puppet/provider/service/daemontools.rb, line 84 def self.daemondir self.defpath end
# File lib/puppet/provider/zone/solaris.rb, line 48 def self.def_multiprop(var, &conf) define_method(var.to_s) do |v| o = properties[var] return '' if o.nil? or o == :absent o.join(' ') end define_method('%s=' % var.to_s) do |v| setconfig self.send( ('%s_conf'% var).intern, v) end define_method('%s_conf' % var.to_s) do |v| multi_conf(var, v, &conf) end end
# File lib/puppet/provider/zone/solaris.rb, line 39 def self.def_prop(var, str) define_method('%s_conf' % var.to_s) do |v| str % v end define_method('%s=' % var.to_s) do |v| setconfig self.send( ('%s_conf'% var).intern, v) end end
Make sure to use mode 644 if ssh_known_hosts is newly created
# File lib/puppet/provider/sshkey/parsed.rb, line 36 def self.default_mode 0644 end
# File lib/puppet/provider/service/bsd.rb, line 16 def self.defpath superclass.defpath end
# File lib/puppet/type/resources.rb, line 137 def self.deprecate_params(title,params) return unless params if title == 'cron' and ! params.select { |param| param.name.intern == :purge and param.value == true }.empty? Puppet.deprecation_warning("Change notice: purging cron entries will be more aggressive in future versions, take care when updating your agents. See http://links.puppetlabs.com/puppet-aggressive-cron-purge") end end
removes all reports for a given host?
# File lib/puppet/reports/store.rb, line 47 def self.destroy(host) validate_host(host) dir = File.join(Puppet[:reportdir], host) if Puppet::FileSystem.exist?(dir) Dir.entries(dir).each do |file| next if ['.','..'].include?(file) file = File.join(dir, file) Puppet::FileSystem.unlink(file) if File.file?(file) end Dir.rmdir(dir) end end
Performs a dpkgquery call with a pipe so that output can be processed inline in a passed block. @param args [Array<String>] any command line arguments to be appended to the command @param block expected to be passed on to execpipe @return whatever the block returns @see Puppet::Util::Execution.execpipe @api private
# File lib/puppet/provider/package/dpkg.rb, line 21 def self.dpkgquery_piped(*args, &block) cmd = args.unshift(command(:dpkgquery)) Puppet::Util::Execution.execpipe(cmd, &block) end
If a vixie cron header is found, it should be dropped, cron will insert a new one in any case, so we need to avoid duplicates.
# File lib/puppet/provider/cron/crontab.rb, line 140 def self.drop_native_header true end
This method exists to map the dscl values to the correct Puppet properties. This stays relatively consistent, but who knows what Apple will do next year…
# File lib/puppet/provider/user/directoryservice.rb, line 43 def self.ds_to_ns_attribute_map { 'RecordName' => :name, 'PrimaryGroupID' => :gid, 'NFSHomeDirectory' => :home, 'UserShell' => :shell, 'UniqueID' => :uid, 'RealName' => :comment, 'Password' => :password, 'GeneratedUID' => :guid, 'IPAddress' => :ip_address, 'ENetAddress' => :en_address, 'GroupMembership' => :members, } end
# File lib/puppet/provider/package/portage.rb, line 138 def self.eix_result_fields [:category, :name, :ensure, :version_available, :vendor, :description] end
# File lib/puppet/provider/package/portage.rb, line 134 def self.eix_result_format /^(\S+)\s+(\S+)\s+\[(\S*)\]\s+\[(\S*)\]\s+(\S+)\s+(.*)$/ end
# File lib/puppet/provider/package/portage.rb, line 146 def self.eix_search_arguments ["--nocolor", "--pure-packages", "--format",self.eix_search_format] end
# File lib/puppet/provider/package/portage.rb, line 130 def self.eix_search_format "'<category> <name> [<installedversions:LASTVERSION>] [<bestversion:LASTVERSION>] <homepage> <description>'" end
# File lib/puppet/provider/package/portage.rb, line 142 def self.eix_version_format "{last}<version>{}" end
some init scripts are not safe to execute, e.g. we do not want to suddently run /etc/init.d/reboot.sh status and reboot our system. The exclude list could be platform agnostic but I assume an invalid init script on system A will never be a valid init script on system B
# File lib/puppet/provider/service/init.rb, line 26 def self.excludes excludes = [] # these exclude list was found with grep -L '\/sbin\/runscript' /etc/init.d/* on gentoo excludes += %w{functions.sh reboot.sh shutdown.sh} # this exclude list is all from /sbin/service (5.x), but I did not exclude kudzu excludes += %w{functions halt killall single linuxconf reboot boot} # 'wait-for-state' and 'portmap-wait' are excluded from instances here # because they take parameters that have unclear meaning. It looks like # 'wait-for-state' is a generic waiter mainly used internally for other # upstart services as a 'sleep until something happens' # (http://lists.debian.org/debian-devel/2012/02/msg01139.html), while # 'portmap-wait' is a specific instance of a waiter. There is an open # launchpad bug # (https://bugs.launchpad.net/ubuntu/+source/upstart/+bug/962047) that may # eventually explain how to use the wait-for-state service or perhaps why # it should remain excluded. When that bug is adddressed this should be # reexamined. excludes += %w{wait-for-state portmap-wait} # these excludes were found with grep -r -L start /etc/init.d excludes += %w{rcS module-init-tools} # Prevent puppet failing to get status of the new service introduced # by the fix for this (bug https://bugs.launchpad.net/ubuntu/+source/lightdm/+bug/982889) # due to puppet's inability to deal with upstart services with instances. excludes += %w{plymouth-ready} # Prevent puppet failing to get status of these services, which need parameters # passed in (see https://bugs.launchpad.net/ubuntu/+source/puppet/+bug/1276766). excludes += %w{idmapd-mounting startpar-bridge} # Prevent puppet failing to get status of these services, additional upstart # service with instances excludes += %w{cryptdisks-udev} excludes += %w{statd-mounting} excludes += %w{gssd-mounting} end
# File lib/puppet/provider/package/blastwave.rb, line 15 def self.extended(mod) unless command(:pkgget) != "pkg-get" raise Puppet::Error, "The pkg-get command is missing; blastwave packaging unavailable" end unless Puppet::FileSystem.exist?("/var/pkg-get/admin") Puppet.notice "It is highly recommended you create '/var/pkg-get/admin'." Puppet.notice "See /var/pkg-get/admin-fullauto" end end
Search for all installed packages that have newer versions, given a combination of repositories to enable and disable.
@api private @param enablerepo [Array<String>] A list of repositories to enable for this query @param disablerepo [Array<String>] A list of repositories to disable for this query @return [Hash<String, Array<Hash<String, String>>>] All packages that were
found with a list of found versions for each package.
# File lib/puppet/provider/package/yum.rb, line 71 def self.fetch_latest_versions(enablerepo, disablerepo) latest_versions = Hash.new {|h, k| h[k] = []} args = [self::YUMHELPER] args.concat(enablerepo.map { |repo| ['-e', repo] }.flatten) args.concat(disablerepo.map { |repo| ['-d', repo] }.flatten) python(args).scan(/^_pkg (.*)$/) do |match| hash = nevra_to_hash(match[0]) # Create entries for both the package name without a version and a # version since yum considers those as mostly interchangeable. short_name = hash[:name] long_name = "#{hash[:name]}.#{hash[:arch]}" latest_versions[short_name] << hash latest_versions[long_name] << hash end latest_versions end
# File lib/puppet/provider/cron/crontab.rb, line 14 def self.filetype tabname = case Facter.value(:osfamily) when "Solaris" :suntab when "AIX" :aixtab else :crontab end Puppet::Util::FileType.filetype(tabname) 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.
# File lib/puppet/provider/yumrepo/inifile.rb, line 102 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
# File lib/puppet/type/zone.rb, line 60 def self.fsm return @fsm if @fsm @fsm = Puppet::Zone::StateMachine.new end
# File lib/puppet/provider/package/gem.rb, line 19 def self.gemlist(options) gem_list_command = [command(:gemcmd), "list"] if options[:local] gem_list_command << "--local" else gem_list_command << "--remote" end if options[:source] gem_list_command << "--source" << options[:source] end if name = options[:justme] gem_list_command << "^" + name + "$" end begin list = execute(gem_list_command).lines. map {|set| gemsplit(set) }. reject {|x| x.nil? } rescue Puppet::ExecutionFailure => detail raise Puppet::Error, "Could not list gems: #{detail}", detail.backtrace end if options[:justme] return list.shift else return list end end
# File lib/puppet/provider/package/gem.rb, line 49 def self.gemsplit(desc) # `gem list` when output console has a line like: # *** LOCAL GEMS *** # but when it's not to the console that line # and all blank lines are stripped # so we don't need to check for them if desc =~ /^(\S+)\s+\((.+)\)/ name = $1 versions = $2.split(/,\s*/) { :name => name, :ensure => versions.map{|v| v.split[0]}, :provider => :gem } else Puppet.warning "Could not match #{desc}" unless desc.chomp.empty? nil end end
This method accepts an individual user plist, passed as a hash, and strips the dsAttrTypeStandard: prefix that dscl adds for each key. An attribute hash is assembled and returned from the properties supported by the user type.
# File lib/puppet/provider/user/directoryservice.rb, line 101 def self.generate_attribute_hash(input_hash) attribute_hash = {} input_hash.keys.each do |key| ds_attribute = key.sub("dsAttrTypeStandard:", "") next unless ds_to_ns_attribute_map.keys.include?(ds_attribute) ds_value = input_hash[key] case ds_to_ns_attribute_map[ds_attribute] when :gid, :uid # OS X stores objects like uid/gid as strings. # Try casting to an integer for these cases to be # consistent with the other providers and the group type # validation begin ds_value = Integer(ds_value[0]) rescue ArgumentError ds_value = ds_value[0] end else ds_value = ds_value[0] end attribute_hash[ds_to_ns_attribute_map[ds_attribute]] = ds_value end attribute_hash[:ensure] = :present attribute_hash[:provider] = :directoryservice attribute_hash[:shadowhashdata] = get_attribute_from_dscl('Users', attribute_hash[:name], 'ShadowHashData') ############## # Get Groups # ############## groups_array = [] get_list_of_groups.each do |group| if group["dsAttrTypeStandard:GroupMembership"] and group["dsAttrTypeStandard:GroupMembership"].include?(attribute_hash[:name]) groups_array << group["dsAttrTypeStandard:RecordName"][0] end if group["dsAttrTypeStandard:GroupMembers"] and group["dsAttrTypeStandard:GroupMembers"].include?(attribute_hash[:guid]) groups_array << group["dsAttrTypeStandard:RecordName"][0] end end attribute_hash[:groups] = groups_array.uniq.sort.join(',') ################################ # Get Password/Salt/Iterations # ################################ if (Puppet::Util::Package.versioncmp(get_os_version, '10.7') == -1) attribute_hash[:password] = get_sha1(attribute_hash[:guid]) else if attribute_hash[:shadowhashdata].empty? attribute_hash[:password] = '*' else embedded_binary_plist = get_embedded_binary_plist(attribute_hash[:shadowhashdata]) if embedded_binary_plist['SALTED-SHA512'] attribute_hash[:password] = get_salted_sha512(embedded_binary_plist) else attribute_hash[:password] = get_salted_sha512_pbkdf2('entropy', embedded_binary_plist) attribute_hash[:salt] = get_salted_sha512_pbkdf2('salt', embedded_binary_plist) attribute_hash[:iterations] = get_salted_sha512_pbkdf2('iterations', embedded_binary_plist) end end end attribute_hash end
Return an array of hashes containing information about every user on the system.
# File lib/puppet/provider/user/directoryservice.rb, line 93 def self.get_all_users Plist.parse_xml(dscl '-plist', '.', 'readall', '/Users') end
Perform a dscl lookup at the path specified for the specific keyname value. The value returned is the first item within the array returned from dscl
# File lib/puppet/provider/user/directoryservice.rb, line 177 def self.get_attribute_from_dscl(path, username, keyname) Plist.parse_xml(dscl '-plist', '.', 'read', "/#{path}/#{username}", keyname) end
The plist embedded in the ShadowHashData key is a binary plist. The facter/util/plist library doesn’t read binary plists, so we need to extract the binary plist, convert it to XML, and return it.
# File lib/puppet/provider/user/directoryservice.rb, line 184 def self.get_embedded_binary_plist(shadow_hash_data) embedded_binary_plist = Array(shadow_hash_data['dsAttrTypeNative:ShadowHashData'][0].delete(' ')).pack('H*') convert_binary_to_xml(embedded_binary_plist) end
Read the rc.conf* files and determine the value of the flags @api private
# File lib/puppet/provider/service/openbsd.rb, line 108 def self.get_flags(rcname) rcflags() @flag_hash[rcname.to_sym] end
Use dscl to retrieve an array of hashes containing attributes about all of the local groups on the machine.
# File lib/puppet/provider/user/directoryservice.rb, line 170 def self.get_list_of_groups @groups ||= Plist.parse_xml(dscl '-plist', '.', 'readall', '/Groups') end
# File lib/puppet/provider/service/launchd.rb, line 232 def self.get_macosx_version_major return @macosx_version_major if @macosx_version_major begin product_version_major = Facter.value(:macosx_productversion_major) fail("#{product_version_major} is not supported by the launchd provider") if %w{10.0 10.1 10.2 10.3 10.4}.include?(product_version_major) @macosx_version_major = product_version_major return @macosx_version_major rescue Puppet::ExecutionFailure => detail self.fail Puppet::Error, "Could not determine OS X version: #{detail}", detail end end
Gets the current Darwin version, example 10.6 returns 9 and 10.10 returns 14 See en.wikipedia.org/wiki/Darwin_(operating_system)#Release_history for more information.
@api private
# File lib/puppet/provider/service/launchd.rb, line 74 def self.get_os_version @os_version ||= Facter.value(:operatingsystemmajrelease).to_i end
The salted-SHA512 password hash in 10.7 is stored in the ‘SALTED-SHA512’ key as binary data. That data is extracted and converted to a hex string.
# File lib/puppet/provider/user/directoryservice.rb, line 218 def self.get_salted_sha512(embedded_binary_plist) embedded_binary_plist['SALTED-SHA512'].string.unpack("H*")[0] end
This method reads the passed embedded_binary_plist hash and returns values according to which field is passed. Arguments passed are the hash containing the value read from the ‘ShadowHashData’ key in the User’s plist, and the field to be read (one of ‘entropy’, ‘salt’, or ‘iterations’)
# File lib/puppet/provider/user/directoryservice.rb, line 226 def self.get_salted_sha512_pbkdf2(field, embedded_binary_plist) case field when 'salt', 'entropy' embedded_binary_plist['SALTED-SHA512-PBKDF2'][field].string.unpack('H*').first when 'iterations' Integer(embedded_binary_plist['SALTED-SHA512-PBKDF2'][field]) else raise Puppet::Error, 'Puppet has tried to read an incorrect value from the ' + "SALTED-SHA512-PBKDF2 hash. Acceptable fields are 'salt', " + "'entropy', or 'iterations'." end end
# File lib/puppet/provider/service/init.rb, line 65 def self.get_services(defpath, exclude = self.excludes) defpath = [defpath] unless defpath.is_a? Array instances = [] defpath.each do |path| unless FileTest.directory?(path) Puppet.debug "Service path #{path} does not exist" next end check = [:ensure] check << :enable if public_method_defined? :enabled? Dir.entries(path).each do |name| fullpath = File.join(path, name) next if name =~ /^\./ next if exclude.include? name next if not FileTest.executable?(fullpath) next if not is_init?(fullpath) instances << new(:name => name, :path => path, :hasstatus => true) end end instances end
In versions 10.5 and 10.6 of OS X, the password hash is stored in a file in the /var/db/shadow/hash directory that matches the GUID of the user.
# File lib/puppet/provider/user/directoryservice.rb, line 241 def self.get_sha1(guid) password_hash = nil password_hash_file = "#{password_hash_dir}/#{guid}" if Puppet::FileSystem.exist?(password_hash_file) and File.file?(password_hash_file) raise Puppet::Error, "Could not read password hash file at #{password_hash_file}" if not File.readable?(password_hash_file) f = File.new(password_hash_file) password_hash = f.read f.close end password_hash end
# File lib/puppet/provider/package/macports.rb, line 39 def self.hash_from_line(line, regex, fields) hash = {} if match = regex.match(line) fields.zip(match.captures) { |field, value| hash[field] = value } hash[:provider] = self.name return hash end nil end
Return the header placed at the top of each generated file, warning users that modifying this file manually is probably a bad idea.
# File lib/puppet/provider/cron/crontab.rb, line 126 def self.header %Q{# HEADER: This file was autogenerated at #{Time.now} by puppet. # HEADER: While it can still be managed manually, it is definitely not recommended. # HEADER: Note particularly that the comments starting with 'Puppet Name' should # HEADER: not be deleted, as doing so could cause duplicate cron jobs.\n} end
# File lib/puppet/provider/package/pkgutil.rb, line 16 def self.healthcheck() unless Puppet::FileSystem.exist?("/var/opt/csw/pkgutil/admin") Puppet.notice "It is highly recommended you create '/var/opt/csw/pkgutil/admin'." Puppet.notice "See /var/opt/csw/pkgutil" end correct_wgetopts = false [ "/opt/csw/etc/pkgutil.conf", "/etc/opt/csw/pkgutil.conf" ].each do |confpath| File.open(confpath) do |conf| conf.each_line {|line| correct_wgetopts = true if line =~ /^\s*wgetopts\s*=.*(-nv|-q|--no-verbose|--quiet)/ } end end if ! correct_wgetopts Puppet.notice "It is highly recommended that you set 'wgetopts=-nv' in your pkgutil.conf." end end
The IFO flag field is just what it names, the first field can have ether i_nstalled or -, and second field f_rozen or -, and last o_bsolate or r_rename or - so this checks if the installed field is present, and also verifies that if not the field is -, else we dont know what we are doing and exit with out doing more damage.
# File lib/puppet/provider/package/pkg.rb, line 38 def self.ifo_flag(flags) ( case flags[0..0] when 'i' {:status => 'installed'} when '-' {:status => 'known'} else raise ArgumentError, 'Unknown format %s: %s[%s]' % [self.name, flags, flags[0..0]] end ).merge( case flags[1..1] when 'f' {:ensure => 'held'} when '-' {} else raise ArgumentError, 'Unknown format %s: %s[%s]' % [self.name, flags, flags[1..1]] end ) end
# File lib/puppet/provider/package/appdmg.rb, line 42 def self.installapp(source, name, orig_source) appname = File.basename(source); ditto "--rsrc", source, "/Applications/#{appname}" File.open("/var/db/.puppet_appdmg_installed_#{name}", "w") do |t| t.print "name: '#{name}'\n" t.print "source: '#{orig_source}'\n" end end
Get installed groups (pacman -Qg)
# File lib/puppet/provider/package/pacman.rb, line 123 def self.installedgroups packages = [] begin execpipe(listgroupcmd()) do |process| # pacman -Qg output is 'groupname packagename' # Groups need to be deduplicated groups = Set[] process.each_line { |line| groups.add(line.split[0]) } groups.each { |line| hash = { :name => line, :ensure => "1", # Groups don't have versions, so ensure => latest # will still cause a reinstall. :provider => self.name } packages << new(hash) } end rescue Puppet::ExecutionFailure return nil end packages end
Get installed packages (pacman -Q)
# File lib/puppet/provider/package/pacman.rb, line 91 def self.installedpkgs packages = [] begin execpipe(listcmd()) do |process| # pacman -Q output is 'packagename version-rel' regex = %r{^(\S+)\s(\S+)} fields = [:name, :ensure] hash = {} process.each_line { |line| if match = regex.match(line) fields.zip(match.captures) { |field,value| hash[field] = value } hash[:provider] = self.name packages << new(hash) hash = {} else warning("Failed to match line %s" % line) end } end rescue Puppet::ExecutionFailure return nil end packages end
# File lib/puppet/provider/package/pkgdmg.rb, line 61 def self.installpkg(source, name, orig_source) installer "-pkg", source, "-target", "/" # Non-zero exit status will throw an exception. File.open("/var/db/.puppet_pkgdmg_installed_#{name}", "w") do |t| t.print "name: '#{name}'\n" t.print "source: '#{orig_source}'\n" end end
# File lib/puppet/provider/package/appdmg.rb, line 51 def self.installpkgdmg(source, name) require 'open-uri' require 'facter/util/plist' cached_source = source tmpdir = Dir.mktmpdir begin if %r{\A[A-Za-z][A-Za-z0-9+\-\.]*://} =~ cached_source cached_source = File.join(tmpdir, name) begin curl "-o", cached_source, "-C", "-", "-k", "-L", "-s", "--url", source Puppet.debug "Success: curl transfered [#{name}]" rescue Puppet::ExecutionFailure Puppet.debug "curl did not transfer [#{name}]. Falling back to slower open-uri transfer methods." cached_source = source end end open(cached_source) do |dmg| xml_str = hdiutil "mount", "-plist", "-nobrowse", "-readonly", "-mountrandom", "/tmp", dmg.path ptable = Plist::parse_xml xml_str # JJM Filter out all mount-paths into a single array, discard the rest. mounts = ptable['system-entities'].collect { |entity| entity['mount-point'] }.select { |mountloc|; mountloc } begin mounts.each do |fspath| Dir.entries(fspath).select { |f| f =~ /\.app$/ }.each do |pkg| installapp("#{fspath}/#{pkg}", name, source) end end ensure hdiutil "eject", mounts[0] end end ensure FileUtils.remove_entry_secure(tmpdir, true) end end
# File lib/puppet/provider/package/apple.rb, line 24 def self.instance_by_name Dir.entries("/Library/Receipts").find_all { |f| f =~ /\.pkg$/ }.collect { |f| name = f.sub(/\.pkg/, '') yield name if block_given? name } end
# File lib/puppet/provider/service/systemd.rb, line 13 def self.instances i = [] output = systemctl('list-unit-files', '--type', 'service', '--full', '--all', '--no-pager') output.scan(/^(\S+)\s+(disabled|enabled)\s*$/).each do |m| i << new(:name => m[0]) end return i rescue Puppet::ExecutionFailure return [] end
JJM We store a cookie for each installed .app.dmg in /var/db
# File lib/puppet/provider/package/appdmg.rb, line 26 def self.instances_by_name Dir.entries("/var/db").find_all { |f| f =~ /^\.puppet_appdmg_installed_/ }.collect do |f| name = f.sub(/^\.puppet_appdmg_installed_/, '') yield name if block_given? name end end
# File lib/puppet/provider/service/init.rb, line 171 def self.is_init?(script = initscript) file = Puppet::FileSystem.pathname(script) !Puppet::FileSystem.symlink?(file) || Puppet::FileSystem.readlink(file) != "/lib/init/upstart-job" end
This status method lists out all currently running services. This hash is returned at the end of the method.
# File lib/puppet/provider/service/launchd.rb, line 180 def self.job_list @job_list = Hash.new begin output = launchctl :list raise Puppet::Error.new("launchctl list failed to return any data.") if output.nil? output.split("\n").each do |line| @job_list[line.split(/\s/).last] = :running end rescue Puppet::ExecutionFailure raise Puppet::Error.new("Unable to determine status of #{resource[:name]}", $!) end @job_list end
Sets a class instance variable with a hash of all launchd plist files that are found on the system. The key of the hash is the job id and the value is the path to the file. If a label is passed, we return the job id and path for that specific job.
# File lib/puppet/provider/service/launchd.rb, line 157 def self.jobsearch(label=nil) by_label = make_label_to_path_map if label if by_label.has_key? label return { label => by_label[label] } else # try refreshing the map, in case a plist has been added in the interim by_label = make_label_to_path_map(true) if by_label.has_key? label return { label => by_label[label] } else raise Puppet::Error, "Unable to find launchd plist for job: #{label}" end end else # caller wants the whole map by_label end end
Retrieve the latest package version information for a given package name and combination of repos to enable and disable.
@note If multiple package versions are defined (such as in the case where a
package is built for multiple architectures), the first package found will be used.
@api private @param package [String] The name of the package to query @param enablerepo [Array<String>] A list of repositories to enable for this query @param disablerepo [Array<String>] A list of repositories to disable for this query @return [Hash<Symbol, String>]
# File lib/puppet/provider/package/yum.rb, line 49 def self.latest_package_version(package, enablerepo, disablerepo) key = [enablerepo, disablerepo] @latest_versions ||= {} if @latest_versions[key].nil? @latest_versions[key] = fetch_latest_versions(enablerepo, disablerepo) end if @latest_versions[key][package] @latest_versions[key][package].first end end
Defines the path to the overrides plist file where service enabling behavior is defined in 10.6 and greater.
With the rewrite of launchd in 10.10+, this moves and slightly changes format.
@api private
# File lib/puppet/provider/service/launchd.rb, line 84 def self.launchd_overrides if self.get_os_version < 14 "/var/db/launchd.db/com.apple.launchd/overrides.plist" else "/var/db/com.apple.xpc.launchd/disabled.plist" end end
These are the paths in OS X where a launchd service plist could exist. This is a helper method, versus a constant, for easy testing and mocking
@api private
# File lib/puppet/provider/service/launchd.rb, line 60 def self.launchd_paths [ "/Library/LaunchAgents", "/Library/LaunchDaemons", "/System/Library/LaunchAgents", "/System/Library/LaunchDaemons" ] end
Convert the output of a list into a hash
# File lib/puppet/provider/zone/solaris.rb, line 10 def self.line2hash(line) fields = [:id, :name, :ensure, :path, :uuid, :brand, :iptype] properties = Hash[fields.zip(line.split(':'))] del_id = [:brand, :uuid] # Configured but not installed zones do not have IDs del_id << :id if properties[:id] == "-" del_id.each { |p| properties.delete(p) } properties[:ensure] = properties[:ensure].intern properties[:iptype] = 'exclusive' if properties[:iptype] == 'excl' properties end
Override lines and use scan instead of split, because we DON’T want to remove the separators
# File lib/puppet/provider/mount/parsed.rb, line 53 def self.lines(text) lines = text.split("\n") filesystem_stanza = false filesystem_index = 0 ret = Array.new lines.each_with_index do |line,i| if line.match(%r{^\S+:}) # Begin new filesystem stanza and save the index ret[filesystem_index] = filesystem_stanza.join("\n") if filesystem_stanza filesystem_stanza = Array(line) filesystem_index = i # Eat the preceeding blank line ret[i-1] = nil if i > 0 and ret[i-1] and ret[i-1].match(%r{^\s*$}) nil elsif line.match(%r{^(\s*\*.*|\s*)$}) # Just a comment or blank line; add in place ret[i] = line else # Non-comments or blank lines must be part of a stanza filesystem_stanza << line end end # Add the final stanza to the return ret[filesystem_index] = filesystem_stanza.join("\n") if filesystem_stanza ret = ret.compact.flatten ret.reject { |line| line.match(/^\* HEADER/) } end
# File lib/puppet/provider/package/zypper.rb, line 22 def self.list_updates output = zypper 'list-updates' avail_updates = {} # split up columns output.lines.each do |line| pkg_ver = line.split(/\s*\|\s*/) # ignore zypper headers next unless pkg_ver[0] == 'v' avail_updates[pkg_ver[2]] = pkg_ver[4] end avail_updates end
# File lib/puppet/provider/package/openbsd.rb, line 61 def self.listcmd [command(:pkginfo), "-a"] end
Pacman has a concept of package groups as well. Package groups have no versions.
# File lib/puppet/provider/package/pacman.rb, line 86 def self.listgroupcmd [command(:pacman), "-Qg"] end
# File lib/puppet/provider/interface/cisco.rb, line 9 def self.lookup(device, name) interface = nil device.command do |dev| interface = dev.interface(name) end interface end
Get a hash of all launchd plists, keyed by label. This value is cached, but the cache will be refreshed if refresh is true.
@api private
# File lib/puppet/provider/service/launchd.rb, line 134 def self.make_label_to_path_map(refresh=false) return @label_to_path_map if @label_to_path_map and not refresh @label_to_path_map = {} launchd_paths.each do |path| return_globbed_list_of_file_paths(path).each do |filepath| job = read_plist(filepath) next if job.nil? if job.has_key?("Label") @label_to_path_map[job["Label"]] = filepath else Puppet.warning("The #{filepath} plist does not contain a 'label' key; " + "Puppet is skipping it") next end end end @label_to_path_map end
See if we can match the record against an existing cron job.
# File lib/puppet/provider/cron/crontab.rb, line 145 def self.match(record, resources) # if the record is named, do not even bother (#19876) # except the resource name was implicitly generated (#3220) return false if record[:name] and !record[:unmanaged] resources.each do |name, resource| # Match the command first, since it's the most important one. next unless record[:target] == resource[:target] next unless record[:command] == resource.value(:command) # Now check the time fields compare_fields = self::TIME_FIELDS + [:special] matched = true compare_fields.each do |field| # If the resource does not manage a property (say monthday) it should # always match. If it is the other way around (e.g. resource defines # a should value for :special but the record does not have it, we do # not match next unless resource[field] unless record.include?(field) matched = false break end if record_value = record[field] and resource_value = resource.value(field) # The record translates '*' into absent in the post_parse hook and # the resource type does exactly the opposite (alias :absent to *) next if resource_value == '*' and record_value == :absent next if resource_value == record_value end matched =false break end return resource if matched end false end
# File lib/puppet/util/log/destinations.rb, line 49 def self.match?(obj) Puppet::Util.absolute_path?(obj) end
# File lib/puppet/provider/mcx/mcxcontent.rb, line 62 def self.mcxexport(ds_type, ds_name) ds_t = TypeMap[ds_type] ds_n = ds_name.to_s ds_path = "/Local/Default/#{ds_t}/#{ds_n}" dscl 'localhost', '-mcxexport', ds_path end
# File lib/puppet/provider/mount/parsed.rb, line 231 def self.mountinstances # XXX: Will not work for mount points that have spaces in path (does fstab support this anyways?) regex = case Facter.value(:osfamily) when "Darwin" / on (?:\/private\/var\/automount)?(\S*)/ when "Solaris", "HP-UX" /^(\S*) on / when "AIX" /^(?:\S*\s+\S+\s+)(\S+)/ else / on (\S*)/ end instances = [] mount_output = mountcmd.split("\n") if mount_output.length >= 2 and mount_output[1] =~ /^[- \t]*$/ # On some OSes (e.g. AIX) mount output begins with a header line # followed by a line consisting of dashes and whitespace. # Discard these two lines. mount_output[0..1] = [] end mount_output.each do |line| if match = regex.match(line) and name = match.captures.first instances << {:name => name, :mounted => :yes} # Only :name is important here else raise Puppet::Error, "Could not understand line #{line} from mount output" end end instances end
Convert a group name to an id.
# File lib/puppet/provider/group/ldap.rb, line 38 def self.name2id(group) return nil unless result = manager.search("cn=#{group}") and result.length > 0 # Only use the first result. group = result[0] group[:gid][0] end
# File lib/puppet/provider/package/sun.rb, line 32 def self.namemap(hash) self::Namemap.keys.inject({}) do |hsh,k| hsh.merge(self::Namemap[k] => hash[k]) end end
Regex for finding one vixie cron header.
# File lib/puppet/provider/cron/crontab.rb, line 134 def self.native_header_regex /# DO NOT EDIT THIS FILE.*?Cron version.*?vixie.*?\n/ end
@param line [String] one line of rpm package query information @return [Hash] of NEVRA_FIELDS strings parsed from package info or an empty hash if we failed to parse @api private
# File lib/puppet/provider/package/rpm.rb, line 173 def self.nevra_to_hash(line) line.strip! hash = {} if match = self::NEVRA_REGEX.match(line) self::NEVRA_FIELDS.zip(match.captures) { |f, v| hash[f] = v } hash[:provider] = self.name hash[:ensure] = "#{hash[:version]}-#{hash[:release]}" else Puppet.debug("Failed to match rpm line #{line}") end return hash end
rpm < 4.0.2 does not support –nodigest
# File lib/puppet/provider/package/rpm.rb, line 49 def self.nodigest '--nodigest' unless Puppet::Util::Package.versioncmp(current_version, '4.0.2') < 0 end
Identify common types of pkgutil noise as it downloads catalogs etc
# File lib/puppet/provider/package/pkgutil.rb, line 115 def self.noise?(line) true if line =~ /^#/ true if line =~ /^Checking integrity / # use_gpg true if line =~ /^gpg: / # gpg verification true if line =~ /^=+> / # catalog fetch true if line =~ /\d+:\d+:\d+ URL:/ # wget without -q false end
# File lib/puppet/provider/scheduled_task/win32_taskscheduler.rb, line 248 def self.normalized_date(date_string) date = Date.parse("#{date_string}") "#{date.year}-#{date.month}-#{date.day}" end
# File lib/puppet/provider/scheduled_task/win32_taskscheduler.rb, line 253 def self.normalized_time(time_string) Time.parse("#{time_string}").strftime('%H:%M') end
rpm < 4.1 does not support –nosignature
# File lib/puppet/provider/package/rpm.rb, line 44 def self.nosignature '--nosignature' unless Puppet::Util::Package.versioncmp(current_version, '4.1') < 0 end
# File lib/puppet/provider/user/directoryservice.rb, line 59 def self.ns_to_ds_attribute_map @ns_to_ds_attribute_map ||= ds_to_ns_attribute_map.invert end
Parse lines of output from `pip freeze`, which are structured as package==version.
# File lib/puppet/provider/package/pip.rb, line 17 def self.parse(line) if line.chomp =~ /^([^=]+)==([^=]+)$/ {:ensure => $2, :name => $1, :provider => name} else nil end end
# File lib/puppet/provider/package/macports.rb, line 33 def self.parse_info_query_line(line) regex = /(\S+)\s+(\S+)/ fields = [:version, :revision] hash_from_line(line, regex, fields) end
# File lib/puppet/provider/package/macports.rb, line 27 def self.parse_installed_query_line(line) regex = /(\S+)\s+@(\S+)_(\d+).*\(active\)/ fields = [:name, :ensure, :revision] hash_from_line(line, regex, fields) end
@param line [String] one line of dpkg-query output @return [Hash,nil] a hash of FIELDS or nil if we failed to match @api private
# File lib/puppet/provider/package/dpkg.rb, line 53 def self.parse_line(line) hash = nil if match = self::FIELDS_REGEX.match(line) hash = {} self::FIELDS.zip(match.captures) do |field,value| hash[field] = value end hash[:provider] = self.name if hash[:status] == 'not-installed' hash[:ensure] = :purged elsif ['config-files', 'half-installed', 'unpacked', 'half-configured'].include?(hash[:status]) hash[:ensure] = :absent end hash[:ensure] = :held if hash[:desired] == 'hold' else Puppet.debug("Failed to match dpkg-query line #{line.inspect}") end return hash end
parse sshv2 option strings, wich is a comma separated list of either key=“values” elements or bare-word elements
# File lib/puppet/provider/ssh_authorized_key/parsed.rb, line 73 def self.parse_options(options) result = [] scanner = StringScanner.new(options) while !scanner.eos? scanner.skip(/[ \t]*/) # scan a long option if out = scanner.scan(/[-a-z0-9A-Z_]+=\".*?[^\]\"/) or out = scanner.scan(/[-a-z0-9A-Z_]+/) result << out else # found an unscannable token, let's abort break end # eat a comma scanner.skip(/[ \t]*,[ \t]*/) end result end
# File lib/puppet/provider/package/pkgin.rb, line 12 def self.parse_pkgin_line(package) # e.g. # vim-7.2.446 = Vim editor (vi clone) without GUI match, name, version, status = *package.match(/(\S+)-(\S+)(?: (=|>|<))?\s+.+$/) if match { :name => name, :status => status, :ensure => version } end end
# File lib/puppet/provider/package/sun.rb, line 38 def self.parse_pkginfo(out) # collect all the lines with : in them, and separate them out by ^$ pkgs = [] pkg = {} out.each_line do |line| case line.chomp when /^\s*$/ pkgs << pkg unless pkg.empty? pkg = {} when /^\s*([^:]+):\s+(.+)$/ pkg[$1] = $2 end end pkgs << pkg unless pkg.empty? pkgs end
Turn our pkgutil -c listing into a bunch of hashes.
# File lib/puppet/provider/package/pkgutil.rb, line 87 def self.parse_pkglist(output, hash = {}) output = output.split("\n") if output[-1] == "Not in catalog" Puppet.warning "Package not in pkgutil catalog: %s" % hash[:justme] return nil end list = output.collect do |line| next if line =~ /installed\s+catalog/ # header of package list next if noise?(line) pkgsplit(line) end.reject { |h| h.nil? } if hash[:justme] # Single queries may have been for an alias so return the name requested if list.any? list[-1][:name] = hash[:justme] return list[-1] end else list.reject! { |h| h[:ensure] == :absent } return list end end
@api private
# File lib/puppet/provider/service/openbsd.rb, line 100 def self.parse_rc_line(rc_line) rc_line.sub!(/\s*#(.*)$/,'') regex = /\w+_flags=(.*)/ rc_line.match(regex)[1].gsub(/^"/,'').gsub(/"$/,'') end
# File lib/puppet/provider/user/directoryservice.rb, line 494 def self.password_hash_dir '/var/db/shadow/hash' end
pkg state was present in the older version of pkg (with UFOXI) but is no longer available with the IFO field version. When it was present, it was used to indicate that a particular version was present (installed) and later versions were known. Note that according to the pkg man page, known never lists older versions of the package. So we can rely on this field to make sure that if a known is present, then the pkg is upgradable.
# File lib/puppet/provider/package/pkg.rb, line 78 def self.pkg_state(state) case state when /installed/ {:status => 'installed'} when /known/ {:status => 'known'} else raise ArgumentError, 'Unknown format %s: %s' % [self.name, state] end end
# File lib/puppet/provider/package/aix.rb, line 101 def self.pkglist(hash = {}) cmd = [command(:lslpp), "-qLc"] if name = hash[:pkgname] cmd << name end begin list = execute(cmd).scan(/^[^#][^:]*:([^:]*):([^:]*)/).collect { |n,e| { :name => n, :ensure => e, :provider => self.name } } rescue Puppet::ExecutionFailure => detail if hash[:pkgname] return nil else raise Puppet::Error, "Could not list installed Packages: #{detail}", detail.backtrace end end if hash[:pkgname] return list.shift else return list end end
Split the different lines into hashes.
# File lib/puppet/provider/package/pkgutil.rb, line 125 def self.pkgsplit(line) if line =~ /\s*(\S+)\s+(\S+)\s+(.*)/ hash = {} hash[:name] = $1 hash[:ensure] = if $2 == "notinst" :absent else $2 end hash[:avail] = $3 if hash[:avail] =~ /^SAME\s*$/ hash[:avail] = hash[:ensure] end # Use the name method, so it works with subclasses. hash[:provider] = self.name return hash else Puppet.warning "Cannot match %s" % line return nil end end
# File lib/puppet/provider/macauthorization/macauthorization.rb, line 64 def populate_rules_rights auth_plist = Plist::parse_xml(AuthDB) raise Puppet::Error.new("Cannot parse: #{AuthDB}") if not auth_plist self.rights = auth_plist["rights"].dup self.rules = auth_plist["rules"].dup self.parsed_auth_db = self.rights.dup self.parsed_auth_db.merge!(self.rules.dup) end
Fetch the state of all service resources
# File lib/puppet/provider/service/openbsd.rb, line 29 def self.prefetch(resources) services = instances resources.keys.each do |name| if provider = services.find { |svc| svc.name == name } resources[name].provider = provider end end end
Collapse name and env records.
# File lib/puppet/provider/cron/crontab.rb, line 186 def self.prefetch_hook(records) name = nil envs = nil result = records.each { |record| case record[:record_type] when :comment if record[:name] name = record[:name] record[:skip] = true # Start collecting env values envs = [] end when :environment # If we're collecting env values (meaning we're in a named cronjob), # store the line and skip the record. if envs envs << record[:line] record[:skip] = true end when :blank # nothing else if name record[:name] = name name = nil else cmd_string = record[:command].gsub(/\s+/, "_") index = ( @name_index += 1 ) record[:name] = "unmanaged:#{cmd_string}-#{ index.to_s }" record[:unmanaged] = true end if envs.nil? or envs.empty? record[:environment] = :absent else # Collect all of the environment lines, and mark the records to be skipped, # since their data is included in our crontab record. record[:environment] = envs # And turn off env collection again envs = nil end end }.reject { |record| record[:skip] } result end
# File lib/puppet/vendor/semantic/spec/unit/semantic/version_range_spec.rb, line 224 def self.range(x, y, ex = false) Semantic::VersionRange.new(v(x), v(y), ex) end
# File lib/puppet/provider/service/openbsd.rb, line 9 def self.rcconf() '/etc/rc.conf' end
# File lib/puppet/provider/service/openbsd.rb, line 10 def self.rcconf_local() '/etc/rc.conf.local' end
Return a hash where the keys are the rc script names as symbols with flags as values @api private
# File lib/puppet/provider/service/openbsd.rb, line 56 def self.rcflags unless @flag_hash Puppet.debug "Retrieving flags for all discovered services" Puppet.debug "Reading the contents of the rc conf files" if File.exists?(rcconf_local()) rcconf_local_contents = File.readlines(rcconf_local()) else rcconf_local_contents = [] end if File.exists?(rcconf()) rcconf_contents = File.readlines(rcconf()) else rcconf_contents = [] end @flag_hash = {} rclist().each do |rcitem| rcname = rcitem.split('/').last if flagline = rcconf_local_contents.find {|l| l =~ /^#{rcname}_flags/ } flag = parse_rc_line(flagline) @flag_hash[rcname.to_sym] ||= flag end # For the defaults, if the flags are set to 'NO', we skip setting the # flag here, since it will already be disabled, and this makes the # output of `puppet resource service` a bit more correct. if flagline = rcconf_contents.find {|l| l =~ /^#{rcname}_flags/ } flag = parse_rc_line(flagline) unless flag == "NO" @flag_hash[rcname.to_sym] ||= flag end end @flag_hash[rcname.to_sym] ||= nil end end @flag_hash end
Return the list of rc scripts @api private
# File lib/puppet/provider/service/openbsd.rb, line 40 def self.rclist unless @rclist Puppet.debug "Building list of rc scripts" @rclist = [] defpath.each do |p| Dir.glob(p + '/*').each do |item| @rclist << item if File.executable?(item) end end end @rclist end
Read a plist, whether its format is XML or in Apple’s “binary1” format.
# File lib/puppet/provider/service/launchd.rb, line 206 def self.read_plist(path) begin return Plist::parse_xml(path) rescue ArgumentError, NoMethodError => detail Puppet.debug("Error reading #{path}: #{detail}. Retrying with plutil.") end begin Plist::parse_xml(plutil('-convert', 'xml1', '-o', '/dev/stdout', path)) rescue Puppet::ExecutionFailure => detail Puppet.warning("Cannot read file #{path}; Puppet is skipping it. \n" + "Details: #{detail}") return nil end end
Enumerate all files that may contain yum repository configs. ‘/etc/yum.conf’ is always included.
@api private @return [Array<String>
# File lib/puppet/provider/yumrepo/inifile.rb, line 117 def self.repofiles files = ["/etc/yum.conf"] reposdir.each do |dir| Dir.glob("#{dir}/*.repo").each do |file| files << file end end files 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<String>] Default locations for yum repos. @return [Array<String>] All present directories that may contain yum repo configs.
# File lib/puppet/provider/yumrepo/inifile.rb, line 74 def self.reposdir(conf='/etc/yum.conf', dirs=['/etc/yum.repos.d', '/etc/yum/repos.d']) reposdir = find_conf_value('reposdir', conf) # Use directories in reposdir if they are set instead of default dirs = reposdir.split(",").map(&:strip) 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? Puppet.debug('No yum directories were found on the local filesystem') end dirs end
# File lib/puppet/type/resources.rb, line 184 def self.reset_system_users_max_uid! @system_users_max_uid = nil end
Look up a resource with a given name whose user matches a record target
@api private
@note This overrides the ParsedFile method for finding resources by name,
so that only records for a given user are matched to resources of the same user so that orphaned records in other crontabs don't get falsely matched (#2251)
@param [Hash<Symbol, Object>] record @param [Array<Puppet::Resource>] resources
@return [Puppet::Resource, nil] The resource if found, else nil
# File lib/puppet/provider/cron/crontab.rb, line 113 def self.resource_for_record(record, resources) resource = super if resource target = resource[:target] || resource[:user] if record[:target] == target resource end end end
This method will return a list of files in the passed directory. This method does not go recursively down the tree and does not return directories
@param path [String] The directory to glob
@api private
@return [Array] of String instances modeling file paths
# File lib/puppet/provider/service/launchd.rb, line 123 def self.return_globbed_list_of_file_paths(path) array_of_files = Dir.glob(File.join(path, '*')).collect do |filepath| File.file?(filepath) ? filepath : nil end array_of_files.compact 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
# File lib/puppet/provider/yumrepo/inifile.rb, line 162 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
# File lib/puppet/type/zone.rb, line 71 def self.seqvalue(name, hash) fsm.insert_state(name, hash) self.newvalue name end
# File lib/puppet/provider/package/nim.rb, line 31 def self.srclistcmd(source) [ command(:nimclient), "-o", "showres", "-a", "installp_flags=L", "-a", "resource=#{source}" ] end
# File lib/puppet/type/zone.rb, line 87 def self.state_sequence(first, second) fsm.sequence(first, second) end
Save all yum repository files and force the mode to 0644 @api private @return [void]
# File lib/puppet/provider/yumrepo/inifile.rb, line 183 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
# File lib/puppet/util/log/destinations.rb, line 2 def self.suitable?(obj) Puppet.features.syslog? end
# File lib/puppet/type/resources.rb, line 163 def self.system_users_max_uid return @system_users_max_uid if @system_users_max_uid # First try to read the minimum user id from login.defs if Puppet::FileSystem.exist?('/etc/login.defs') @system_users_max_uid = Puppet::FileSystem.each_line '/etc/login.defs' do |line| break $1.to_i - 1 if line =~ /^\s*UID_MIN\s+(\d+)(\s*#.*)?$/ end end # Otherwise, use a sensible default based on the OS family @system_users_max_uid ||= case Facter.value(:osfamily) when 'OpenBSD', 'FreeBSD' 999 else 499 end @system_users_max_uid end
# File lib/puppet/vendor/semantic/spec/unit/semantic/version_range_spec.rb, line 7 def self.test_range(range_list, str, includes, excludes) Array(range_list).each do |expr| example "#{expr.inspect} stringifies as #{str}" do range = Semantic::VersionRange.parse(expr) expect(range.to_s).to eql str end includes.each do |vstring| example "#{expr.inspect} includes #{vstring}" do range = Semantic::VersionRange.parse(expr) expect(range).to include(Semantic::Version.parse(vstring)) end example "parse(#{expr.inspect}).to_s includes #{vstring}" do range = Semantic::VersionRange.parse(expr) range = Semantic::VersionRange.parse(range.to_s) expect(range).to include(Semantic::Version.parse(vstring)) end end excludes.each do |vstring| example "#{expr.inspect} excludes #{vstring}" do range = Semantic::VersionRange.parse(expr) expect(range).to_not include(Semantic::Version.parse(vstring)) end example "parse(#{expr.inspect}).to_s excludes #{vstring}" do range = Semantic::VersionRange.parse(expr) range = Semantic::VersionRange.parse(range.to_s) expect(range).to_not include(Semantic::Version.parse(vstring)) end end end end
# File lib/puppet/type/file.rb, line 39 def self.title_patterns [ [ /^(.*?)\/*\Z/, [ [ :path ] ] ] ] end
# File lib/puppet/provider/cron/crontab.rb, line 233 def self.to_file(records) text = super # Apparently Freebsd will "helpfully" add a new TZ line to every # single cron line, but not in all cases (e.g., it doesn't do it # on my machine). This is my attempt to fix it so the TZ lines don't # multiply. if text =~ /(^TZ=.+\n)/ tz = $1 text.sub!(tz, '') text = tz + text end text end
# File lib/puppet/provider/package/windows.rb, line 43 def self.to_hash(pkg) { :name => pkg.name, :ensure => pkg.version || :installed, :provider => :windows } end
The UFOXI field is the field present in the older pkg (solaris 2009.06 - snv151a) similar to IFO, UFOXI is also an either letter or - u_pdate indicates that an update for the package is available. f_rozen(n/i) o_bsolete x_cluded(n/i) i_constrained(n/i) note that u_pdate flag may not be trustable due to constraints. so we dont rely on it Frozen was never implemented in UFOXI so skipping frozen here.
# File lib/puppet/provider/package/pkg.rb, line 68 def self.ufoxi_flag(flags) {} end
# File lib/puppet/vendor/semantic/spec/unit/semantic/version_range_spec.rb, line 220 def self.v(num) Semantic::Version.parse("#{num}.0.0") 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.
# File lib/puppet/provider/yumrepo/inifile.rb, line 148 def self.valid_property?(key) PROPERTIES.include?(key) 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.
# File lib/puppet/provider/yumrepo/inifile.rb, line 133 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
# File lib/puppet/provider/interface/cisco.rb, line 17 def initialize(device, *args) super end