BasicObject
We need this because the RAL uses ‘should’ as a method. This allows us the same behaviour but with a different method name.
Add our wrapper to the method.
Behavior for custom classes
msdn.microsoft.com/en-us/library/windows/desktop/aa368542(v=vs.85).aspx
The query format by which we identify installed packages
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.
# File lib/puppet/type/file.rb, line 304 def self.[](path) return nil unless path super(path.gsub(/\/+/, '/').sub(/\/$/, '')) end
# File lib/puppet/type/zone.rb, line 63 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"] list = 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
# File lib/puppet/provider/package/pip.rb, line 38 def self.cmd case Facter.value(:osfamily) when "RedHat" "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 201 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 - -', mode='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 188 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 - -', mode='r+') do |io| io.write Plist::Emit.dump(plist_data) io.close_write @converted_plist = io.read end @converted_plist 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 49 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 40 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
# File lib/puppet/provider/service/bsd.rb, line 16 def self.defpath superclass.defpath end
removes all reports for a given host?
# File lib/puppet/reports/store.rb, line 52 def self.destroy(host) validate_host(host) dir = File.join(Puppet[:reportdir], host) if File.exists?(dir) Dir.entries(dir).each do |file| next if ['.','..'].include?(file) file = File.join(dir, file) File.unlink(file) if File.file?(file) end Dir.rmdir(dir) end 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 40 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 130 def self.eix_result_fields [:category, :name, :ensure, :version_available, :vendor, :description] end
# File lib/puppet/provider/package/portage.rb, line 126 def self.eix_result_format /^(\S+)\s+(\S+)\s+\[(\S*)\]\s+\[(\S*)\]\s+(\S+)\s+(.*)$/ end
# File lib/puppet/provider/package/portage.rb, line 138 def self.eix_search_arguments ["--nocolor", "--pure-packages", "--format",self.eix_search_format] end
# File lib/puppet/provider/package/portage.rb, line 122 def self.eix_search_format "'<category> <name> [<installedversions:LASTVERSION>] [<bestversion:LASTVERSION>] <homepage> <description>'" end
# File lib/puppet/provider/package/portage.rb, line 134 def self.eix_version_format "{last}<version>{}" 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 FileTest.exists?("/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
# File lib/puppet/type/zone.rb, line 58 def self.fsm return @fsm if @fsm @fsm = StateMachine.new end
# File lib/puppet/provider/package/gem.rb, line 15 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}" end if options[:justme] return list.shift else return list end end
# File lib/puppet/provider/package/gem.rb, line 45 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, :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 98 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 90 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 174 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 181 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
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 167 def self.get_list_of_groups @groups ||= Plist.parse_xml(dscl '-plist', '.', 'readall', '/Groups') end
# File lib/puppet/provider/service/launchd.rb, line 202 def self.get_macosx_version_major return @macosx_version_major if @macosx_version_major begin # Make sure we've loaded all of the facts Facter.loadfacts product_version_major = Facter.value(:macosx_productversion_major) fail("#{product_version_major} is not supported by the launchd provider") if %{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 fail("Could not determine OS X version: #{detail}") end end
# File lib/puppet/provider/user/directoryservice.rb, line 161 def self.get_os_version @os_version ||= Facter.value(:macosx_productversion_major) 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 215 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 223 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 27 def self.get_services(defpath, exclude=[]) 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 238 def self.get_sha1(guid) password_hash = nil password_hash_file = "#{password_hash_dir}/#{guid}" if File.exists?(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
Get the groupname from its id
# File lib/puppet/provider/user/aix.rb, line 149 def self.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
# 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
# File lib/puppet/provider/package/pkgutil.rb, line 16 def self.healthcheck() unless FileTest.exists?("/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
# File lib/puppet/provider/package/pkgdmg.rb, line 46 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) unless source =~ /\.dmg$/ self.fail "Mac OS X PKG DMG's must specify a source string ending in .dmg" end require 'open-uri' require 'facter/util/plist' cached_source = source tmpdir = Dir.mktmpdir begin if %{\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, force=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/group/windows_adsi.rb, line 51 def self.instances Puppet::Util::ADSI::Group.map { |g| new(:ensure => :present, :name => g.name) } 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 136 def self.is_init?(script = initscript) !File.symlink?(script) || File.readlink(script) != "/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 154 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 119 def self.jobsearch(label=nil) @label_to_path_map ||= {} if @label_to_path_map.empty? 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") if job["Label"] == label return { label => filepath } else @label_to_path_map[job["Label"]] = filepath end else Puppet.warning("The #{filepath} plist does not contain a 'label' key; " + "Puppet is skipping it") next end end end end if label if @label_to_path_map.has_key? label return { label => @label_to_path_map[label] } else raise Puppet::Error.new("Unable to find launchd plist for job: #{label}") end else @label_to_path_map end end
Defines the path to the overrides plist file where service enabling behavior is defined in 10.6 and greater.
@api private
# File lib/puppet/provider/service/launchd.rb, line 73 def self.launchd_overrides "/var/db/launchd.db/com.apple.launchd/overrides.plist" 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
# File lib/puppet/provider/package/freebsd.rb, line 14 def self.listcmd command(:pkginfo) end
# File lib/puppet/provider/interface/cisco.rb, line 9 def self.lookup(device, name) interface = nil device.command do |ng| interface = device.interface(name) end interface 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 89 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] gid = group[:gid][0] end
# File lib/puppet/provider/package/sun.rb, line 28 def self.namemap(hash) Namemap.keys.inject({}) do |hsh,k| hsh.merge(Namemap[k] => hash[k]) end end
# File lib/puppet/provider/package/rpm.rb, line 124 def self.nevra_to_hash(line) line.chomp! hash = {} NEVRA_FIELDS.zip(line.split) { |f, v| hash[f] = v } hash[:provider] = self.name hash[:ensure] = "#{hash[:version]}-#{hash[:release]}" hash end
# File lib/puppet/provider/interface/cisco.rb, line 17 def initialize(device, *args) super 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 253 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 258 def self.normalized_time(time_string) Time.parse("#{time_string}").strftime('%H:%M') end
# File lib/puppet/provider/user/directoryservice.rb, line 56 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 16 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
# File lib/puppet/provider/package/dpkg.rb, line 40 def self.parse_line(line) if match = self::REGEX.match(line) hash = {} self::FIELDS.zip(match.captures) { |field,value| hash[field] = value } 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.warning "Failed to match dpkg-query line #{line.inspect}" return nil end 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 71 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, force_status=nil) # e.g. # vim-7.2.446 = Vim editor (vi clone) without GUI match, name, version, status = *package.match(/(\S+)-(\S+)(?: (=|>|<))?\s+.+$/) if match ensure_status = if force_status force_status elsif status :present else :absent end { :name => name, :ensure => ensure_status, :provider => :pkgin } end end
# File lib/puppet/provider/package/sun.rb, line 34 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
# File lib/puppet/provider/user/directoryservice.rb, line 480 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 77 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}" 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
# File lib/puppet/provider/macauthorization/macauthorization.rb, line 51 def prefetch(resources) self.populate_rules_rights end
Every entry in fstab is :unmounted until we can prove different
# File lib/puppet/provider/mount/parsed.rb, line 43 def self.prefetch_hook(target_records) target_records.collect do |record| record[:ensure] = :unmounted if record[:record_type] == :parsed record end end
Read a plist, whether its format is XML or in Apple’s “binary1” format.
# File lib/puppet/provider/service/launchd.rb, line 182 def self.read_plist(path) 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
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 108 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
# File lib/puppet/type/zone.rb, line 69 def self.seqvalue(name, hash) fsm.insert_state(name, hash) self.newvalue name end
# File lib/puppet/provider/package/aix.rb, line 20 def self.srclistcmd(source) [ command(:installp), "-L", "-d", source ] end
# File lib/puppet/type/zone.rb, line 85 def self.state_sequence(first, second) fsm.sequence(first, second) end
# File lib/puppet/util/log/destinations.rb, line 2 def self.suitable?(obj) Puppet.features.syslog? end
# File lib/puppet/type/file.rb, line 36 def self.title_patterns [ [ /^(.*?)\/*\Z/, [ [ :path ] ] ] ] end
# File lib/puppet/provider/package/windows.rb, line 37 def self.to_hash(pkg) { :name => pkg.name, # we're not versionable, so we can't set the ensure # parameter to the currently installed version :ensure => :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
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 77 def able_to_ensure_absent?(resource) resource[:ensure] = :absent rescue ArgumentError, Puppet::Error => detail 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 130 def add_cmd(cmd) @cmds = [] if @cmds.nil? @cmds << cmd end
# File lib/puppet/provider/service/upstart.rb, line 328 def add_default_start_to(text) text + "\nstart on runlevel [2,3,4,5]" end
must override this to hand the keyvalue pairs
# File lib/puppet/provider/user/user_role_add.rb, line 31 def add_properties cmd = [] Puppet::Type.type(:user).validproperties.each do |property| #skip the password because we can't create it with the solaris useradd next if [:ensure, :password, :password_min_age, :password_max_age].include?(property) # 1680 Now you can set the hashed passwords on solaris:lib/puppet/provider/user/user_role_add.rb # the value needs to be quoted, mostly because -c might # have spaces in it if value = @resource.should(property) and value != "" if property == :keys cmd += build_keys_cmd(value) else cmd << flag(property) << value end end end cmd end
# File lib/puppet/provider/group/aix.rb, line 69 def addcmd(extra_attrs = []) # Here we use the @resource.to_hash to get the list of provided parameters # Puppet does not call to self.<parameter>= method if it does not exists. # # It gets an extra list of arguments to add to the user. [self.class.command(:add) ] + self.get_ia_module_args +<EMAIL_ADDRESS>+ extra_attrs + [@resource[:name]] 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}"} %{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.
@returns [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 135 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 => detail 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 256 def alpha %{sunday monday tuesday wednesday thursday friday saturday} end
# File lib/puppet/type/file.rb, line 382 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 56 def arguments task.parameters end
# File lib/puppet/provider/scheduled_task/win32_taskscheduler.rb, line 151 def arguments=(value) task.parameters = value end
Determine the user to write files as.
# File lib/puppet/type/file.rb, line 314 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(refresh = 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 #{<EMAIL_ADDRESS>#{detail}" 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 109 def auths user_attributes[:auths] if user_attributes 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 584 def base64_decode_string(value) Base64.decode64([[value].pack("H*")].pack("m").strip) end
# File lib/puppet/provider/scheduled_task/win32_taskscheduler.rb, line 393 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 412 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 379 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 329 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 137 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 83 def build_vdevs if disk = @resource[:disk] disk.collect { |d| d.split(' ') }.flatten elsif mirror = @resource[:mirror] ["mirror"] + mirror elsif raidz = @resource[:raidz] [raidzarity] + raidz end end
Make output a bit prettier
# File lib/puppet/type/augeas.rb, line 201 def change_to_s(currentvalue, newvalue) "executed successfully" end
# File lib/puppet/type/resources.rb, line 67 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/user/useradd.rb, line 29 def check_allow_dup @resource.allowdupe? ? ["-o"] : [] end
# File lib/puppet/provider/user/useradd.rb, line 43 def check_manage_expiry cmd = [] if @resource[:expiry] cmd << "-e #{@resource[:expiry]}" end cmd end
# File lib/puppet/provider/user/useradd.rb, line 33 def check_manage_home cmd = [] if @resource.managehome? cmd << "-m" elsif 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/msi.rb, line 98 def check_result(hr) operation = resource[:ensure] == :absent ? 'uninstall' : 'install' # http://msdn.microsoft.com/en-us/library/windows/desktop/aa368542(v=vs.85).aspx case hr when 0 # yeah when 194 warning("The package requested a reboot to finish the operation.") when 1641 warning("The package #{operation}ed successfully and the system is rebooting now.") when 3010 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 52 def check_system_users if self.class.system_users? and resource.system? ["-r"] else [] end end
Verify that we have the executable
# File lib/puppet/provider/exec/posix.rb, line 15 def checkexe(command) exe = extractexe(command) if File.expand_path(exe) == exe if !File.exists?(exe) raise ArgumentError, "Could not find command '#{exe}'" elsif !File.file?(exe) raise ArgumentError, "'#{exe}' is a #{File.ftype(exe)}, not a file" elsif !File.executable?(exe) raise ArgumentError, "'#{exe}' is not executable" end return end if resource[:path] Puppet::Util.withenv :PATH => resource[:path].join(File::PATH_SEPARATOR) do return if which(exe) end end # 'which' will only return the command if it's executable, so we can't # distinguish not found from not executable 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 25 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 43 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 194 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 52 def command task.application_name end
# File lib/puppet/provider/scheduled_task/win32_taskscheduler.rb, line 147 def command=(value) task.application_name = value end
# File lib/puppet/provider/user/windows_adsi.rb, line 61 def comment=(value) user['Description'] = value end
# File lib/puppet/provider/service/upstart.rb, line 293 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 317 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 112 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<EMAIL_ADDRESS>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 112 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/group/windows_adsi.rb, line 23 def create @group = Puppet::Util::ADSI::Group.create(@resource[:name]) @group.commit self.members = @resource[:members] end
Create the new user with dscl
# File lib/puppet/provider/user/directoryservice.rb, line 494 def create_new_user(username) dscl '.', '-create', "/Users/#{username}" end
# File lib/puppet/provider/user/user_role_add.rb, line 97 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
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 65 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 24 def data @last_logs.synchronize { @last_logs.dup } end
If they pass class information, we want to ignore it. By default, we’ll include class information but we won’t rely on it - we don’t want class names to be required because we then can’t change our internal class names, which is bad.
# File lib/puppet/network/formats.rb, line 123 def data_to_instance(klass, data) if data.is_a?(Hash) and d = data['data'] data = d end return data if data.is_a?(klass) klass.from_pson(data) end
# File lib/puppet/provider/scheduled_task/win32_taskscheduler.rb, line 514 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 526 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 435 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 453 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 73 def decode(yaml) requiring_zlib do YAML.load(Zlib::Inflate.inflate(Base64.decode64(yaml))) end end
# File lib/puppet/type/file.rb, line 351 def default_bucket Puppet::Type.type(:filebucket).mkdefaultbucket.bucket end
# File lib/puppet/provider/group/windows_adsi.rb, line 34 def delete Puppet::Util::ADSI::Group.delete(@resource[:name]) 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
# File lib/puppet/provider/macauthorization/macauthorization.rb, line 99 def destroy # We explicitly delete here rather than in the flush method. case resource[:auth_type] when :right destroy_right when :rule destroy_rule else raise Puppet::Error.new("Must specify auth_type when destroying.") end 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}") end end end
# File lib/puppet/provider/ssh_authorized_key/parsed.rb, line 35 def dir_perm 0700 end
remove service file from rc.conf.d to disable it
# File lib/puppet/provider/service/bsd.rb, line 21 def disable rcfile = File.join(rcconf_dir, @model[:name]) File.delete(rcfile) if File.exists?(rcfile) end
# File lib/puppet/provider/service/upstart.rb, line 261 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 252 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 257 def disable_pre_0_9_0(script_text) write_script_to(initscript, ensure_disabled_with_manual(script_text)) end
Actually execute the augeas changes.
# File lib/puppet/provider/augeas/augeas.rb, line 422 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/provider/scheduled_task/win32_taskscheduler.rb, line 262 def dummy_time_trigger now = Time.now { 'flags' => 0, 'random_minutes_interval' => 0, 'end_day' => 0, "end_year" => 0, "trigger_type" => 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
enable service by creating a service file under rc.conf.d with the proper contents
# File lib/puppet/provider/service/bsd.rb, line 36 def enable Dir.mkdir(rcconf_dir) if not File.exists?(rcconf_dir) rcfile = File.join(rcconf_dir, @model[:name]) open(rcfile, 'w') { |f| f << "%s_enable=\"YES\"\n" % @model[:name] } end
# File lib/puppet/provider/service/upstart.rb, line 238 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 220 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 48 def enabled task.flags & Win32::TaskScheduler::DISABLED == 0 ? :true : :false end
# File lib/puppet/provider/scheduled_task/win32_taskscheduler.rb, line 159 def enabled=(value) if value == :true task.flags = task.flags & ~Win32::TaskScheduler::DISABLED else task.flags = task.flags | Win32::TaskScheduler::DISABLED end end
if the service file exists in rc.conf.d then it’s already enabled
# File lib/puppet/provider/service/bsd.rb, line 27 def enabled? rcfile = File.join(rcconf_dir, @model[:name]) return :true if File.exists?(rcfile) :false end
# File lib/puppet/provider/service/upstart.rb, line 197 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 173 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 182 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/network/formats.rb, line 67 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 332 def ensure_disabled_with_manual(text) remove_manual_from(text) + "\nmanual" end
# File lib/puppet/face/node/clean.rb, line 146 def environment @environment ||= Puppet::Node::Environment.new end
# File lib/puppet/face/help.rb, line 116 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 370 def eval_generate return [] unless self.recurse? recurse #recurse.reject do |resource| # catalog.resource(:file, resource[:path]) #end.each do |child| # catalog.add_resource child # catalog.relationship_graph.add_edge self, child #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 :horribly_extract_summary_from
# File lib/puppet/face/help.rb, line 175 def exclude_from_docs?(appname) %{face_base indirection_base}.include? appname end
# File lib/puppet/provider/package/pkg.rb, line 186 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] end output end
# File lib/puppet/provider/augeas/augeas.rb, line 400 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 with return code #{success}, 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 357 def exist? stat ? true : false end
# File lib/puppet/provider/group/windows_adsi.rb, line 30 def exists? Puppet::Util::ADSI::Group.exists?(@resource[:name]) end
# File lib/puppet/provider/package/msi.rb, line 91 def exit_status $CHILD_STATUS.exitstatus end
Get expiry from system and convert to Puppet-style date
# File lib/puppet/provider/user/pw.rb, line 89 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 201 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 #{<EMAIL_ADDRESS>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 190 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 318 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
Make sure the file we wrote out is what we think it is.
# File lib/puppet/type/file.rb, line 755 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/ssh_authorized_key/parsed.rb, line 39 def file_perm 0600 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
We have to do some extra finishing, to retrieve our bucket if there is one.
# File lib/puppet/type/file.rb, line 363 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
Only flush if we created or modified a group, not deleted
# File lib/puppet/provider/group/windows_adsi.rb, line 39 def flush @group.commit if @group end
# File lib/puppet/provider/user/directoryservice.rb, line 539 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
Generate any new resources we need to manage. This is pretty hackish right now, because it only supports purging.
# File lib/puppet/type/resources.rb, line 86 def generate return [] unless self.purge? resource_type.instances. reject { |r| catalog.resource_refs.include? r.ref }. select { |r| check(r) }. select { |r| r.class.validproperty?(:ensure) }. select { |r| able_to_ensure_absent?(r) }. each { |resource| @parameters.each do |name, param| resource[name] = param.value if param.metaparam? end # Mark that we're purging, so transactions can handle relationships # correctly resource.purging } 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 #{<EMAIL_ADDRESS>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 303 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 152 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 286 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 File.exists?("#{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
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 551 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 60 def get_start_link_count Dir.glob("/etc/rc*.d/S*#{@resource[:name]}").length end
# File lib/puppet/provider/user/directoryservice.rb, line 543 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 88 def get_version execpipe([command(:pkginfo), "-I", @resource[:name]]) do |process| # our regex for matching pkg_info output regex = /^(.*)-(\d[^-]*)[-]?(\D*)(.*)$/ fields = [ :name, :version, :flavor ] 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: <IP_ADDRESS> physical: eg0001 defrouter not specified
net:
address: <IP_ADDRESS> physical: eg0002 defrouter not specified
# File lib/puppet/provider/zone/solaris.rb, line 216 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 43 def gid Puppet::Util::Windows::Security.name_to_sid(@resource[:name]) end
# File lib/puppet/provider/file/posix.rb, line 33 def gid2name(id) return id.to_s if id.is_a?(Symbol) or id.is_a?(String) return nil if id > Puppet[:maximum_uid].to_i begin group = Etc.getgrgid(id) rescue TypeError, ArgumentError return nil end if group.gid == "" return nil else return group.name end end
# File lib/puppet/provider/group/windows_adsi.rb, line 47 def gid=(value) fail "gid is read-only" end
Get the group gid from its name
# File lib/puppet/provider/user/aix.rb, line 184 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 179 def gid_to_attr(value) verify_group(value) end
# File lib/puppet/provider/file/posix.rb, line 87 def group return :absent unless stat = resource.stat currentvalue = stat.gid # On OS X, files that are owned by -2 get returned as really # large GIDs instead of negative ones. This isn't a Ruby bug, # it's an OS X bug, since it shows up in perl, too. if currentvalue > Puppet[:maximum_uid].to_i self.warning "Apparently using negative GID (#{currentvalue}) on a platform that does not consistently handle them" currentvalue = :silly end currentvalue end
Convert a gropu name to an id.
# File lib/puppet/provider/user/ldap.rb, line 112 def group2id(group) Puppet::Type.type(:group).provider(:ldap).name2id(group) end
# File lib/puppet/provider/file/posix.rb, line 103 def group=(should) # Set our method appropriately, depending on links. if resource[:links] == :manage method = :lchown else method = :chown end begin File.send(method, nil, should, resource[:path]) rescue => detail raise Puppet::Error, "Failed to set group to '#{should}': #{detail}" end end
# File lib/puppet/provider/user/ldap.rb, line 118 def group_manager Puppet::Type.type(:group).provider(:ldap).manager end
# File lib/puppet/provider/user/ldap.rb, line 122 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 161 def groupid_by_name(groupname) attrs = self.parse_attr_list(execute(lsgroupscmd(groupname)).split("\n")[0], nil) attrs ? attrs[:id].to_i : nil end
Find all groups this user is a member of in ldap.
# File lib/puppet/provider/user/ldap.rb, line 56 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/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
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 172 def has_macosx_plist_overrides? @product_version ||= self.class.get_macosx_version_major # (#11593) Remove support for OS X 10.4 & earlier # leaving this as is because 10.5 still didn't have plist support return true unless /^10\.[0-5]/.match(@product_version) return false 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 53 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 135 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 65 def home user['HomeDirectory'] end
# File lib/puppet/provider/user/windows_adsi.rb, line 69 def home=(value) user['HomeDirectory'] = value end
# File lib/puppet/face/help.rb, line 152 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::Security.valid_sid?(id) Puppet::Util::Windows::Security.sid_to_name(id) else id end end
# File lib/puppet/provider/package/sun.rb, line 114 def if_have_value(prefix, value) if value [prefix, value] else [] end end
Get info on a package, optionally specifying a device.
# File lib/puppet/provider/package/sun.rb, line 60 def info2hash(device = nil) cmd = [command(:pkginfo), '-l'] cmd << '-d' << device if device cmd << @resource[:name] pkgs = self.class.parse_pkginfo(execute(cmd, :failonfail => false, :combine => false)) errmsg = case pkgs.size when 0; 'No message' when 1; pkgs[0]['ERROR'] end return self.class.namemap(pkgs[0]) if errmsg.nil? return {:ensure => :absent} if errmsg =~ /information for "#{Regexp.escape(@resource[:name])}"/ raise Puppet::Error, "Unable to get information about package #{@resource[:name]} because of: #{errmsg}" end
Where is our init script?
# File lib/puppet/provider/service/init.rb, line 63 def initscript @initscript ||= self.search(@resource[:name]) end
# File lib/puppet/provider/package/aix.rb, line 65 def install(useversion = true) unless source = @resource[:source] self.fail "A directory is required which will be used to find packages" end pkg = @resource[:name] pkg << " #{@resource.should(:ensure)}" if (! @resource.should(:ensure).is_a? Symbol) and useversion installp "-acgwXY", "-d", source, pkg end
# File lib/puppet/provider/package/pacman.rb, line 44 def install_from_file source = @resource[:source] begin source_uri = URI.parse source rescue => detail fail "Invalid source '#{source}': #{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 35 def install_from_repo if yaourt? yaourt "--noconfirm", "-S", @resource[:name] else pacman "--noconfirm", "--noprogressbar", "-Sy", @resource[:name] end end
# File lib/puppet/provider/package/msi.rb, line 120 def install_options join_options(resource[:install_options]) end
# File lib/puppet/util/monkey_patches.rb, line 244 def instance_variables puppet_original_instance_variables.map(&:to_sym) end
# File lib/puppet/type/cron.rb, line 303 def insync?(is) if is.is_a? Array return is.sort == @should.sort else return is == @should end end
Yaml doesn’t need the class name; it’s serialized.
# File lib/puppet/network/formats.rb, line 5 def intern(klass, text) YAML.load(text) end
Yaml doesn’t need the class name; it’s serialized.
# File lib/puppet/network/formats.rb, line 10 def intern_multiple(klass, text) YAML.load(text) 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 183 def is_face_app?(appname) clazz = Puppet::Application.find(appname) clazz.ancestors.include?(Puppet::Application::FaceBase) end
# File lib/puppet/provider/user/user_role_add.rb, line 63 def is_role? user_attributes and user_attributes[:type] == "role" end
# File lib/puppet/type/cron.rb, line 311 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 157 def is_upstart?(script = initscript) File.exists?(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 406 def iterations=(value) if (Puppet::Util::Package.versioncmp(self.class.get_os_version, '10.7') > 0) sleep 2 flush_dscl_cache users_plist =<EMAIL_ADDRESS>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/provider/package/msi.rb, line 132 def join_options(options) return unless options options.collect do |val| case val when Hash val.keys.sort.collect do |k| "#{k}=#{val[k]}" end.join(' ') else val end end end
# File lib/puppet/network/formats.rb, line 139 def json @json ||= Puppet::Network::FormatHandler.format(:pson) end
# File lib/puppet/provider/user/user_role_add.rb, line 130 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 145 def keys=(keys_hash) run([command(:modify)] + build_keys_cmd(keys_hash) << @resource[:name], "modify attribute key pairs") end
# File lib/puppet/provider/package/aix.rb, line 109 def latest upd = latest_info unless upd.nil? return "#{upd[:version]}" else raise Puppet::DevError, "Tried to get latest on a missing package" if properties[:ensure] == :absent return properties[:ensure] end end
# File lib/puppet/provider/package/pip.rb, line 109 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.' end end
Return a list of applications that are not simply just stubs for Faces.
# File lib/puppet/face/help.rb, line 124 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, it’s dependency status, and the location in the modulepath relative to it’s parent.
Returns a Hash
# File lib/puppet/face/module/list.rb, line 244 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 209 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 fail ArgumentError, Could not load help for the face #{facename}.Please check the error logs for more information.Detail: "#{detail.message}" 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
# 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 90 def lsgroupscmd(value=@resource[:name]) [command(:lsgroup)] + self.get_ia_module_args + ["-a", "id", value] end
# File lib/puppet/face/instrumentation_listener.rb, line 47 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/user_role_add.rb, line 121 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 Win32::Service::Error => detail raise Puppet::Error.new("Cannot enable #{@resource[:name]} for manual start, error was: #{detail}" ) end
Configure discovered resources to be purged.
# File lib/puppet/type/file.rb, line 416 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
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}" tmp = Tempfile.new('puppet_mcx') begin tmp << val tmp.flush dscl 'localhost', '-mcximport', ds_path, tmp.path ensure tmp.close tmp.unlink end end
# File lib/puppet/provider/group/windows_adsi.rb, line 15 def members group.members end
# File lib/puppet/provider/group/windows_adsi.rb, line 19 def members=(members) group.set_members(members) end
This method will merge in a given value using dscl
# File lib/puppet/provider/user/directoryservice.rb, line 485 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}" end 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 = %{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/posix.rb, line 118 def mode if stat = resource.stat return (stat.mode & 007777).to_s(8) else return :absent end end
# File lib/puppet/provider/file/posix.rb, line 126 def mode=(value) begin File.chmod(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 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 538 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 423 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 32 def multi_conf(name, should, &action) has = properties[name] has = [] if 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/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 107 def my_properties [:path, :iptype, :autoboot, :pool, :shares, :ip, :dataset, :inherit] end
# File lib/puppet/provider/file/posix.rb, line 50 def name2gid(value) Integer(value) rescue gid(value) || false 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::Security.name_to_sid(value) end
Determine if the user is valid, and if so, return the UID
# File lib/puppet/provider/file/posix.rb, line 29 def name2uid(value) Integer(value) rescue uid(value) || false end
Determines if augeas acutally needs to run.
# File lib/puppet/provider/augeas/augeas.rb, line 339 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("Save failed with return code #{save_result}, 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] notice "\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 577 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 425 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 500 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 15 def notify(label, event, data) return if event == :start log_line = "#{label} took #{data[:finished] - data[:started]}" @last_logs.synchronize { (@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 546 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 556 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 = true elsif glob_avail and opt_ctx restricted = true # 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 = true 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(:warning => restricted) end @aug end
Where is our override script?
# File lib/puppet/provider/service/upstart.rb, line 71 def overscript @overscript ||= initscript.gsub(/\.conf$/,".override") end
# File lib/puppet/provider/file/posix.rb, line 54 def owner unless stat = resource.stat return :absent end currentvalue = stat.uid # On OS X, files that are owned by -2 get returned as really # large UIDs instead of negative ones. This isn't a Ruby bug, # it's an OS X bug, since it shows up in perl, too. if currentvalue > Puppet[:maximum_uid].to_i self.warning "Apparently using negative UID (#{currentvalue}) on a platform that does not consistently handle them" currentvalue = :silly end currentvalue end
# File lib/puppet/provider/file/posix.rb, line 72 def owner=(should) # Set our method appropriately, depending on links. if resource[:links] == :manage method = :lchown else method = :chown end begin File.send(method, should, nil, resource[:path]) rescue => detail raise Puppet::Error, "Failed to set owner to '#{should}': #{detail}" end end
The common package name format.
# File lib/puppet/provider/package/portage.rb, line 60 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
Given the resource name string, parse ds_name out.
# File lib/puppet/provider/mcx/mcxcontent.rb, line 142 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
Given the resource name string, parse ds_type out.
# File lib/puppet/provider/mcx/mcxcontent.rb, line 126 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 90 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
*password*
The user's password, in whatever encrypted format the local machine requires. Be sure to enclose any value that includes a dollar sign ($) in single quotes ('). Requires features manages_passwords.
Retrieve the password parsing directly the /etc/security/passwd
# File lib/puppet/provider/user/aix.rb, line 227 def password password = :absent user = @resource[:name] f = File.open("/etc/security/passwd", 'r') # Skip to the user f.each_line { |l| break if l =~ /^#{user}:\s*$/ } if ! f.eof? f.each_line { |l| # If there is a new user stanza, stop break if l =~ /^\S*:\s*$/ # If the password= entry is found, return it if l =~ /^\s*password\s*=\s*(.*)$/ password = $1; break; end } end f.close() return password end
# File lib/puppet/provider/user/aix.rb, line 247 def password=(value) user = @resource[:name] # Puppet execute does not support strings as input, only files. tmpfile = Tempfile.new('puppet_#{user}_pw') tmpfile << "#{user}:#{value}\n" tmpfile.close() # Options '-e', '-c', use encrypted password and clear flags # Must receive "user:enc_password" as input # command, arguments = {:failonfail => true, :combine => true} # Fix for bugs #11200 and #10915 cmd = [self.class.command(:chpasswd), get_ia_module_args, '-e', '-c', user].flatten begin output = execute(cmd, {:failonfail => false, :combine => true, :stdinfile => tmpfile.path }) # chpasswd can return 1, even on success (at least on AIX 6.1); empty output indicates success if output != "" raise Puppet::ExecutionFailure, "chpasswd said #{output}" end rescue Puppet::ExecutionFailure => detail raise Puppet::Error, "Could not set #{param} on #{<EMAIL_ADDRESS>#{detail}" ensure tmpfile.delete() end end
# File lib/puppet/provider/user/user_role_add.rb, line 175 def password_max_age return :absent unless shadow_entry shadow_entry[4] || -1 end
# File lib/puppet/provider/user/user_role_add.rb, line 171 def password_min_age shadow_entry ? shadow_entry[3] : :absent end
Component paths are special because they function as containers.
# File lib/puppet/type/component.rb, line 37 def pathbuilder if reference.type == "Class" # 'main' is the top class, so we want to see '//' instead of # its name. if reference.title.to_s.downcase == "main" myname = "" else myname = reference.title end else myname = reference.to_s end if p = self.parent return [p.pathbuilder, myname] else return [myname] end end
# File lib/puppet/provider/service/init.rb, line 67 def paths @paths ||= @resource[:path].find_all do |path| if File.directory?(path) true else if File.exist?(path) and ! File.directory?(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 588 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 ) 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 221 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/provider/mailalias/aliases.rb, line 15 def post_parse(record) # LAK:NOTE See http://snurl.com/21zf8 [groups_google_com] # It's not sufficient to assign to an existing hash. recipient = record[:recipient].split(/\s*,\s*/).collect { |d| d.gsub(/^['"]|['"]$/, '') } record[:recipient] = recipient record end
# File lib/puppet/provider/package/sun.rb, line 106 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
Return the principals
# File lib/puppet/type/k5login.rb, line 58 def principals(dummy_argument=:work_arround_for_ruby_GC_bug) if File.exists?(@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 329 def print_errors(errors) errors.each do |errnode| @aug.match("#{errnode}/*").each do |subnode| subvalue = @aug.get(subnode) debug("#{subnode} = #{subvalue}") end end end
# File lib/puppet/provider/augeas/augeas.rb, line 311 def print_load_errors(args={}) errors = @aug.match("/augeas//error") unless errors.empty? if args[:warning] 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 323 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 23 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 205 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) || '' case comparator when "!=" return_value = (result != arg) when "=~" 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 231 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 190 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 113 def profiles user_attributes[:profiles] if user_attributes end
# File lib/puppet/provider/user/user_role_add.rb, line 117 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 779 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 96 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
Should we be purging?
# File lib/puppet/type/file.rb, line 470 def purge? @parameters.include?(:purge) and (self[:purge] == :true or self[:purge] == "true") 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 File.exists?(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 File.exists?(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 File.exists?(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
Extract rcvar name
# File lib/puppet/provider/service/freebsd.rb, line 41 def rcvar_name name = self.rcvar[1] self.error("No rcvar name found in rcvar") if name.nil? name = name.gsub!(/(.*)(_enable)?=(.*)/, '\1') self.error("rcvar name is empty") if name.nil? self.debug("rcvar name is #{name}") name 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
# File lib/puppet/provider/service/upstart.rb, line 265 def read_override_file if File.exists?(overscript) read_script_from(overscript) else "" end end
# File lib/puppet/provider/service/upstart.rb, line 336 def read_script_from(filename) File.open(filename) do |file| file.read end end
# File lib/puppet/provider/zone/solaris.rb, line 298 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 477 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 516 def recurse? self[:recurse] == true or self[:recurse] == :remote end
Recurse the target of the link.
# File lib/puppet/type/file.rb, line 521 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 540 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 552 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 children[meta.relative_path][:checksum] = :md5 if meta.ftype == "file" children[meta.relative_path].parameter(:source).metadata = meta end children end
# File lib/puppet/type/component.rb, line 56 def ref reference.to_s end
# File lib/puppet/type/component.rb, line 69 def refresh catalog.adjacent(self).each do |child| if child.respond_to?(:refresh) child.refresh child.log "triggering #{:refresh}" end end end
Remove any existing data. This is only used when dealing with links or directories.