class Object
Make translation methods (e.g. `_()` and `n_()`) available everywhere.
Constants
- AgeConvertors
- BLANK
- COMMENTED_START_ON
- COMMON
- CREATORS
mutually exclusive ways to create files
- DEFAULT_SECTION
- DEFAULT_SECTION_MARKER
- DPKG_QUERY_FORMAT_STRING
- DPKG_QUERY_PROVIDES_FORMAT_STRING
- DebianVersion
- ERROR_SUCCESS
- ERROR_SUCCESS_REBOOT_INITIATED
- ERROR_SUCCESS_REBOOT_REQUIRED
- FIELDS
- FIELDS_REGEX
- FIELDS_REGEX_WITH_PROVIDES
- GEM_VERSION
- GEM_VERSION_RANGE
- HEADER_LINE_REGEX
- INSTALLP_PACKAGE_REGEX
- MANUAL
- MULTIVERSION_SEPARATOR
- NEVRA_FIELDS
- NEVRA_FORMAT
- NEVRA_REGEX
- Namemap
- PACKAGE_LINE_REGEX
- PIP_VERSION
- PIP_VERSION_RANGE
- RPM_PACKAGE_REGEX
- RPM_VERSION
- RPM_VERSION_RANGE
- SEPARATOR
- SHA512_PBKDF2_AUTHENTICATION_AUTHORITY
- SOURCE_ONLY_CHECKSUMS
This is both “checksum types that can't be used with the content property” and “checksum types that are not digest based”
- SPECIALIZED
- START_ON
- STATE_CODE
- STATUSLINE
- VERSION_REGEX
- VersionRange
- WINDOWS_SYSTEM_SID_REGEXES
Public Class Methods
# File lib/puppet/type/file.rb 459 def self.[](path) 460 return nil unless path 461 super(path.gsub(/\/+/, '/').sub(/\/$/, '')) 462 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 63 def self.availlist 64 output = pkguti ["-a"] 65 66 output.split("\n").collect do |line| 67 next if line =~ /^common\s+package/ # header of package list 68 next if noise?(line) 69 70 if line =~ /\s*(\S+)\s+(\S+)\s+(.*)/ 71 { :alias => $1, :name => $2, :avail => $3 } 72 else 73 Puppet.warning _("Cannot match %{line}") % { line: line } 74 end 75 end.reject { |h| h.nil? } 76 end
Turn our blastwave listing into a bunch of hashes.
# File lib/puppet/provider/package/blastwave.rb 35 def self.blastlist(hash) 36 command = ["-c"] 37 38 command << hash[:justme] if hash[:justme] 39 40 output = Puppet::Util.withenv(:PAGER => "/usr/bin/cat") { pkgget command } 41 42 list = output.split("\n").collect do |line| 43 next if line =~ /^#/ 44 next if line =~ /^WARNING/ 45 next if line =~ /localrev\s+remoterev/ 46 47 blastsplit(line) 48 end.reject { |h| h.nil? } 49 50 if hash[:justme] 51 return list[0] 52 else 53 list.reject! { |h| 54 h[:ensure] == :absent 55 } 56 return list 57 end 58 59 end
Split the different lines into hashes.
# File lib/puppet/provider/package/blastwave.rb 62 def self.blastsplit(line) 63 if line =~ /\s*(\S+)\s+((\[Not installed\])|(\S+))\s+(\S+)/ 64 hash = {} 65 hash[:name] = $1 66 hash[:ensure] = if $2 == "[Not installed]" 67 :absent 68 else 69 $2 70 end 71 hash[:avail] = $5 72 73 hash[:avail] = hash[:ensure] if hash[:avail] == "SAME" 74 75 # Use the name method, so it works with subclasses. 76 hash[:provider] = self.name 77 78 return hash 79 else 80 Puppet.warning _("Cannot match %{line}") % { line: line } 81 return nil 82 end 83 end
# File lib/puppet/provider/package/pkgng.rb 24 def self.cached_version_list 25 @version_list ||= get_version_list 26 end
Search for all installed packages that have newer versions, given a combination of repositories to enable and disable.
@api private @param disablerepo [Array<String>] A list of repositories to disable for this query @param enablerepo [Array<String>] A list of repositories to enable for this query @param disableexcludes [Array<String>] A list of repository excludes to disable for this query @return [Hash<String, Array<Hash<String, String>>>] All packages that were
found with a list of found versions for each package.
# File lib/puppet/provider/package/yum.rb 109 def self.check_updates(disablerepo, enablerepo, disableexcludes) 110 args = [command(:cmd), 'check-update'] 111 args.concat(disablerepo.map { |repo| ["--disablerepo=#{repo}"] }.flatten) 112 args.concat(enablerepo.map { |repo| ["--enablerepo=#{repo}"] }.flatten) 113 args.concat(disableexcludes.map { |repo| ["--disableexcludes=#{repo}"] }.flatten) 114 115 output = Puppet::Util::Execution.execute(args, :failonfail => false, :combine => false) 116 117 updates = {} 118 if output.exitstatus == 100 119 updates = parse_updates(output) 120 elsif output.exitstatus == 0 121 self.debug "#{command(:cmd)} check-update exited with 0; no package updates available." 122 else 123 self.warning _("Could not check for updates, '%{cmd} check-update' exited with %{status}") % { cmd: command(:cmd), status: output.exitstatus } 124 end 125 updates 126 end
# File lib/puppet/provider/package/yum.rb 175 def self.clear 176 @latest_versions = nil 177 end
# File lib/puppet/provider/package/pip.rb 37 def self.cmd 38 if Puppet::Util::Platform.windows? 39 ["pip.exe"] 40 else 41 ["pip", "pip-python", "pip2", "pip-2"] 42 end 43 end
# File lib/puppet/provider/package/pip.rb 133 def self.compare_pip_versions(x, y) 134 begin 135 Puppet::Util::Package::Version::Pip.compare(x, y) 136 rescue PIP_VERSION::ValidationFailure => ex 137 Puppet.debug("Cannot compare #{x} and #{y}. #{ex.message} Falling through default comparison mechanism.") 138 Puppet::Util::Package.versioncmp(x, y) 139 end 140 end
This method will accept a binary plist (as a string) and convert it to a hash.
# File lib/puppet/provider/user/directoryservice.rb 193 def self.convert_binary_to_hash(plist_data) 194 Puppet.debug('Converting binary plist to hash') 195 Puppet::Util::Plist.parse_plist(plist_data) 196 end
This method will accept a hash and convert it to a binary plist (string value).
# File lib/puppet/provider/user/directoryservice.rb 187 def self.convert_hash_to_binary(plist_data) 188 Puppet.debug('Converting plist hash to binary') 189 Puppet::Util::Plist.dump_plist(plist_data, :binary) 190 end
# File lib/puppet/provider/package/dnfmodule.rb 24 def self.current_version 25 @current_version ||= dnf('--version').split.first 26 end
returns the daemon dir on this node
# File lib/puppet/provider/service/daemontools.rb 82 def self.daemondir 83 self.defpath 84 end
# File lib/puppet/provider/package/apt.rb 30 def self.defaultto_allow_virtual 31 false 32 end
# File lib/puppet/provider/service/bsd.rb 14 def self.defpath 15 superclass.defpath 16 end
removes all reports for a given host?
# File lib/puppet/reports/store.rb 47 def self.destroy(host) 48 validate_host(host) 49 50 dir = File.join(Puppet[:reportdir], host) 51 52 if Puppet::FileSystem.exist?(dir) 53 Dir.entries(dir).each do |file| 54 next if ['.','..'].include?(file) 55 file = File.join(dir, file) 56 Puppet::FileSystem.unlink(file) if File.file?(file) 57 end 58 Dir.rmdir(dir) 59 end 60 end
Performs a dpkgquery call with a pipe so that output can be processed inline in a passed block. @param args [Array<String>] any command line arguments to be appended to the command @param block expected to be passed on to execpipe @return whatever the block returns @see Puppet::Util::Execution.execpipe
@api private
# File lib/puppet/provider/package/dpkg.rb 20 def self.dpkgquery_piped(*args, &block) 21 cmd = args.unshift(command(:dpkgquery)) 22 Puppet::Util::Execution.execpipe(cmd, &block) 23 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 43 def self.ds_to_ns_attribute_map 44 { 45 'RecordName' => :name, 46 'PrimaryGroupID' => :gid, 47 'NFSHomeDirectory' => :home, 48 'UserShell' => :shell, 49 'UniqueID' => :uid, 50 'RealName' => :comment, 51 'Password' => :password, 52 'GeneratedUID' => :guid, 53 'IPAddress' => :ip_address, 54 'ENetAddress' => :en_address, 55 'GroupMembership' => :members, 56 } 57 end
# File lib/puppet/provider/package/portage.rb 291 def self.eix_install_versions_format 292 '{!first}{!last},{}{}{isstable}<version>{}' 293 end
# File lib/puppet/provider/package/portage.rb 287 def self.eix_installed_versions_format 288 '{!first},{}<version>' 289 end
# File lib/puppet/provider/package/portage.rb 295 def self.eix_limit 296 '0' 297 end
# File lib/puppet/provider/package/portage.rb 274 def self.eix_result_fields 275 # ensure:[3.4.5], version_available:[3.5.2], installed_slots:[2.7.12:2.7,3.4.5:3.4], installable_versions:[2.7.10-r1,2.7.12,3.4.3-r1,3.4.5,3.5.2] slot_versions_available:[2.7.12:2.7,3.4.5:3.4,3.5.2:3.5] 276 [:category, :name, :ensure, :version_available, :installed_slots, :installed_versions, :installable_versions, :slot_versions_available, :vendor, :description] 277 end
# File lib/puppet/provider/package/portage.rb 270 def self.eix_result_format 271 /^(\S+)\s+(\S+)\s+\[(\S*)\]\s+\[(\S*)\]\s+\[(\S*)\]\s+\[(\S*)\]\s+\[(\S*)\]\s+\[(\S*)\]\s+(\S+)\s+(.*)$/ 272 end
# File lib/puppet/provider/package/portage.rb 299 def self.eix_search_arguments 300 ['--nocolor', '--pure-packages', '--format', self.eix_search_format] 301 end
# File lib/puppet/provider/package/portage.rb 266 def self.eix_search_format 267 "'<category> <name> [<installedversions:LASTVERSION>] [<bestversion:LASTVERSION>] [<installedversions:LASTSLOTVERSIONS>] [<installedversions:INSTALLEDVERSIONS>] [<availableversions:STABLEVERSIONS>] [<bestslotversions:LASTSLOTVERSIONS>] <homepage> <description>\n'" 268 end
# File lib/puppet/provider/package/portage.rb 283 def self.eix_slot_versions_format 284 '{!first},{}<version>:<slot>' 285 end
# File lib/puppet/provider/package/portage.rb 279 def self.eix_version_format 280 '{last}<version>{}' 281 end
The value to pass to DNF as its error output level. DNF differs from Yum slightly with regards to error outputting.
@param None @return [String]
# File lib/puppet/provider/package/dnf.rb 46 def self.error_level 47 '1' 48 end
some init scripts are not safe to execute, e.g. we do not want to suddenly run /etc/init.d/reboot.sh status and reboot our system. The exclude list could be platform agnostic but I assume an invalid init script on system A will never be a valid init script on system B
# File lib/puppet/provider/service/init.rb 36 def self.excludes 37 excludes = [] 38 # these exclude list was found with grep -L '\/sbin\/runscript' /etc/init.d/* on gentoo 39 excludes += %w{functions.sh reboot.sh shutdown.sh} 40 # this exclude list is all from /sbin/service (5.x), but I did not exclude kudzu 41 excludes += %w{functions halt killall single linuxconf reboot boot} 42 # 'wait-for-state' and 'portmap-wait' are excluded from instances here 43 # because they take parameters that have unclear meaning. It looks like 44 # 'wait-for-state' is a generic waiter mainly used internally for other 45 # upstart services as a 'sleep until something happens' 46 # (http://lists.debian.org/debian-devel/2012/02/msg01139.html), while 47 # 'portmap-wait' is a specific instance of a waiter. There is an open 48 # launchpad bug 49 # (https://bugs.launchpad.net/ubuntu/+source/upstart/+bug/962047) that may 50 # eventually explain how to use the wait-for-state service or perhaps why 51 # it should remain excluded. When that bug is addressed this should be 52 # reexamined. 53 excludes += %w{wait-for-state portmap-wait} 54 # these excludes were found with grep -r -L start /etc/init.d 55 excludes += %w{rcS module-init-tools} 56 # Prevent puppet failing on unsafe scripts from Yocto Linux 57 if Facter.value(:osfamily) == "cisco-wrlinux" 58 excludes += %w{banner.sh bootmisc.sh checkroot.sh devpts.sh dmesg.sh 59 hostname.sh mountall.sh mountnfs.sh populate-volatile.sh 60 rmnologin.sh save-rtc.sh sendsigs sysfs.sh umountfs 61 umountnfs.sh} 62 end 63 # Prevent puppet failing to get status of the new service introduced 64 # by the fix for this (bug https://bugs.launchpad.net/ubuntu/+source/lightdm/+bug/982889) 65 # due to puppet's inability to deal with upstart services with instances. 66 excludes += %w{plymouth-ready} 67 # Prevent puppet failing to get status of these services, which need parameters 68 # passed in (see https://bugs.launchpad.net/ubuntu/+source/puppet/+bug/1276766). 69 excludes += %w{idmapd-mounting startpar-bridge} 70 # Prevent puppet failing to get status of these services, additional upstart 71 # service with instances 72 excludes += %w{cryptdisks-udev} 73 excludes += %w{statd-mounting} 74 excludes += %w{gssd-mounting} 75 excludes 76 end
CommandDefiner in provider.rb creates convenience execution methods that set failonfail, combine, and optionally, environment. And when a child provider defines its own command via commands() or has_command(), the provider-specific path is always returned by command(). But when the convenience execution method is invoked, the last convenience method to be defined is executed. This makes invoking those convenience execution methods unsuitable for inherited providers.
In this case, causing the puppet_gem provider to inherit the parent gem provider's convenience gemcmd() methods, with the wrong path.
# File lib/puppet/provider/package/gem.rb 72 def self.execute_gem_command(command, command_options, custom_environment = {}) 73 validate_command(command) 74 cmd = [command] << command_options 75 76 custom_environment = {'HOME'=>Puppet::Util.get_env('HOME')}.merge(custom_environment) 77 78 if Puppet::Util::Platform.windows? 79 custom_environment[:PATH] = windows_path_without_puppet_bin 80 end 81 82 execute(cmd, {:failonfail => true, :combine => true, :custom_environment => custom_environment}) 83 end
The puppetserver gem cli command is very slow, since it starts a JVM.
Instead, for the list subcommand (which is executed with every puppet run), use the rubygems library from puppet ruby: setting GEM_HOME and GEM_PATH to the default values, or the values in the puppetserver configuration file.
The rubygems library cannot access java platform gems, for example: json (1.8.3 java) but java platform gems should not be managed by this (or any) provider.
# File lib/puppet/provider/package/puppetserver_gem.rb 140 def self.execute_rubygems_list_command(gem_regex) 141 puppetserver_default_gem_home = '/opt/puppetlabs/server/data/puppetserver/jruby-gems' 142 puppetserver_default_vendored_jruby_gems = '/opt/puppetlabs/server/data/puppetserver/vendored-jruby-gems' 143 puppet_default_vendor_gems = '/opt/puppetlabs/puppet/lib/ruby/vendor_gems' 144 puppetserver_default_gem_path = [puppetserver_default_gem_home, puppetserver_default_vendored_jruby_gems, puppet_default_vendor_gems].join(':') 145 146 pe_puppetserver_conf_file = '/etc/puppetlabs/puppetserver/conf.d/pe-puppet-server.conf' 147 os_puppetserver_conf_file = '/etc/puppetlabs/puppetserver/puppetserver.conf' 148 puppetserver_conf_file = Facter.value(:pe_server_version) ? pe_puppetserver_conf_file : os_puppetserver_conf_file 149 puppetserver_conf = Hocon.load(puppetserver_conf_file) 150 151 gem_env = {} 152 if puppetserver_conf.empty? || puppetserver_conf.key?('jruby-puppet') == false 153 gem_env['GEM_HOME'] = puppetserver_default_gem_home 154 gem_env['GEM_PATH'] = puppetserver_default_gem_path 155 else 156 gem_env['GEM_HOME'] = puppetserver_conf['jruby-puppet'].key?('gem-home') ? puppetserver_conf['jruby-puppet']['gem-home'] : puppetserver_default_gem_home 157 gem_env['GEM_PATH'] = puppetserver_conf['jruby-puppet'].key?('gem-path') ? puppetserver_conf['jruby-puppet']['gem-path'].join(':') : puppetserver_default_gem_path 158 end 159 gem_env['GEM_SPEC_CACHE'] = "/tmp/#{$$}" 160 Gem.paths = gem_env 161 162 sio_inn = StringIO.new 163 sio_out = StringIO.new 164 sio_err = StringIO.new 165 stream_ui = Gem::StreamUI.new(sio_inn, sio_out, sio_err, false) 166 gem_list_cmd = Gem::Commands::ListCommand.new 167 gem_list_cmd.options[:domain] = :local 168 gem_list_cmd.options[:args] = [gem_regex] if gem_regex 169 gem_list_cmd.ui = stream_ui 170 gem_list_cmd.execute 171 172 # There is no method exclude default gems from the local gem list, 173 # for example: psych (default: 2.2.2) 174 # but default gems should not be managed by this (or any) provider. 175 gem_list = sio_out.string.lines.reject { |gem| gem =~ / \(default\: / } 176 gem_list.join("\n") 177 ensure 178 Gem.clear_paths 179 end
# File lib/puppet/provider/user/aix.rb 64 def expires_to_expiry(provider, expires) 65 return :absent if expires == '0' 66 67 unless (match_obj = /\A(\d\d)(\d\d)(\d\d)(\d\d)(\d\d)\z/.match(expires)) 68 #TRANSLATORS 'AIX' is the name of an operating system and should not be translated 69 Puppet.warning(_("Could not convert AIX expires date '%{expires}' on %{class_name}[%{resource_name}]") % { expires: expires, class_name: provider.resource.class.name, resource_name: provider.resource.name }) 70 return :absent 71 end 72 73 month, day, year = match_obj[1], match_obj[2], match_obj[-1] 74 return "20#{year}-#{month}-#{day}" 75 end
# File lib/puppet/provider/user/aix.rb 57 def expiry_to_expires(expiry) 58 return '0' if expiry == "0000-00-00" || expiry.to_sym == :absent 59 60 DateTime.parse(expiry, "%Y-%m-%d %H:%M") 61 .strftime("%m%d%H%M%y") 62 end
# File lib/puppet/provider/package/blastwave.rb 15 def self.extended(mod) 16 unless command(:pkgget) != "pkg-get" 17 raise Puppet::Error, 18 _("The pkg-get command is missing; blastwave packaging unavailable") 19 end 20 21 unless Puppet::FileSystem.exist?("/var/pkg-get/admin") 22 Puppet.notice _("It is highly recommended you create '/var/pkg-get/admin'.") 23 Puppet.notice _("See /var/pkg-get/admin-fullauto") 24 end 25 end
Used by the AIX user provider. Returns a hash of:
{ :name => <group_name>, :gid => <gid> }
that matches the group, which can either be the group name or the gid. Takes an optional set of ia_module_args
# File lib/puppet/provider/group/aix.rb 32 def find(group, ia_module_args = []) 33 groups = list_all(ia_module_args) 34 35 id_property = mappings[:puppet_property][:id] 36 37 if group.is_a?(String) 38 # Find by name 39 group_hash = groups.find { |cur_group| cur_group[:name] == group } 40 else 41 # Find by gid 42 group_hash = groups.find do |cur_group| 43 id_property.convert_attribute_value(cur_group[:id]) == group 44 end 45 end 46 47 unless group_hash 48 raise ArgumentError, _("No AIX group exists with a group name or gid of %{group}!") % { group: group } 49 end 50 51 # Convert :id => :gid 52 id = group_hash.delete(:id) 53 group_hash[:gid] = id_property.convert_attribute_value(id) 54 55 group_hash 56 end
# File lib/puppet/provider/package/gem.rb 101 def self.gemlist(options) 102 command_options = ["list"] 103 104 if options[:local] 105 command_options << "--local" 106 else 107 command_options << "--remote" 108 end 109 if options[:source] 110 command_options << "--source" << options[:source] 111 end 112 name = options[:justme] 113 if name 114 command_options << '\A' + name + '\z' 115 end 116 117 begin 118 list = execute_gem_command(options[:command], command_options).lines. 119 map {|set| gemsplit(set) }. 120 reject {|x| x.nil? } 121 rescue Puppet::ExecutionFailure => detail 122 raise Puppet::Error, _("Could not list gems: %{detail}") % { detail: detail }, detail.backtrace 123 end 124 125 if options[:justme] 126 return list.shift 127 else 128 return list 129 end 130 end
# File lib/puppet/provider/package/gem.rb 132 def self.gemsplit(desc) 133 # `gem list` when output console has a line like: 134 # *** LOCAL GEMS *** 135 # but when it's not to the console that line 136 # and all blank lines are stripped 137 # so we don't need to check for them 138 139 if desc =~ /^(\S+)\s+\((.+)\)/ 140 gem_name = $1 141 versions = $2.sub('default: ', '').split(/,\s*/) 142 { 143 :name => gem_name, 144 :ensure => versions.map{|v| v.split[0]}, 145 :provider => name 146 } 147 else 148 Puppet.warning _("Could not match %{desc}") % { desc: desc } unless desc.chomp.empty? 149 nil 150 end 151 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 102 def self.generate_attribute_hash(input_hash) 103 attribute_hash = {} 104 input_hash.each_key do |key| 105 ds_attribute = key.sub("dsAttrTypeStandard:", "") 106 next unless ds_to_ns_attribute_map.keys.include?(ds_attribute) 107 ds_value = input_hash[key] 108 case ds_to_ns_attribute_map[ds_attribute] 109 when :gid, :uid 110 # OS X stores objects like uid/gid as strings. 111 # Try casting to an integer for these cases to be 112 # consistent with the other providers and the group type 113 # validation 114 begin 115 ds_value = Integer(ds_value[0]) 116 rescue ArgumentError 117 ds_value = ds_value[0] 118 end 119 else ds_value = ds_value[0] 120 end 121 attribute_hash[ds_to_ns_attribute_map[ds_attribute]] = ds_value 122 end 123 attribute_hash[:ensure] = :present 124 attribute_hash[:provider] = :directoryservice 125 attribute_hash[:shadowhashdata] = input_hash['dsAttrTypeNative:ShadowHashData'] 126 127 ############## 128 # Get Groups # 129 ############## 130 groups_array = [] 131 get_list_of_groups.each do |group| 132 if group["dsAttrTypeStandard:GroupMembership"] and group["dsAttrTypeStandard:GroupMembership"].include?(attribute_hash[:name]) 133 groups_array << group["dsAttrTypeStandard:RecordName"][0] 134 end 135 136 if group["dsAttrTypeStandard:GroupMembers"] and group["dsAttrTypeStandard:GroupMembers"].include?(attribute_hash[:guid]) 137 groups_array << group["dsAttrTypeStandard:RecordName"][0] 138 end 139 end 140 attribute_hash[:groups] = groups_array.uniq.sort.join(',') 141 142 ################################ 143 # Get Password/Salt/Iterations # 144 ################################ 145 if attribute_hash[:shadowhashdata].nil? or attribute_hash[:shadowhashdata].empty? 146 attribute_hash[:password] = '*' 147 else 148 embedded_binary_plist = get_embedded_binary_plist(attribute_hash[:shadowhashdata]) 149 if embedded_binary_plist['SALTED-SHA512-PBKDF2'] 150 attribute_hash[:password] = get_salted_sha512_pbkdf2('entropy', embedded_binary_plist) 151 attribute_hash[:salt] = get_salted_sha512_pbkdf2('salt', embedded_binary_plist) 152 attribute_hash[:iterations] = get_salted_sha512_pbkdf2('iterations', embedded_binary_plist) 153 elsif embedded_binary_plist['SALTED-SHA512'] 154 attribute_hash[:password] = get_salted_sha512(embedded_binary_plist) 155 end 156 end 157 158 attribute_hash 159 end
Return an array of hashes containing information about every user on the system.
# File lib/puppet/provider/user/directoryservice.rb 94 def self.get_all_users 95 Puppet::Util::Plist.parse_plist(dscl '-plist', '.', 'readall', '/Users') 96 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 174 def self.get_attribute_from_dscl(path, username, keyname) 175 Puppet::Util::Plist.parse_plist(dscl '-plist', '.', 'read', "/#{path}/#{username}", keyname) 176 end
The plist embedded in the ShadowHashData key is a binary plist. The 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 181 def self.get_embedded_binary_plist(shadow_hash_data) 182 embedded_binary_plist = Array(shadow_hash_data[0].delete(' ')).pack('H*') 183 convert_binary_to_hash(embedded_binary_plist) 184 end
returns a hash of group => version of installed groups
# File lib/puppet/provider/package/pacman.rb 96 def self.get_installed_groups(installed_packages, filter = nil) 97 groups = {} 98 begin 99 # Build a hash of group name => list of packages 100 command = [command(:pacman), "-Sgg"] 101 command << filter if filter 102 execpipe(command) do |pipe| 103 pipe.each_line do |line| 104 name, package = line.split 105 packages = (groups[name] ||= []) 106 packages << package 107 end 108 end 109 110 # Remove any group that doesn't have all its packages installed 111 groups.delete_if do |_, packages| 112 !packages.all? { |package| installed_packages[package] } 113 end 114 115 # Replace the list of packages with a version string consisting of packages that make up the group 116 groups.each do |name, packages| 117 groups[name] = packages.sort.map {|package| "#{package} #{installed_packages[package]}"}.join ', ' 118 end 119 rescue Puppet::ExecutionFailure 120 # pacman returns an expected non-zero exit code when the filter name is not a group 121 raise unless filter 122 end 123 groups 124 end
returns a hash package => version of installed packages
# File lib/puppet/provider/package/pacman.rb 74 def self.get_installed_packages 75 begin 76 packages = {} 77 execpipe([command(:pacman), "-Q"]) do |pipe| 78 # pacman -Q output is 'packagename version-rel' 79 regex = %r{^(\S+)\s(\S+)} 80 pipe.each_line do |line| 81 match = regex.match(line) 82 if match 83 packages[match.captures[0]] = match.captures[1] 84 else 85 warning(_("Failed to match line '%{line}'") % { line: line }) 86 end 87 end 88 end 89 packages 90 rescue Puppet::ExecutionFailure 91 fail(_("Error getting installed packages")) 92 end 93 end
# File lib/puppet/provider/package/pkgng.rb 32 def self.get_latest_version(origin) 33 latest_version = cached_version_list.lines.find { |l| l =~ /^#{origin} / } 34 if latest_version 35 _name, compare, status = latest_version.chomp.split(' ', 3) 36 if ['!', '?'].include?(compare) 37 return nil 38 end 39 latest_version = status.split(' ').last.split(')').first 40 return latest_version 41 end 42 nil 43 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 167 def self.get_list_of_groups 168 @groups ||= Puppet::Util::Plist.parse_plist(dscl '-plist', '.', 'readall', '/Groups') 169 end
Gets the current Darwin version, example 10.6 returns 9 and 10.10 returns 14 See en.wikipedia.org/wiki/Darwin_(operating_system)#Release_history for more information.
@api private
# File lib/puppet/provider/service/launchd.rb 72 def self.get_os_version 73 @os_version ||= Facter.value(:operatingsystemmajrelease).to_i 74 end
# File lib/puppet/provider/package/pkgng.rb 16 def self.get_query 17 pkg(['query', '-a', '%n %v %o']) 18 end
# File lib/puppet/provider/package/pkgng.rb 20 def self.get_resource_info(name) 21 pkg(['query', '%n %v %o', name]) 22 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 200 def self.get_salted_sha512(embedded_binary_plist) 201 embedded_binary_plist['SALTED-SHA512'].unpack("H*")[0] 202 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 208 def self.get_salted_sha512_pbkdf2(field, embedded_binary_plist) 209 case field 210 when 'salt', 'entropy' 211 embedded_binary_plist['SALTED-SHA512-PBKDF2'][field].unpack('H*').first 212 when 'iterations' 213 Integer(embedded_binary_plist['SALTED-SHA512-PBKDF2'][field]) 214 else 215 raise Puppet::Error, 'Puppet has tried to read an incorrect value from the ' + 216 "SALTED-SHA512-PBKDF2 hash. Acceptable fields are 'salt', " + 217 "'entropy', or 'iterations'." 218 end 219 end
# File lib/puppet/provider/service/init.rb 83 def self.get_services(defpath, exclude = self.excludes) 84 defpath = [defpath] unless defpath.is_a? Array 85 instances = [] 86 defpath.each do |path| 87 unless FileTest.directory?(path) 88 Puppet.debug "Service path #{path} does not exist" 89 next 90 end 91 92 check = [:ensure] 93 94 check << :enable if public_method_defined? :enabled? 95 96 Dir.entries(path).each do |name| 97 fullpath = File.join(path, name) 98 next if name =~ /^\./ 99 next if exclude.include? name 100 next if not FileTest.executable?(fullpath) 101 next if not is_init?(fullpath) 102 instances << new(:name => name, :path => path, :hasstatus => true) 103 end 104 end 105 instances 106 end
# File lib/puppet/provider/package/portage.rb 155 def self.get_sets 156 @sets ||= begin 157 @sets = emerge(*(['--list-sets'])) 158 end 159 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 223 def self.get_sha1(guid) 224 password_hash = nil 225 password_hash_file = "#{password_hash_dir}/#{guid}" 226 if Puppet::FileSystem.exist?(password_hash_file) and File.file?(password_hash_file) 227 raise Puppet::Error, "Could not read password hash file at #{password_hash_file}" if not File.readable?(password_hash_file) 228 f = File.new(password_hash_file) 229 password_hash = f.read 230 f.close 231 end 232 password_hash 233 end
# File lib/puppet/provider/package/pkgng.rb 28 def self.get_version_list 29 @version_list = pkg(['version', '-voRL=']) 30 end
Define some Puppet
Property => AIX Attribute (and vice versa) conversion functions here.
# File lib/puppet/provider/user/aix.rb 45 def gid_to_pgrp(provider, gid) 46 group = group_provider.find(gid, provider.ia_module_args) 47 48 group[:name] 49 end
Checks if a given name is a group
# File lib/puppet/provider/package/pacman.rb 28 def self.group?(name) 29 begin 30 !pacman("-Sg", name).empty? 31 rescue Puppet::ExecutionFailure 32 # pacman returns an expected non-zero exit code when the name is not a group 33 false 34 end 35 end
# File lib/puppet/provider/user/aix.rb 38 def group_provider 39 @group_provider ||= Puppet::Type.type(:group).provider(:aix) 40 end
We do not directly use the groups attribute value because that will always include the primary group, even if our user is not one of its members. Instead, we retrieve our property value by parsing the etc/group file, which matches what we do on our other POSIX platforms like Linux and Solaris.
See www.ibm.com/support/knowledgecenter/en/ssw_aix_72/com.ibm.aix.files/group_security.htm
# File lib/puppet/provider/user/aix.rb 95 def groups_attribute_to_property(provider, _groups) 96 Puppet::Util::POSIX.groups_of(provider.resource[:name]).join(',') 97 end
We do some validation before-hand to ensure the value's an Array, a String, etc. in the property. This routine does a final check to ensure our value doesn't have whitespace before we convert it to an attribute.
# File lib/puppet/provider/user/aix.rb 81 def groups_property_to_attribute(groups) 82 if groups =~ /\s/ 83 raise ArgumentError, _("Invalid value %{groups}: Groups must be comma separated!") % { groups: groups } 84 end 85 86 groups 87 end
# File lib/puppet/provider/service/upstart.rb 33 def self.has_initctl? 34 # Puppet::Util::Execution.execute does not currently work on jRuby. 35 # Unfortunately, since this confine is invoked whenever we check for 36 # provider suitability and since provider suitability is still checked 37 # on the master, this confine will still be invoked on the master. Thus 38 # to avoid raising an exception, we do an early return if we're running 39 # on jRuby. 40 return false if Puppet::Util::Platform.jruby? 41 42 begin 43 initctl('version', '--quiet') 44 true 45 rescue 46 false 47 end 48 end
# File lib/puppet/provider/package/macports.rb 39 def self.hash_from_line(line, regex, fields) 40 hash = {} 41 match = regex.match(line) 42 if match 43 fields.zip(match.captures) { |field, value| 44 hash[field] = value 45 } 46 hash[:provider] = self.name 47 return hash 48 end 49 nil 50 end
# File lib/puppet/provider/package/pkgutil.rb 16 def self.healthcheck() 17 unless Puppet::FileSystem.exist?("/var/opt/csw/pkgutil/admin") 18 Puppet.notice _("It is highly recommended you create '/var/opt/csw/pkgutil/admin'.") 19 Puppet.notice _("See /var/opt/csw/pkgutil") 20 end 21 22 correct_wgetopts = false 23 [ "/opt/csw/etc/pkgutil.conf", "/etc/opt/csw/pkgutil.conf" ].each do |confpath| 24 File.open(confpath) do |conf| 25 conf.each_line {|line| correct_wgetopts = true if line =~ /^\s*wgetopts\s*=.*(-nv|-q|--no-verbose|--quiet)/ } 26 end 27 end 28 if ! correct_wgetopts 29 Puppet.notice _("It is highly recommended that you set 'wgetopts=-nv' in your pkgutil.conf.") 30 end 31 end
The IFO flag field is just what it names, the first field can have either 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 don't know what we are doing and exit with out doing more damage.
# File lib/puppet/provider/package/pkg.rb 45 def self.ifo_flag(flags) 46 ( 47 case flags[0..0] 48 when 'i' 49 {:status => 'installed'} 50 when '-' 51 {:status => 'known'} 52 else 53 raise ArgumentError, _('Unknown format %{resource_name}: %{full_flags}[%{bad_flag}]') % 54 { resource_name: self.name, full_flags: flags, bad_flag: flags[0..0] } 55 end 56 ).merge( 57 case flags[1..1] 58 when 'f' 59 {:mark => :hold} 60 when '-' 61 {} 62 else 63 raise ArgumentError, _('Unknown format %{resource_name}: %{full_flags}[%{bad_flag}]') % 64 { resource_name: self.name, full_flags: flags, bad_flag: flags[1..1] } 65 end 66 ) 67 end
# File lib/puppet/provider/package/appdmg.rb 44 def self.installapp(source, name, orig_source) 45 appname = File.basename(source); 46 ditto "--rsrc", source, "/Applications/#{appname}" 47 Puppet::FileSystem.open("/var/db/.puppet_appdmg_installed_#{name}", nil, "w:UTF-8") do |t| 48 t.print "name: '#{name}'\n" 49 t.print "source: '#{orig_source}'\n" 50 end 51 end
# File lib/puppet/provider/package/pkgdmg.rb 62 def self.installpkg(source, name, orig_source) 63 installer "-pkg", source, "-target", "/" 64 # Non-zero exit status will throw an exception. 65 Puppet::FileSystem.open("/var/db/.puppet_pkgdmg_installed_#{name}", nil, "w:UTF-8") do |t| 66 t.print "name: '#{name}'\n" 67 t.print "source: '#{orig_source}'\n" 68 end 69 end
# File lib/puppet/provider/package/appdmg.rb 53 def self.installpkgdmg(source, name) 54 require 'open-uri' 55 cached_source = source 56 tmpdir = Dir.mktmpdir 57 begin 58 if %r{\A[A-Za-z][A-Za-z0-9+\-\.]*://} =~ cached_source 59 cached_source = File.join(tmpdir, name) 60 begin 61 curl "-o", cached_source, "-C", "-", "-L", "-s", "--url", source 62 Puppet.debug "Success: curl transferred [#{name}]" 63 rescue Puppet::ExecutionFailure 64 Puppet.debug "curl did not transfer [#{name}]. Falling back to slower open-uri transfer methods." 65 cached_source = source 66 end 67 end 68 69 open(cached_source) do |dmg| 70 xml_str = hdiutil "mount", "-plist", "-nobrowse", "-readonly", "-mountrandom", "/tmp", dmg.path 71 ptable = Puppet::Util::Plist::parse_plist(xml_str) 72 # JJM Filter out all mount-paths into a single array, discard the rest. 73 mounts = ptable['system-entities'].collect { |entity| 74 entity['mount-point'] 75 }.select { |mountloc|; mountloc } 76 begin 77 found_app = false 78 mounts.each do |fspath| 79 Dir.entries(fspath).select { |f| 80 f =~ /\.app$/i 81 }.each do |pkg| 82 found_app = true 83 installapp("#{fspath}/#{pkg}", name, source) 84 end 85 end 86 Puppet.debug "Unable to find .app in .appdmg. #{name} will not be installed." if !found_app 87 ensure 88 hdiutil "eject", mounts[0] 89 end 90 end 91 ensure 92 FileUtils.remove_entry_secure(tmpdir, true) 93 end 94 end
# File lib/puppet/provider/package/apple.rb 24 def self.instance_by_name 25 Dir.entries("/Library/Receipts").find_all { |f| 26 f =~ /\.pkg$/ 27 }.collect { |f| 28 name = f.sub(/\.pkg/, '') 29 yield name if block_given? 30 31 name 32 } 33 end
# File lib/puppet/provider/group/windows_adsi.rb 110 def self.instances 111 Puppet::Util::Windows::ADSI::Group.map { |g| new(:ensure => :present, :name => g.name) } 112 end
JJM We store a cookie for each installed .app.dmg in /var/db
# File lib/puppet/provider/package/appdmg.rb 28 def self.instances_by_name 29 Dir.entries("/var/db").find_all { |f| 30 f =~ /^\.puppet_appdmg_installed_/ 31 }.collect do |f| 32 name = f.sub(/^\.puppet_appdmg_installed_/, '') 33 yield name if block_given? 34 name 35 end 36 end
# File lib/puppet/provider/service/init.rb 189 def self.is_init?(script = initscript) 190 file = Puppet::FileSystem.pathname(script) 191 !Puppet::FileSystem.symlink?(file) || Puppet::FileSystem.readlink(file) != "/lib/init/upstart-job" 192 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 180 def self.job_list 181 @job_list = Hash.new 182 begin 183 output = launchctl :list 184 raise Puppet::Error.new("launchctl list failed to return any data.") if output.nil? 185 output.split("\n").each do |line| 186 @job_list[line.split(/\s/).last] = :running 187 end 188 rescue Puppet::ExecutionFailure 189 raise Puppet::Error.new("Unable to determine status of #{resource[:name]}", $!) 190 end 191 @job_list 192 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 157 def self.jobsearch(label=nil) 158 by_label = make_label_to_path_map 159 160 if label 161 if by_label.has_key? label 162 return { label => by_label[label] } 163 else 164 # try refreshing the map, in case a plist has been added in the interim 165 by_label = make_label_to_path_map(true) 166 if by_label.has_key? label 167 return { label => by_label[label] } 168 else 169 raise Puppet::Error, "Unable to find launchd plist for job: #{label}" 170 end 171 end 172 else 173 # caller wants the whole map 174 by_label 175 end 176 end
Retrieve the latest package version information for a given package name and combination of repos to enable and disable.
@note If multiple package versions are defined (such as in the case where a
package is built for multiple architectures), the first package found will be used.
@api private @param package [String] The name of the package to query @param disablerepo [Array<String>] A list of repositories to disable for this query @param enablerepo [Array<String>] A list of repositories to enable for this query @param disableexcludes [Array<String>] A list of repository excludes to disable for this query @return [Hash<Symbol, String>]
# File lib/puppet/provider/package/yum.rb 86 def self.latest_package_version(package, disablerepo, enablerepo, disableexcludes) 87 88 key = [disablerepo, enablerepo, disableexcludes] 89 90 @latest_versions ||= {} 91 if @latest_versions[key].nil? 92 @latest_versions[key] = check_updates(disablerepo, enablerepo, disableexcludes) 93 end 94 95 if @latest_versions[key][package] 96 @latest_versions[key][package].first 97 end 98 end
Defines the path to the overrides plist file where service enabling behavior is defined in 10.6 and greater.
With the rewrite of launchd in 10.10+, this moves and slightly changes format.
@api private
# File lib/puppet/provider/service/launchd.rb 82 def self.launchd_overrides 83 if self.get_os_version < 14 84 "/var/db/launchd.db/com.apple.launchd/overrides.plist" 85 else 86 "/var/db/com.apple.xpc.launchd/disabled.plist" 87 end 88 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 58 def self.launchd_paths 59 [ 60 "/Library/LaunchAgents", 61 "/Library/LaunchDaemons", 62 "/System/Library/LaunchAgents", 63 "/System/Library/LaunchDaemons" 64 ] 65 end
# File lib/puppet/provider/package/zypper.rb 30 def self.list_updates 31 output = zypper 'list-updates' 32 33 avail_updates = {} 34 35 # split up columns 36 output.lines.each do |line| 37 pkg_ver = line.split(/\s*\|\s*/) 38 # ignore zypper headers 39 next unless pkg_ver[0] == 'v' 40 avail_updates[pkg_ver[2]] = pkg_ver[4] 41 end 42 43 avail_updates 44 end
# File lib/puppet/provider/package/freebsd.rb 14 def self.listcmd 15 command(:pkginfo) 16 end
Get a hash of all launchd plists, keyed by label. This value is cached, but the cache will be refreshed if refresh is true.
@api private
# File lib/puppet/provider/service/launchd.rb 133 def self.make_label_to_path_map(refresh=false) 134 return @label_to_path_map if @label_to_path_map and not refresh 135 @label_to_path_map = {} 136 launchd_paths.each do |path| 137 return_globbed_list_of_file_paths(path).each do |filepath| 138 Puppet.debug("Reading launchd plist #{filepath}") 139 job = read_plist(filepath) 140 next if job.nil? 141 if job.respond_to?(:key) && job.key?("Label") 142 @label_to_path_map[job["Label"]] = filepath 143 else 144 #TRANSLATORS 'plist' and label' should not be translated 145 Puppet.debug(_("The %{file} plist does not contain a 'label' key; Puppet is skipping it") % { file: filepath }) 146 next 147 end 148 end 149 end 150 @label_to_path_map 151 end
# File lib/puppet/util/log/destinations.rb 49 def self.match?(obj) 50 obj.is_a?(String) && Puppet::Util.absolute_path?(obj) 51 end
Define some Puppet
Property => AIX Attribute (and vice versa) conversion functions here. This is so we can unit test them.
# File lib/puppet/provider/group/aix.rb 61 def members_to_users(provider, members) 62 members = members.split(',') if members.is_a?(String) 63 unless provider.resource[:auth_membership] 64 current_members = provider.members 65 current_members = [] if current_members == :absent 66 members = (members + current_members).uniq 67 end 68 69 members.join(',') 70 end
Convert a group name to an id.
# File lib/puppet/provider/group/ldap.rb 40 def self.name2id(group) 41 result = manager.search("cn=#{group}") 42 return nil unless result and result.length > 0 43 44 # Only use the first result. 45 group = result[0] 46 group[:gid][0] 47 end
# File lib/puppet/provider/package/sun.rb 32 def self.namemap(hash) 33 self::Namemap.keys.inject({}) do |hsh,k| 34 hsh.merge(self::Namemap[k] => hash[k]) 35 end 36 end
@param line [String] one line of rpm package query information @return [Hash] of NEVRA_FIELDS
strings parsed from package info or an empty hash if we failed to parse @api private
# File lib/puppet/provider/package/rpm.rb 201 def self.nevra_to_hash(line) 202 line.strip! 203 hash = {} 204 205 match = self::NEVRA_REGEX.match(line) 206 if match 207 self::NEVRA_FIELDS.zip(match.captures) { |f, v| hash[f] = v } 208 hash[:provider] = self.name 209 hash[:ensure] = "#{hash[:version]}-#{hash[:release]}" 210 hash[:ensure].prepend("#{hash[:epoch]}:") if hash[:epoch] != '0' 211 else 212 Puppet.debug("Failed to match rpm line #{line}") 213 end 214 215 return hash 216 end
@param line [String] multiple lines of rpm package query information @return list of [Hash] of NEVRA_FIELDS
strings parsed from package info or an empty list if we failed to parse @api private
# File lib/puppet/provider/package/rpm.rb 222 def self.nevra_to_multiversion_hash(multiline) 223 list = [] 224 multiversion_hash = {} 225 multiline.each_line do |line| 226 hash = self.nevra_to_hash(line) 227 if !hash.empty? 228 if multiversion_hash.empty? 229 multiversion_hash = hash.dup 230 next 231 end 232 233 if multiversion_hash[:name] != hash[:name] 234 list << multiversion_hash 235 multiversion_hash = hash.dup 236 next 237 end 238 239 if !multiversion_hash[:ensure].include?(hash[:ensure]) 240 multiversion_hash[:ensure].concat("#{self::MULTIVERSION_SEPARATOR}#{hash[:ensure]}") 241 end 242 end 243 end 244 list << multiversion_hash if multiversion_hash 245 if list.size == 1 246 return list[0] 247 end 248 return list 249 end
# File lib/puppet/functions/match.rb 48 def initialize(closure_scope, loader) 49 super 50 51 # Make this visitor shared among all instantiations of this function since it is faster. 52 # This can be used because it is not possible to replace 53 # a puppet runtime (where this function is) without a reboot. If you model a function in a module after 54 # this class, use a regular instance variable instead to enable reloading of the module without reboot 55 # 56 @@match_visitor ||= Puppet::Pops::Visitor.new(self, "match", 1, 1) 57 end
rpm < 4.0.2 does not support –nodigest
# File lib/puppet/provider/package/rpm.rb 54 def self.nodigest 55 '--nodigest' unless Puppet::Util::Package.versioncmp(current_version, '4.0.2') < 0 56 end
Identify common types of pkgutil noise as it downloads catalogs etc
# File lib/puppet/provider/package/pkgutil.rb 115 def self.noise?(line) 116 true if line =~ /^#/ 117 true if line =~ /^Checking integrity / # use_gpg 118 true if line =~ /^gpg: / # gpg verification 119 true if line =~ /^=+> / # catalog fetch 120 true if line =~ /\d+:\d+:\d+ URL:/ # wget without -q 121 false 122 end
rpm < 4.1 does not support –nosignature
# File lib/puppet/provider/package/rpm.rb 49 def self.nosignature 50 '--nosignature' unless Puppet::Util::Package.versioncmp(current_version, '4.1') < 0 51 end
# File lib/puppet/provider/user/directoryservice.rb 59 def self.ns_to_ds_attribute_map 60 @ns_to_ds_attribute_map ||= ds_to_ns_attribute_map.invert 61 end
Parse lines of output from `pip freeze`, which are structured as: package==version or package===version
# File lib/puppet/provider/package/pip.rb 102 def self.parse(line) 103 if line.chomp =~ /^([^=]+)===?([^=]+)$/ 104 {:ensure => $2, :name => $1, :provider => name} 105 end 106 end
# File lib/puppet/provider/package/macports.rb 33 def self.parse_info_query_line(line) 34 regex = /(\S+)\s+(\S+)/ 35 fields = [:version, :revision] 36 hash_from_line(line, regex, fields) 37 end
# File lib/puppet/provider/package/macports.rb 27 def self.parse_installed_query_line(line) 28 regex = /(\S+)\s+@(\S+)_(\d+).*\(active\)/ 29 fields = [:name, :ensure, :revision] 30 hash_from_line(line, regex, fields) 31 end
@param line [String] one line of dpkg-query output @return [Hash,nil] a hash of FIELDS
or nil if we failed to match @api private
# File lib/puppet/provider/package/dpkg.rb 59 def self.parse_line(line, regex=self::FIELDS_REGEX) 60 hash = nil 61 62 match = regex.match(line) 63 if match 64 hash = {} 65 66 self::FIELDS.zip(match.captures) do |field,value| 67 hash[field] = value 68 end 69 70 hash[:provider] = self.name 71 72 if hash[:status] == 'not-installed' 73 hash[:ensure] = :purged 74 elsif ['config-files', 'half-installed', 'unpacked', 'half-configured'].include?(hash[:status]) 75 hash[:ensure] = :absent 76 end 77 hash[:mark] = hash[:desired] == 'hold' ? :hold : :none 78 else 79 Puppet.debug("Failed to match dpkg-query line #{line.inspect}") 80 end 81 82 return hash 83 end
# File lib/puppet/provider/package/pkgng.rb 45 def self.parse_pkg_query_line(line) 46 name, version, origin = line.chomp.split(' ', 3) 47 latest_version = get_latest_version(origin) || version 48 49 { 50 :ensure => version, 51 :name => name, 52 :provider => self.name, 53 :origin => origin, 54 :version => version, 55 :latest => latest_version 56 } 57 end
# File lib/puppet/provider/package/pkgin.rb 12 def self.parse_pkgin_line(package) 13 14 # e.g. 15 # vim-7.2.446;Vim editor (vi clone) without GUI 16 match, name, version, status = *package.match(/([^\s;]+)-([^\s;]+)[;\s](=|>|<)?.+$/) 17 if match 18 { 19 :name => name, 20 :status => status, 21 :ensure => version 22 } 23 end 24 end
# File lib/puppet/provider/package/sun.rb 38 def self.parse_pkginfo(out) 39 # collect all the lines with : in them, and separate them out by ^$ 40 pkgs = [] 41 pkg = {} 42 out.each_line do |line| 43 case line.chomp 44 when /^\s*$/ 45 pkgs << pkg unless pkg.empty? 46 pkg = {} 47 when /^\s*([^:]+):\s+(.+)$/ 48 pkg[$1] = $2 49 end 50 end 51 pkgs << pkg unless pkg.empty? 52 pkgs 53 end
Turn our pkgutil -c listing into a bunch of hashes.
# File lib/puppet/provider/package/pkgutil.rb 87 def self.parse_pkglist(output, hash = {}) 88 output = output.split("\n") 89 90 if output[-1] == "Not in catalog" 91 Puppet.warning _("Package not in pkgutil catalog: %{package}") % { package: hash[:justme] } 92 return nil 93 end 94 95 list = output.collect do |line| 96 next if line =~ /installed\s+catalog/ # header of package list 97 next if noise?(line) 98 99 pkgsplit(line) 100 end.reject { |h| h.nil? } 101 102 if hash[:justme] 103 # Single queries may have been for an alias so return the name requested 104 if list.any? 105 list[-1][:name] = hash[:justme] 106 return list[-1] 107 end 108 else 109 list.reject! { |h| h[:ensure] == :absent } 110 return list 111 end 112 end
# File lib/puppet/provider/package/yum.rb 128 def self.parse_updates(str) 129 # Strip off all content that contains Obsoleting, Security: or Update 130 body = str.partition(/^(Obsoleting|Security:|Update)/).first 131 132 updates = Hash.new { |h, k| h[k] = [] } 133 134 body.split(/^\s*\n/).each do |line| 135 line.split.each_slice(3) do |tuple| 136 next unless tuple[0].include?('.') && tuple[1] =~ VERSION_REGEX 137 138 hash = update_to_hash(*tuple[0..1]) 139 # Create entries for both the package name without a version and a 140 # version since yum considers those as mostly interchangeable. 141 short_name = hash[:name] 142 long_name = "#{hash[:name]}.#{hash[:arch]}" 143 updates[short_name] << hash 144 updates[long_name] << hash 145 end 146 end 147 updates 148 end
# File lib/puppet/provider/user/directoryservice.rb 475 def self.password_hash_dir 476 '/var/db/shadow/hash' 477 end
# File lib/puppet/provider/user/aix.rb 51 def pgrp_to_gid(provider, pgrp) 52 group = group_provider.find(pgrp, provider.ia_module_args) 53 54 group[:gid] 55 end
# File lib/puppet/provider/package/pip.rb 45 def self.pip_version(command) 46 version = nil 47 execpipe [quote(command), '--version'] do |process| 48 process.collect do |line| 49 md = line.strip.match(/^pip (\d+\.\d+\.?\d*).*$/) 50 if md 51 version = md[1] 52 break 53 end 54 end 55 end 56 57 raise Puppet::Error, _("Cannot resolve pip version") unless version 58 59 version 60 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 87 def self.pkg_state(state) 88 case state 89 when /installed/ 90 {:status => 'installed'} 91 when /known/ 92 {:status => 'known'} 93 else 94 raise ArgumentError, _('Unknown format %{resource_name}: %{state}') % { resource_name: self.name, state: state } 95 end 96 end
# File lib/puppet/provider/package/aix.rb 116 def self.pkglist(hash = {}) 117 cmd = [command(:lslpp), "-qLc"] 118 119 name = hash[:pkgname] 120 if name 121 cmd << name 122 end 123 124 begin 125 list = execute(cmd).scan(/^[^#][^:]*:([^:]*):([^:]*):[^:]*:[^:]*:([^:])/).collect { |n,e,s| 126 e = :absent if [:broken, :inconsistent].include?(STATE_CODE[s]) 127 { :name => n, :ensure => e, :status => STATE_CODE[s], :provider => self.name } 128 } 129 rescue Puppet::ExecutionFailure => detail 130 if hash[:pkgname] 131 return nil 132 else 133 raise Puppet::Error, _("Could not list installed Packages: %{detail}") % { detail: detail }, detail.backtrace 134 end 135 end 136 137 if hash[:pkgname] 138 return list.shift 139 else 140 return list 141 end 142 end
Split the different lines into hashes.
# File lib/puppet/provider/package/pkgutil.rb 125 def self.pkgsplit(line) 126 if line =~ /\s*(\S+)\s+(\S+)\s+(.*)/ 127 hash = {} 128 hash[:name] = $1 129 hash[:ensure] = if $2 == "notinst" 130 :absent 131 else 132 $2 133 end 134 hash[:avail] = $3 135 136 if hash[:avail] =~ /^SAME\s*$/ 137 hash[:avail] = hash[:ensure] 138 end 139 140 # Use the name method, so it works with subclasses. 141 hash[:provider] = self.name 142 143 return hash 144 else 145 Puppet.warning _("Cannot match %{line}") % { line: line } 146 return nil 147 end 148 end
# File lib/puppet/provider/file/posix.rb 13 def self.post_resource_eval 14 Selinux.matchpathcon_fini if Puppet::Util::SELinux.selinux_support? 15 end
# File lib/puppet/provider/package/aix.rb 45 def self.prefetch(packages) 46 raise Puppet::Error, _("The aix provider can only be used by root") if Process.euid != 0 47 48 return unless packages.detect { |name, package| package.should(:ensure) == :latest } 49 50 sources = packages.collect { |name, package| package[:source] }.uniq.compact 51 52 updates = {} 53 sources.each do |source| 54 execute(self.srclistcmd(source)).each_line do |line| 55 if line =~ /^[^#][^:]*:([^:]*):([^:]*)/ 56 current = {} 57 current[:name] = $1 58 current[:version] = $2 59 current[:source] = source 60 61 if updates.key?(current[:name]) 62 previous = updates[current[:name]] 63 64 updates[current[:name]] = current unless Puppet::Util::Package.versioncmp(previous[:version], current[:version]) == 1 65 66 else 67 updates[current[:name]] = current 68 end 69 end 70 end 71 end 72 73 packages.each do |name, package| 74 if updates.key?(name) 75 package.provider.latest_info = updates[name] 76 end 77 end 78 end
Define the default provider package command name when the provider is targetable. Required by Puppet::Provider::Package::Targetable::resource_or_provider_command
# File lib/puppet/provider/package/gem.rb 38 def self.provider_command 39 if Puppet::Util::Platform.windows? 40 Puppet::Util.withenv(PATH: windows_path_without_puppet_bin) { command(:gemcmd) } 41 else 42 command(:gemcmd) 43 end 44 end
Quoting is required if the path to the pip command contains spaces. Required for execpipe() but not execute(), as execute() already does this.
# File lib/puppet/provider/package/pip.rb 326 def self.quote(path) 327 if path.include?(" ") 328 "\"#{path}\"" 329 else 330 path 331 end 332 end
Read overrides plist, retrying if necessary
# File lib/puppet/provider/service/launchd.rb 201 def self.read_overrides 202 i = 1 203 overrides = nil 204 loop do 205 Puppet.debug(_("Reading overrides plist, attempt %{i}") % {i: i}) if i > 1 206 overrides = read_plist(launchd_overrides) 207 break unless overrides.nil? 208 raise Puppet::Error.new(_('Unable to read overrides plist, too many attempts')) if i == 20 209 Puppet.info(_('Overrides file could not be read, trying again.')) 210 Kernel.sleep(0.1) 211 i += 1 212 end 213 overrides 214 end
Read a plist, whether its format is XML or in Apple's “binary1” format.
# File lib/puppet/provider/service/launchd.rb 196 def self.read_plist(path) 197 Puppet::Util::Plist.read_plist_file(path) 198 end
This is to fix bug #2296, where two files recurse over the same set of files. It's a rare case, and when it does happen you're not likely to have many actual conflicts, which is good, because this is a pretty inefficient implementation.
# File lib/puppet/type/file.rb 655 def self.remove_less_specific_files(files, parent_path, existing_files, &block) 656 # REVISIT: is this Windows safe? AltSeparator? 657 mypath = parent_path.split(::File::Separator) 658 other_paths = existing_files. 659 select { |r| (yield r) != parent_path}. 660 collect { |r| (yield r).split(::File::Separator) }. 661 select { |p| p[0,mypath.length] == mypath } 662 663 return files if other_paths.empty? 664 665 files.reject { |file| 666 path = (yield file).split(::File::Separator) 667 other_paths.any? { |p| path[0,p.length] == p } 668 } 669 end
@api private Reset the latest version hash to nil needed for spec tests to clear cached value
# File lib/puppet/provider/package/zypper.rb 18 def self.reset! 19 @latest_versions = nil 20 end
# File lib/puppet/type/resources.rb 188 def self.reset_system_users_max_uid! 189 @system_users_max_uid = nil 190 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 122 def self.return_globbed_list_of_file_paths(path) 123 array_of_files = Dir.glob(File.join(path, '*')).collect do |filepath| 124 File.file?(filepath) ? filepath : nil 125 end 126 array_of_files.compact 127 end
Override the specificity method to return 1 if gem is not set as default provider
# File lib/puppet/provider/package/gem.rb 26 def self.specificity 27 match = default_match 28 length = match ? match.length : 0 29 30 return 1 if length == 0 31 32 super 33 end
# File lib/puppet/provider/package/aix.rb 41 def self.srclistcmd(source) 42 [ command(:installp), "-L", "-d", source ] 43 end
# File lib/puppet/util/log/destinations.rb 2 def self.suitable?(obj) 3 Puppet.features.syslog? 4 end
# File lib/puppet/type/resources.rb 167 def self.system_users_max_uid 168 return @system_users_max_uid if @system_users_max_uid 169 170 # First try to read the minimum user id from login.defs 171 if Puppet::FileSystem.exist?('/etc/login.defs') 172 @system_users_max_uid = Puppet::FileSystem.each_line '/etc/login.defs' do |line| 173 break $1.to_i - 1 if line =~ /^\s*UID_MIN\s+(\d+)(\s*#.*)?$/ 174 end 175 end 176 177 # Otherwise, use a sensible default based on the OS family 178 @system_users_max_uid ||= case Facter.value(:osfamily) 179 when 'OpenBSD', 'FreeBSD' 180 999 181 else 182 499 183 end 184 185 @system_users_max_uid 186 end
# File lib/puppet/type/file.rb 44 def self.title_patterns 45 # strip trailing slashes from path but allow the root directory, including 46 # for example "/" or "C:/" 47 [ [ %r{^(/|.+:/|.*[^/])/*\Z}m, [ [ :path ] ] ] ] 48 end
# File lib/puppet/provider/package/windows.rb 56 def self.to_hash(pkg) 57 { 58 :name => pkg.name, 59 :ensure => pkg.version || :installed, 60 :provider => :windows 61 } 62 end
# File lib/puppet/provider/package/pacman.rb 186 def self.to_resource_hash(name, version) 187 { 188 :name => name, 189 :ensure => version, 190 :provider => self.name 191 } 192 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 77 def self.ufoxi_flag(flags) 78 {} 79 end
# File lib/puppet/provider/package/dnf.rb 36 def self.update_command 37 # In DNF, update is deprecated for upgrade 38 'upgrade' 39 end
# File lib/puppet/provider/package/yum.rb 150 def self.update_to_hash(pkgname, pkgversion) 151 152 # The pkgname string has two parts: name, and architecture. Architecture 153 # is the portion of the string following the last "." character. All 154 # characters preceding the final dot are the package name. Parse out 155 # these two pieces of component data. 156 name, _, arch = pkgname.rpartition('.') 157 if name.empty? 158 raise _("Failed to parse package name and architecture from '%{pkgname}'") % { pkgname: pkgname } 159 end 160 161 match = pkgversion.match(VERSION_REGEX) 162 epoch = match[1] || '0' 163 version = match[2] 164 release = match[3] 165 166 { 167 :name => name, 168 :epoch => epoch, 169 :version => version, 170 :release => release, 171 :arch => arch, 172 } 173 end
# File lib/puppet/provider/group/aix.rb 72 def users_to_members(users) 73 users.split(',') 74 end
# File lib/puppet/provider/package/puppet_gem.rb 9 def self.windows_gemcmd 10 puppet_dir = Puppet::Util.get_env('PUPPET_DIR') 11 if puppet_dir 12 File.join(Puppet::Util.get_env('PUPPET_DIR').to_s, 'bin', 'gem.bat') 13 else 14 File.join(Gem.default_bindir, 'gem.bat') 15 end 16 end
Having puppet/bin in PATH makes gem provider to use puppet/bin/gem This is an utility methods that reads the PATH and returns a string that contains the content of PATH but without puppet/bin dir. This is used to pass a custom PATH and execute commands in a controlled environment
# File lib/puppet/provider/package/gem.rb 57 def self.windows_path_without_puppet_bin 58 @path ||= Puppet::Util.get_env('PATH').split(File::PATH_SEPARATOR) 59 .reject { |dir| dir =~ /puppet\\bin$/ } 60 .join(File::PATH_SEPARATOR) 61 end
If yaourt is installed, we can make use of it
# File lib/puppet/provider/package/pacman.rb 12 def self.yaourt? 13 @yaourt ||= Puppet::FileSystem.exist?('/usr/bin/yaourt') 14 end
Public Instance Methods
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 16 def [](param) 17 return super if self.class.valid_parameter?(param) 18 @extra_parameters[param.to_sym] 19 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 23 def []=(param, value) 24 return super if self.class.valid_parameter?(param) 25 @extra_parameters[param.to_sym] = value 26 end
These stub the translation methods normally brought in by FastGettext. Used when Gettext could not be properly initialized.
# File lib/puppet/gettext/stubs.rb 4 def _(msg) 5 msg 6 end
# File lib/puppet/type/resources.rb 106 def able_to_ensure_absent?(resource) 107 resource[:ensure] = :absent 108 rescue ArgumentError, Puppet::Error 109 err _("The 'ensure' attribute on %{name} resources does not accept 'absent' as a value") % { name: self[:name] } 110 false 111 end
# File lib/puppet/provider/service/upstart.rb 366 def add_default_start_to(text) 367 text + "\nstart on runlevel [2,3,4,5]" 368 end
must override this to hand the keyvalue pairs
# File lib/puppet/provider/user/user_role_add.rb 48 def add_properties 49 cmd = [] 50 Puppet::Type.type(:user).validproperties.each do |property| 51 #skip the password because we can't create it with the solaris useradd 52 next if [:ensure, :password, :password_min_age, :password_max_age, :password_warn_days].include?(property) 53 # 1680 Now you can set the hashed passwords on solaris:lib/puppet/provider/user/user_role_add.rb 54 # the value needs to be quoted, mostly because -c might 55 # have spaces in it 56 value = @resource.should(property) 57 if value && value != "" 58 if property == :keys 59 cmd += build_keys_cmd(value) 60 else 61 cmd << flag(property) << value 62 end 63 end 64 end 65 cmd 66 end
# File lib/puppet/provider/group/groupadd.rb 57 def addcmd 58 if @resource.forcelocal? 59 cmd = [command(:localadd)] 60 @custom_environment = Puppet::Util::Libuser.getenv 61 else 62 cmd = [command(:add)] 63 end 64 65 gid = @resource.should(:gid) 66 if gid 67 unless gid == :absent 68 cmd << flag(:gid) << gid 69 end 70 end 71 cmd += check_allow_dup 72 cmd << "-r" if @resource.system? and self.class.system_groups? 73 cmd << @resource[:name] 74 cmd 75 end
# File lib/puppet/functions/alert.rb 11 def alert(scope, *values) 12 Puppet::Util::Log.log_func(scope, :alert, values) 13 end
# File lib/puppet/functions/all.rb 91 def all_Enumerable_1(enumerable) 92 Puppet::Pops::Types::Iterable.asserted_iterable(self, enumerable).all? { |e| yield(e) } 93 end
# File lib/puppet/functions/all.rb 95 def all_Enumerable_2(enumerable) 96 enum = Puppet::Pops::Types::Iterable.asserted_iterable(self, enumerable) 97 if enum.hash_style? 98 enum.all? { |entry| yield(*entry) } 99 else 100 enum.each_with_index { |e, i| return false unless yield(i, e) } 101 true 102 end 103 end
# File lib/puppet/functions/all.rb 83 def all_Hash_1(hash) 84 hash.each_pair.all? { |x| yield(x) } 85 end
# File lib/puppet/functions/all.rb 87 def all_Hash_2(hash) 88 hash.each_pair.all? { |x,y| yield(x,y) } 89 end
Return a list of all applications (both legacy and Face applications), along with a summary
of their functionality.
@return [Array] An Array of Arrays. The outer array contains one entry per application; each
element in the outer array is a pair whose first element is a String containing the application name, and whose second element is a String containing the summary for that application.
# File lib/puppet/face/help.rb 160 def all_application_summaries() 161 available_application_names_special_sort().inject([]) do |result, appname| 162 next result if exclude_from_docs?(appname) 163 164 if (appname == COMMON || appname == SPECIALIZED || appname == BLANK) 165 result << appname 166 elsif (is_face_app?(appname)) 167 begin 168 face = Puppet::Face[appname, :current] 169 # Add deprecation message to summary if the face is deprecated 170 summary = face.deprecated? ? face.summary + ' ' + _("(Deprecated)") : face.summary 171 result << [appname, summary, ' '] 172 rescue StandardError, LoadError 173 error_message = _("!%{sub_command}! Subcommand unavailable due to error.") % { sub_command: appname } 174 error_message += ' ' + _("Check error logs.") 175 result << [ error_message, '', ' ' ] 176 end 177 else 178 begin 179 summary = Puppet::Application[appname].summary 180 if summary.empty? 181 summary = horribly_extract_summary_from(appname) 182 end 183 result << [appname, summary, ' '] 184 rescue StandardError, LoadError 185 error_message = _("!%{sub_command}! Subcommand unavailable due to error.") % { sub_command: appname } 186 error_message += ' ' + _("Check error logs.") 187 result << [ error_message, '', ' ' ] 188 end 189 end 190 end 191 end
# File lib/puppet/network/formats.rb 26 def allowed_yaml_classes 27 @allowed_yaml_classes ||= [ 28 Puppet::Node::Facts, 29 Puppet::Node, 30 Puppet::Transaction::Report, 31 Puppet::Resource, 32 Puppet::Resource::Catalog 33 ] 34 end
# File lib/puppet/type/file.rb 536 def ancestors 537 ancestors = Pathname.new(self[:path]).enum_for(:ascend).map(&:to_s) 538 ancestors.delete(self[:path]) 539 ancestors 540 end
@param type [Annotation] the annotation type @param value [Object] the value to annotate @param block [Proc] optional block to produce the annotation hash
# File lib/puppet/functions/annotate.rb 89 def annotate(type, value, &block) 90 type.implementation_class.annotate(value, &block) 91 end
@param type [Type] the Pcore type @param value [Object] the value to annotate @param annotations [Hash{Annotation => Hash{String => Object}}] hash of annotation hashes
# File lib/puppet/functions/annotate.rb 105 def annotate_multi(type, value, annotations) 106 type.implementation_class.annotate(value, annotations) 107 end
@param type [Annotation] the annotation type @param value [Object] the value to annotate @param annotation_hash [Hash{String => Object}] the annotation hash
# File lib/puppet/functions/annotate.rb 97 def annotate_new(type, value, annotation_hash) 98 type.implementation_class.annotate_new(value, annotation_hash) 99 end
# File lib/puppet/functions/any.rb 96 def any_Enumerable_1(enumerable) 97 Puppet::Pops::Types::Iterable.asserted_iterable(self, enumerable).any? { |e| yield(e) } 98 end
# File lib/puppet/functions/any.rb 100 def any_Enumerable_2(enumerable) 101 enum = Puppet::Pops::Types::Iterable.asserted_iterable(self, enumerable) 102 if enum.hash_style? 103 enum.any? { |entry| yield(*entry) } 104 else 105 enum.each_with_index { |e, i| return true if yield(i, e) } 106 false 107 end 108 end
# File lib/puppet/functions/any.rb 88 def any_Hash_1(hash) 89 hash.each_pair.any? { |x| yield(x) } 90 end
# File lib/puppet/functions/any.rb 92 def any_Hash_2(hash) 93 hash.each_pair.any? { |x,y| yield(x, y) } 94 end
# File lib/puppet/provider/package/aptitude.rb 11 def aptget(*args) 12 args.flatten! 13 # Apparently aptitude hasn't always supported a -q flag. 14 args.delete("-q") if args.include?("-q") 15 args.delete("--force-yes") if args.include?("--force-yes") 16 output = aptitude(*args) 17 18 # Yay, stupid aptitude doesn't throw an error when the package is missing. 19 if args.include?(:install) and output.to_s =~ /Couldn't find any package/ 20 raise Puppet::Error.new( 21 _("Could not find package %{name}") % { name: self.name } 22 ) 23 end 24 end
# File lib/puppet/functions/max.rb 180 def assert_arg_count(args) 181 raise(ArgumentError, 'max(): Wrong number of arguments need at least one') if args.empty? 182 end
##
Helper Methods ##
##
# File lib/puppet/provider/user/directoryservice.rb 463 def assert_full_pbkdf2_password 464 missing = [:password, :salt, :iterations].select { |parameter| @resource[parameter].nil? } 465 466 if !missing.empty? 467 raise Puppet::Error, "OS X versions > 10\.7 use PBKDF2 password hashes, which requires all three of salt, iterations, and password hash. This resource is missing: #{missing.join(', ')}." 468 end 469 end
@param type [Type] the type the value must be an instance of @param value [Object] the value to assert
# File lib/puppet/functions/assert_type.rb 69 def assert_type(type, value) 70 unless Puppet::Pops::Types::TypeCalculator.instance?(type,value) 71 inferred_type = Puppet::Pops::Types::TypeCalculator.infer_set(value) 72 if block_given? 73 # Give the inferred type to allow richer comparison in the given block (if generalized 74 # information is lost). 75 # 76 value = yield(type, inferred_type) 77 else 78 raise Puppet::Pops::Types::TypeAssertionError.new( 79 Puppet::Pops::Types::TypeMismatchDescriber.singleton.describe_mismatch('assert_type():', type, inferred_type), 80 type, inferred_type) 81 end 82 end 83 value 84 end
@param type_string [String] the type the value must be an instance of given in String form @param value [Object] the value to assert
# File lib/puppet/functions/assert_type.rb 89 def assert_type_s(type_string, value, &proc) 90 t = Puppet::Pops::Types::TypeParser.singleton.parse(type_string) 91 block_given? ? assert_type(t, value, &proc) : assert_type(t, value) 92 end
# File lib/puppet/functions/slice.rb 108 def asserted_slice_serving_size(pblock, slice_size) 109 if pblock 110 arity = pblock.arity 111 serving_size = arity < 0 ? slice_size : arity 112 else 113 serving_size = 1 114 end 115 if serving_size == 0 116 raise ArgumentError, _("slice(): block must define at least one parameter. Block has 0.") 117 end 118 unless serving_size == 1 || serving_size == slice_size 119 raise ArgumentError, _("slice(): block must define one parameter, or the same number of parameters as the given size of the slice (%{slice_size}). Block has %{serving_size}; %{parameter_names}") % 120 { slice_size: slice_size, serving_size: serving_size, parameter_names: pblock.parameter_names.join(', ') } 121 end 122 serving_size 123 end
Determine the user to write files as.
# File lib/puppet/type/file.rb 469 def asuser 470 if self.should(:owner) && ! self.should(:owner).is_a?(Symbol) 471 writeable = Puppet::Util::SUIDManager.asuser(self.should(:owner)) { 472 FileTest.writable?(::File.dirname(self[:path])) 473 } 474 475 # If the parent directory is writeable, then we execute 476 # as the user in question. Otherwise we'll rely on 477 # the 'owner' property to do things. 478 asuser = self.should(:owner) if writeable 479 end 480 481 asuser 482 end
# File lib/puppet/provider/user/user_role_add.rb 128 def auths 129 user_attributes[:auths] if user_attributes 130 end
# File lib/puppet/face/help.rb 196 def available_application_names_special_sort() 197 full_list = Puppet::Application.available_application_names 198 a_list = full_list & %w{apply agent config help lookup module resource} 199 a_list = a_list.sort 200 also_ran = full_list - a_list 201 also_ran = also_ran.sort 202 [[COMMON], a_list, [BLANK], [SPECIALIZED], also_ran].flatten(1) 203 end
Use pip CLI to look up versions from PyPI repositories, honoring local pip config such as custom repositories.
# File lib/puppet/provider/package/pip.rb 144 def available_versions 145 command = resource_or_provider_command 146 self.class.validate_command(command) 147 148 command_version = self.class.pip_version(command) 149 if self.class.compare_pip_versions(command_version, '1.5.4') == -1 150 available_versions_with_old_pip 151 else 152 available_versions_with_new_pip(command_version) 153 end 154 end
# File lib/puppet/provider/package/pip.rb 156 def available_versions_with_new_pip(command_version) 157 command = resource_or_provider_command 158 self.class.validate_command(command) 159 160 command_and_options = [self.class.quote(command), 'install', "#{@resource[:name]}==versionplease"] 161 extra_arg = list_extra_flags(command_version) 162 command_and_options << extra_arg if extra_arg 163 command_and_options << install_options if @resource[:install_options] 164 execpipe command_and_options do |process| 165 process.collect do |line| 166 # PIP OUTPUT: Could not find a version that satisfies the requirement example==versionplease (from versions: 1.2.3, 4.5.6) 167 if line =~ /from versions: (.+)\)/ 168 versionList = $1.split(', ').sort do |x,y| 169 self.class.compare_pip_versions(x, y) 170 end 171 return versionList 172 end 173 end 174 end 175 [] 176 end
# File lib/puppet/provider/package/pip.rb 178 def available_versions_with_old_pip 179 command = resource_or_provider_command 180 self.class.validate_command(command) 181 182 Dir.mktmpdir("puppet_pip") do |dir| 183 command_and_options = [self.class.quote(command), 'install', "#{@resource[:name]}", '-d', "#{dir}", '-v'] 184 command_and_options << install_options if @resource[:install_options] 185 execpipe command_and_options do |process| 186 process.collect do |line| 187 # PIP OUTPUT: Using version 0.10.1 (newest of versions: 1.2.3, 4.5.6) 188 if line =~ /Using version .+? \(newest of versions: (.+?)\)/ 189 versionList = $1.split(', ').sort do |x,y| 190 self.class.compare_pip_versions(x, y) 191 end 192 return versionList 193 end 194 end 195 end 196 return [] 197 end 198 end
Back up the existing file at a given prior to it being removed @api private @raise [Puppet::Error] if the file backup failed @return [void]
# File lib/puppet/type/file.rb 1056 def backup_existing 1057 unless perform_backup 1058 #TRANSLATORS refers to a file which could not be backed up 1059 raise Puppet::Error, _("Could not back up; will not remove") 1060 end 1061 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 621 def base64_decode_string(value) 622 Base64.decode64([[value].pack("H*")].pack("m").strip) 623 end
# File lib/puppet/provider/package/apt.rb 93 def best_version(should_range) 94 versions = [] 95 96 output = aptcache :madison, @resource[:name] 97 output.each_line do |line| 98 is = line.split('|')[1].strip 99 begin 100 is_version = DebianVersion.parse(is) 101 versions << is_version if should_range.include?(is_version) 102 rescue DebianVersion::ValidationFailure 103 Puppet.debug("Cannot parse #{is} as a debian version") 104 end 105 end 106 107 return versions.sort.last if versions.any? 108 109 Puppet.debug("No available version for package #{@resource[:name]} is included in range #{should_range}") 110 should_range 111 end
# File lib/puppet/functions/empty.rb 69 def binary_empty(bin) 70 bin.length == 0 71 end
# File lib/puppet/functions/binary_file.rb 24 def binary_file(scope, unresolved_path) 25 path = Puppet::Parser::Files.find_file(unresolved_path, scope.compiler.environment) 26 unless path && Puppet::FileSystem.exist?(path) 27 #TRANSLATORS the string "binary_file()" should not be translated 28 raise Puppet::ParseError, _("binary_file(): The given file '%{unresolved_path}' does not exist") % { unresolved_path: unresolved_path } 29 end 30 Puppet::Pops::Types::PBinaryType::Binary.from_binary_string(Puppet::FileSystem.binread(path)) 31 end
# File lib/puppet/functions/length.rb 40 def binary_length(bin) 41 bin.length 42 end
# File lib/puppet/functions/break.rb 38 def break_impl() 39 # get file, line if available, else they are set to nil 40 file, line = Puppet::Pops::PuppetStack.top_of_stack 41 42 # PuppetStopIteration contains file and line and is a StopIteration exception 43 # so it can break a Ruby Kernel#loop or enumeration 44 # 45 raise Puppet::Pops::Evaluator::PuppetStopIteration.new(file, line) 46 end
# File lib/puppet/type/file.rb 484 def bucket 485 return @bucket if @bucket 486 487 backup = self[:backup] 488 return nil unless backup 489 return nil if backup =~ /^\./ 490 491 unless catalog or backup == "puppet" 492 fail _("Can not find filebucket for backups without a catalog") 493 end 494 495 filebucket = catalog.resource(:filebucket, backup) if catalog 496 if !catalog || (!filebucket && backup != 'puppet') 497 fail _("Could not find filebucket %{backup} specified in backup") % { backup: backup } 498 end 499 500 return default_bucket unless filebucket 501 502 @bucket = filebucket.bucket 503 504 @bucket 505 end
# File lib/puppet/provider/user/user_role_add.rb 156 def build_keys_cmd(keys_hash) 157 cmd = [] 158 keys_hash.each do |k,v| 159 cmd << "-K" << "#{k}=#{v}" 160 end 161 cmd 162 end
# File lib/puppet/provider/service/systemd.rb 91 def cached_enabled? 92 return @cached_enabled if @cached_enabled 93 cmd = [command(:systemctl), 'is-enabled', '--', @resource[:name]] 94 result = execute(cmd, :failonfail => false) 95 @cached_enabled = { output: result.chomp, exitcode: result.exitstatus } 96 end
# File lib/puppet/functions/call.rb 76 def call_deferred(scope, deferred) 77 Puppet::Pops::Evaluator::DeferredResolver.resolve(deferred, scope.compiler) 78 end
# File lib/puppet/functions/call.rb 71 def call_impl_block(scope, function_name, *args, &block) 72 # The call function must be able to call functions loaded by any loader visible from the calling scope. 73 Puppet::Pops::Parser::EvaluatingParser.new.evaluator.external_call_function(function_name, args, scope, &block) 74 end
@return [Boolean] If the current file should be backed up and can be backed up.
# File lib/puppet/type/file.rb 1012 def can_backup?(type) 1013 if type == "directory" and force? 1014 # (#18110) Directories cannot be removed without :force, 1015 # so it doesn't make sense to back them up unless removing with :force. 1016 true 1017 elsif type == "file" or type == "link" 1018 true 1019 else 1020 # Including: “blockSpecial”, “characterSpecial”, "fifo", "socket", “unknown” 1021 false 1022 end 1023 end
# File lib/puppet/type/resources.rb 96 def check(resource) 97 @checkmethod ||= "#{self[:name]}_check" 98 @hascheck ||= respond_to?(@checkmethod) 99 if @hascheck 100 return send(@checkmethod, resource) 101 else 102 return true 103 end 104 end
# File lib/puppet/provider/group/groupadd.rb 37 def check_allow_dup 38 # We have to manually check for duplicates when using libuser 39 # because by default duplicates are allowed. This check is 40 # to ensure consistent behaviour of the useradd provider when 41 # using both useradd and luseradd 42 if not @resource.allowdupe? and @resource.forcelocal? 43 if @resource.should(:gid) and findgroup(:gid, @resource.should(:gid).to_s) 44 raise(Puppet::Error, _("GID %{resource} already exists, use allowdupe to force group creation") % { resource: @resource.should(:gid).to_s }) 45 end 46 elsif @resource.allowdupe? and not @resource.forcelocal? 47 return ["-o"] 48 end 49 [] 50 end
# File lib/puppet/provider/user/useradd.rb 225 def check_manage_home 226 cmd = [] 227 if @resource.managehome? 228 # libuser does not implement the -m flag 229 cmd << "-m" unless @resource.forcelocal? 230 else 231 osfamily = Facter.value(:osfamily) 232 osversion = Facter.value(:operatingsystemmajrelease).to_i 233 # SLES 11 uses pwdutils instead of shadow, which does not have -M 234 # Solaris and OpenBSD use different useradd flavors 235 unless osfamily =~ /Solaris|OpenBSD/ || osfamily == 'Suse' && osversion <= 11 236 cmd << "-M" 237 end 238 end 239 cmd 240 end
(Un)install may “fail” because the package requested a reboot, the system requested a reboot, or something else entirely. Reboot requests mean the package was installed successfully, but we warn since we don't have a good reboot strategy.
# File lib/puppet/provider/package/windows.rb 103 def check_result(hr) 104 operation = resource[:ensure] == :absent ? 'uninstall' : 'install' 105 106 case hr 107 when self.class::ERROR_SUCCESS 108 # yeah 109 when self.class::ERROR_SUCCESS_REBOOT_INITIATED 110 warning(_("The package %{operation}ed successfully and the system is rebooting now.") % { operation: operation }) 111 when self.class::ERROR_SUCCESS_REBOOT_REQUIRED 112 warning(_("The package %{operation}ed successfully, but the system must be rebooted.") % { operation: operation }) 113 else 114 raise Puppet::Util::Windows::Error.new(_("Failed to %{operation}") % { operation: operation }, hr) 115 end 116 end
# File lib/puppet/provider/user/useradd.rb 242 def check_system_users 243 if self.class.system_users? && resource.system? 244 ["-r"] 245 else 246 [] 247 end 248 end
# File lib/puppet/provider/user/user_role_add.rb 38 def check_valid_shell 39 unless File.exist?(@resource.should(:shell)) 40 raise(Puppet::Error, "Shell #{@resource.should(:shell)} must exist") 41 end 42 unless File.executable?(@resource.should(:shell).to_s) 43 raise(Puppet::Error, "Shell #{@resource.should(:shell)} must be executable") 44 end 45 end
Verify that we have the executable
# File lib/puppet/provider/exec/posix.rb 28 def checkexe(command) 29 exe = extractexe(command) 30 31 if File.expand_path(exe) == exe 32 if !Puppet::FileSystem.exist?(exe) 33 raise ArgumentError, _("Could not find command '%{exe}'") % { exe: exe } 34 elsif !File.file?(exe) 35 raise ArgumentError, _("'%{exe}' is a %{klass}, not a file") % { exe: exe, klass: File.ftype(exe) } 36 elsif !File.executable?(exe) 37 raise ArgumentError, _("'%{exe}' is not executable") % { exe: exe } 38 end 39 return 40 end 41 42 if resource[:path] 43 Puppet::Util.withenv :PATH => resource[:path].join(File::PATH_SEPARATOR) do 44 return if which(exe) 45 end 46 end 47 48 # 'which' will only return the command if it's executable, so we can't 49 # distinguish not found from not executable 50 raise ArgumentError, _("Could not find command '%{exe}'") % { exe: exe } 51 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 79 def checkforcdrom 80 have_cdrom = begin 81 !!(File.read("/etc/apt/sources.list") =~ /^[^#]*cdrom:/) 82 rescue 83 # This is basically pathological... 84 false 85 end 86 87 if have_cdrom and @resource[:allowcdrom] != :true 88 raise Puppet::Error, 89 _("/etc/apt/sources.list contains a cdrom source; not installing. Use 'allowcdrom' to override this failure.") 90 end 91 end
Defines an instance method within a class
# File lib/puppet/util/metaid.rb 17 def class_def(name, &blk) 18 class_eval { define_method name, &blk } 19 end
clean facts for host
# File lib/puppet/face/node/clean.rb 77 def clean_cached_facts(node) 78 Puppet::Node::Facts.indirection.destroy(node) 79 Puppet.info _("%{node}'s facts removed") % { node: node } 80 end
clean cached node host
# File lib/puppet/face/node/clean.rb 83 def clean_cached_node(node) 84 Puppet::Node.indirection.destroy(node) 85 Puppet.info _("%{node}'s cached node removed") % { node: node } 86 end
clean signed cert for host
# File lib/puppet/face/node/clean.rb 68 def clean_cert(node) 69 if Puppet.features.puppetserver_ca? 70 Puppetserver::Ca::Action::Clean.new(LoggerIO.new).run({ 'certnames' => [node] }) 71 else 72 Puppet.info _("Not managing %{node} certs as this host is not a CA") % { node: node } 73 end 74 end
clean node reports for host
# File lib/puppet/face/node/clean.rb 89 def clean_reports(node) 90 Puppet::Transaction::Report.indirection.destroy(node) 91 Puppet.info _("%{node}'s reports removed") % { node: node } 92 end
# File lib/puppet/face/node/clean.rb 42 def cleanup(node) 43 clean_cert(node) 44 clean_cached_facts(node) 45 clean_cached_node(node) 46 clean_reports(node) 47 end
# File lib/puppet/util/log/destinations.rb 6 def close 7 Syslog.close 8 end
# File lib/puppet/functions/empty.rb 49 def collection_empty(coll) 50 coll.empty? 51 end
# File lib/puppet/functions/length.rb 32 def collection_length(col) 33 col.size 34 end
# File lib/puppet/provider/user/user_role_add.rb 76 def command(cmd) 77 cmd = ("role_#{cmd}").intern if is_role? or (!exists? and @resource[:ensure] == :role) 78 super(cmd) 79 end
# File lib/puppet/provider/user/useradd.rb 67 def comment 68 return localcomment if @resource.forcelocal? 69 get(:comment) 70 end
# File lib/puppet/provider/user/windows_adsi.rb 124 def comment=(value) 125 user['Description'] = value 126 end
# File lib/puppet/provider/service/upstart.rb 331 def comment_start_block_in(text) 332 parens = 0 333 text.lines.map do |line| 334 if line.match(START_ON) || parens > 0 335 # If there are more opening parens than closing parens, we need to comment out a multiline 'start on' stanza 336 parens += unbalanced_parens_on(remove_trailing_comments_from(line)) 337 "#" + line 338 else 339 line 340 end 341 end.join('') 342 end
Returns true if the service is complete. A complete service is a service that has the general/complete property defined.
# File lib/puppet/provider/service/smf.rb 109 def complete_service? 110 unless supports_incomplete_services? 111 raise Puppet::Error, _("Cannot query if the %{service} service is complete: The concept of complete/incomplete services was introduced in Solaris 11.1. You are on a Solaris %{release} machine.") % { service: @resource[:name], release: Facter.value(:operatingsystemrelease) } 112 end 113 114 return @complete_service if @complete_service 115 116 # We need to use the service's FMRI when querying its config. because 117 # general/complete is an instance-specific property. 118 fmri = service_fmri 119 120 # Check if the general/complete property is defined. If it is undefined, 121 # then svccfg will not print anything to the console. 122 property_defn = svccfg("-s", fmri, "listprop", "general/complete").chomp 123 @complete_service = ! property_defn.empty? 124 end
# File lib/puppet/network/formats.rb 226 def construct_output(data) 227 output = '' 228 data.each do |key, value| 229 output << "#{key}=#{value}" 230 output << "\n" 231 end 232 output 233 end
# File lib/puppet/functions/contain.rb 31 def contain(scope, *classes) 32 if Puppet[:tasks] 33 raise Puppet::ParseErrorWithIssue.from_issue_and_stack( 34 Puppet::Pops::Issues::CATALOG_OPERATION_NOT_SUPPORTED_WHEN_SCRIPTING, 35 {:operation => 'contain'}) 36 end 37 38 # Make call patterns uniform and protected against nested arrays, also make 39 # names absolute if so desired. 40 classes = scope.transform_and_assert_classnames(classes.flatten) 41 42 result = classes.map {|name| Puppet::Pops::Types::TypeFactory.host_class(name) } 43 containing_resource = scope.resource 44 45 # This is the same as calling the include function but faster and does not rely on the include 46 # function. 47 (scope.compiler.evaluate_classes(classes, scope, false) || []).each do |resource| 48 if ! scope.catalog.edge?(containing_resource, resource) 49 scope.catalog.add_edge(containing_resource, resource) 50 end 51 end 52 # Result is an Array[Class, 1, n] which allows chaining other operations 53 result 54 end
# File lib/puppet/type/tidy.rb 136 def convert(unit, multi) 137 num = AgeConvertors[unit] 138 if num 139 return num * multi 140 else 141 self.fail _("Invalid age unit '%{unit}'") % { unit: unit } 142 end 143 end
# File lib/puppet/functions/convert_to.rb 30 def convert_to(value, type, *args, &block) 31 result = call_function('new', type, value, *args) 32 block_given? ? yield(result) : result 33 end
# File lib/puppet/provider/group/groupadd.rb 52 def create 53 super 54 set(:members, @resource[:members]) if @resource[:members] 55 end
This method will create a given value using dscl
# File lib/puppet/provider/user/directoryservice.rb 480 def create_attribute_with_dscl(path, username, keyname, value) 481 set_attribute_with_dscl('-create', path, username, keyname, value) 482 end
@api private
# File lib/puppet/face/epp.rb 499 def create_compiler(options) 500 if options[:node] 501 node = options[:node] 502 else 503 node = Puppet[:node_name_value] 504 505 # If we want to lookup the node we are currently on 506 # we must returning these settings to their default values 507 Puppet.settings[:facts_terminus] = 'facter' 508 Puppet.settings[:node_cache_terminus] = nil 509 end 510 511 unless node.is_a?(Puppet::Node) 512 node = Puppet::Node.indirection.find(node) 513 # Found node must be given the environment to use in some cases, use the one configured 514 # or given on the command line 515 node.environment = Puppet[:environment] 516 end 517 518 fact_file = options[:facts] 519 520 if fact_file 521 if fact_file.is_a?(Hash) # when used via the Face API 522 given_facts = fact_file 523 elsif fact_file.end_with?("json") 524 given_facts = Puppet::Util::Json.load(Puppet::FileSystem.read(fact_file, :encoding => 'utf-8')) 525 else 526 given_facts = Puppet::Util::Yaml.safe_load_file(fact_file) 527 end 528 529 unless given_facts.instance_of?(Hash) 530 raise _("Incorrect formatted data in %{fact_file} given via the --facts flag") % { fact_file: fact_file } 531 end 532 # It is difficult to add to or modify the set of facts once the node is created 533 # as changes does not show up in parameters. Rather than manually patching up 534 # a node and risking future regressions, a new node is created from scratch 535 node = Puppet::Node.new(node.name, :facts => Puppet::Node::Facts.new("facts", node.facts.values.merge(given_facts))) 536 node.environment = Puppet[:environment] 537 node.merge(node.facts.values) 538 end 539 540 compiler = Puppet::Parser::Compiler.new(node) 541 # configure compiler with facts and node related data 542 # Set all global variables from facts 543 compiler.send(:set_node_parameters) 544 545 # pretend that the main class (named '') has been evaluated 546 # since it is otherwise not possible to resolve top scope variables 547 # using '::' when rendering. (There is no harm doing this for the other actions) 548 # 549 compiler.topscope.class_set('', compiler.topscope) 550 compiler 551 end
Create the new user with dscl
# File lib/puppet/provider/user/directoryservice.rb 498 def create_new_user(username) 499 dscl '.', '-create', "/Users/#{username}" 500 end
# File lib/puppet/provider/user/user_role_add.rb 116 def create_role 117 if exists? and !is_role? 118 run(transition("role"), "transition user to") 119 else 120 run(addcmd, "create role") 121 end 122 end
# File lib/puppet/functions/crit.rb 11 def crit(scope, *values) 12 Puppet::Util::Log.log_func(scope, :crit, values) 13 end
returns the full path to the current daemon directory note that this path can be overridden in the resource definition
# File lib/puppet/provider/service/daemontools.rb 109 def daemon 110 path = resource[:path] 111 raise Puppet::Error.new("#{self.class.name} must specify a path for daemon directory") unless path 112 File.join(path, resource[:name]) 113 end
Define the daemon_reload? function to check if the unit is requiring to trigger a “systemctl daemon-reload” If the unit file is flagged with NeedDaemonReload=yes, then a systemd daemon-reload will be run. If multiple unit files have been updated, the first one flagged will trigger the daemon-reload for all of them. The others will be then flagged with NeedDaemonReload=no. So the command will run only once in a puppet run. This function is called only on start & restart unit options. Reference: (PUP-3483) Systemd provider doesn't scan for changed units
# File lib/puppet/provider/service/systemd.rb 152 def daemon_reload? 153 cmd = [command(:systemctl), 'show', '--property=NeedDaemonReload', '--', @resource[:name]] 154 daemon_reload = execute(cmd, :failonfail => false).strip.split('=').last 155 if daemon_reload == 'yes' 156 daemon_reload_cmd = [command(:systemctl), 'daemon-reload'] 157 execute(daemon_reload_cmd, :failonfail => false) 158 end 159 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 27 def daemonize 28 raise NotImplementedError, "Kernel.daemonize is too dangerous, please don't try to use it." 29 end
# File lib/puppet/network/formats.rb 56 def data_to_instance(klass, data) 57 return data if data.is_a?(klass) 58 59 unless data.is_a? Hash 60 raise Puppet::Network::FormatHandler::FormatError, _("Serialized YAML did not contain a valid instance of %{klass}") % { klass: klass } 61 end 62 63 klass.from_data_hash(data) 64 end
This method is required for Debian systems due to the way the SysVInit-Systemd compatibility layer works. When we are trying to manage a service which does not have a Systemd unit file, we need to go through the old init script to determine whether it is enabled or not. See PUP-5016 for more details.
# File lib/puppet/provider/service/systemd.rb 126 def debian_enabled? 127 status = execute(["/usr/sbin/invoke-rc.d", "--quiet", "--query", @resource[:name], "start"], :failonfail => false) 128 if [104, 106].include?(status.exitstatus) 129 return :true 130 elsif [101, 105].include?(status.exitstatus) 131 # 101 is action not allowed, which means we have to do the check manually. 132 # 105 is unknown, which generally means the initscript does not support query 133 # The debian policy states that the initscript should support methods of query 134 # For those that do not, perform the checks manually 135 # http://www.debian.org/doc/debian-policy/ch-opersys.html 136 if get_start_link_count >= 4 137 return :true 138 else 139 return :false 140 end 141 else 142 return :false 143 end 144 end
# File lib/puppet/functions/debug.rb 11 def debug(scope, *values) 12 Puppet::Util::Log.log_func(scope, :debug, values) 13 end
# File lib/puppet/functions/eyaml_lookup_key.rb 80 def decrypt(data, context, options, key) 81 if encrypted?(data) 82 # Options must be set prior to each call to #parse since they end up as static variables in 83 # the Options class. They cannot be set once before #decrypt_value is called, since each #decrypt 84 # might cause a new lookup through interpolation. That lookup in turn, might use a different eyaml 85 # config. 86 # 87 Hiera::Backend::Eyaml::Options.set(options) 88 begin 89 tokens = Hiera::Backend::Eyaml::Parser::ParserFactory.hiera_backend_parser.parse(data) 90 data = tokens.map(&:to_plain_text).join.chomp 91 rescue StandardError => ex 92 raise Puppet::DataBinding::LookupError, 93 _("hiera-eyaml backend error decrypting %{data} when looking up %{key} in %{path}. Error was %{message}") % { data: data, key: key, path: options['path'], message: ex.message } 94 end 95 end 96 context.interpolate(data) 97 end
# File lib/puppet/functions/eyaml_lookup_key.rb 65 def decrypt_value(value, context, options, key) 66 case value 67 when String 68 decrypt(value, context, options, key) 69 when Hash 70 result = {} 71 value.each_pair { |k, v| result[context.interpolate(k)] = decrypt_value(v, context, options, key) } 72 result 73 when Array 74 value.map { |v| decrypt_value(v, context, options, key) } 75 else 76 value 77 end 78 end
# File lib/puppet/provider/service/src.rb 51 def default_action 52 "once" 53 end
# File lib/puppet/type/file.rb 507 def default_bucket 508 Puppet::Type.type(:filebucket).mkdefaultbucket.bucket 509 end
# File lib/puppet/face/help.rb 82 def default_case?(args) 83 args.empty? 84 end
# File lib/puppet/provider/service/src.rb 47 def default_runlevel 48 "2" 49 end
# File lib/puppet/provider/service/windows.rb 118 def default_timeout 119 Puppet::Util::Windows::Service::DEFAULT_TIMEOUT 120 end
# File lib/puppet/provider/service/windows.rb 37 def delayed_start 38 Puppet::Util::Windows::Service.set_startup_configuration(@resource[:name], options: {startup_type: :SERVICE_AUTO_START, delayed: true}) 39 rescue => detail 40 raise Puppet::Error.new(_("Cannot enable %{resource_name} for delayed start, error was: %{detail}") % { resource_name: @resource[:name], detail: detail }, detail ) 41 end
# File lib/puppet/provider/group/windows_adsi.rb 91 def delete 92 Puppet::Util::Windows::ADSI::Group.delete(@resource[:name]) 93 94 @deleted = true 95 end
# File lib/puppet/provider/group/groupadd.rb 108 def deletecmd 109 if @resource.forcelocal? 110 @custom_environment = Puppet::Util::Libuser.getenv 111 [command(:localdelete), @resource[:name]] 112 else 113 [command(:delete), @resource[:name]] 114 end 115 end
# File lib/puppet/functions/empty.rb 80 def deprecation_warning_for(arg_type) 81 file, line = Puppet::Pops::PuppetStack.top_of_stack 82 msg = _("Calling function empty() with %{arg_type} value is deprecated.") % { arg_type: arg_type } 83 Puppet.warn_once('deprecations', "empty-from-#{file}-#{line}", msg, file, line) 84 end
# File lib/puppet/functions/tree_each.rb 195 def depth_first?(options) 196 (order = options['order']).nil? ? true : order == 'depth_first' 197 end
# File lib/puppet/type/tidy.rb 231 def depthfirst? 232 true 233 end
Return the desired checksum or nil
# File lib/puppet/type/file.rb 1079 def desired_checksum(property, path) 1080 return if SOURCE_ONLY_CHECKSUMS.include?(self[:checksum]) 1081 1082 if self[:checksum] && self[:checksum_value] 1083 "{#{self[:checksum]}}#{self[:checksum_value]}" 1084 elsif property && property.name == :source 1085 meta = property.metadata 1086 return unless meta 1087 1088 # due to HttpMetadata the checksum type may fallback to mtime, so recheck 1089 return if SOURCE_ONLY_CHECKSUMS.include?(meta.checksum_type) 1090 meta.checksum 1091 elsif property && property.name == :content 1092 str = property.actual_content 1093 str ? parameter(:checksum).sum(str) : nil 1094 end 1095 end
# File lib/puppet/provider/user/user_role_add.rb 112 def destroy 113 run(deletecmd, "delete "+ (is_role? ? "role" : "user")) 114 end
Given a blob of output from `nimclient -o showres` and a package name, this method checks to see if there are multiple versions of the package available on the lpp_source. If there are, the method returns
- package_type, latest_version
-
(where package_type is one of :installp or :rpm).
If there is only one version of the package available, it returns [package_type, nil], because the caller doesn't need to pass the version string to the command-line command if there is only one version available. If the package is not available at all, the method simply returns nil (instead of a tuple).
# File lib/puppet/provider/package/nim.rb 269 def determine_latest_version(showres_output, package_name) 270 packages = parse_showres_output(showres_output) 271 unless packages.has_key?(package_name) 272 return nil 273 end 274 if (packages[package_name].count == 1) 275 version = packages[package_name].keys[0] 276 return packages[package_name][version], nil 277 else 278 versions = packages[package_name].keys 279 latest_version = (versions.sort { |a, b| Puppet::Util::Package.versioncmp(b, a) })[0] 280 return packages[package_name][latest_version], latest_version 281 end 282 end
# File lib/puppet/provider/package/nim.rb 284 def determine_package_type(showres_output, package_name, version) 285 packages = parse_showres_output(showres_output) 286 unless (packages.has_key?(package_name) and packages[package_name].has_key?(version)) 287 return nil 288 end 289 packages[package_name][version] 290 end
# File lib/puppet/functions/dig.rb 36 def dig(data, *args) 37 walked_path = [] 38 args.reduce(data) do | d, k | 39 return nil if d.nil? || k.nil? 40 if !(d.is_a?(Array) || d.is_a?(Hash)) 41 t = Puppet::Pops::Types::TypeCalculator.infer(d) 42 msg = _("The given data does not contain a Collection at %{walked_path}, got '%{type}'") % { walked_path: walked_path, type: t } 43 error_data = Puppet::DataTypes::Error.new( 44 msg, 45 'SLICE_ERROR', 46 {'walked_path' => walked_path, 'value_type' => t}, 47 'EXPECTED_COLLECTION' 48 ) 49 raise Puppet::ErrorWithData.new(error_data, msg) 50 end 51 52 walked_path << k 53 if d.is_a?(Array) && !k.is_a?(Integer) 54 t = Puppet::Pops::Types::TypeCalculator.infer(k) 55 msg = _("The given data requires an Integer index at %{walked_path}, got '%{type}'") % { walked_path: walked_path, type: t } 56 error_data = Puppet::DataTypes::Error.new( 57 msg, 58 'SLICE_ERROR', 59 {'walked_path' => walked_path, 'index_type' => t}, 60 'EXPECTED_INTEGER_INDEX' 61 ) 62 raise Puppet::ErrorWithData.new(error_data, msg) 63 end 64 d[k] 65 end 66 end
Return the appropriate digest algorithm with fallbacks in case puppet defaults have not been initialized.
# File lib/puppet/type/file/checksum.rb 47 def digest_algorithm 48 value || Puppet[:digest_algorithm].to_sym 49 end
# File lib/puppet/provider/package/dnfmodule.rb 126 def disable(args = @resource[:name]) 127 execute([command(:dnf), 'module', 'disable', '-d', '0', '-e', self.class.error_level, '-y', args]) 128 end
# File lib/puppet/provider/service/upstart.rb 299 def disable_post_0_9_0(over_text) 300 write_script_to(overscript, ensure_disabled_with_manual(over_text)) 301 end
# File lib/puppet/provider/service/upstart.rb 290 def disable_pre_0_6_7(script_text) 291 disabled_script = comment_start_block_in(script_text) 292 write_script_to(initscript, disabled_script) 293 end
# File lib/puppet/provider/service/upstart.rb 295 def disable_pre_0_9_0(script_text) 296 write_script_to(initscript, ensure_disabled_with_manual(script_text)) 297 end
# File lib/puppet/provider/package/yum.rb 357 def disableexcludes 358 scan_options(resource[:install_options], '--disableexcludes') 359 end
# File lib/puppet/provider/package/yum.rb 353 def disablerepo 354 scan_options(resource[:install_options], '--disablerepo') 355 end
# File lib/puppet/functions/camelcase.rb 58 def do_camelcase(x) 59 # x can only be a String or Numeric because type constraints have been automatically applied 60 x.is_a?(String) ? on_string(x) : x 61 end
# File lib/puppet/functions/capitalize.rb 57 def do_capitalize(x) 58 # x can only be a String or Numeric because type constraints have been automatically applied 59 x.is_a?(String) ? x.capitalize : x 60 end
# File lib/puppet/functions/chomp.rb 53 def do_chomp(x) 54 # x can only be a String or Numeric because type constraints have been automatically applied 55 x.is_a?(String) ? x.chomp : x 56 end
# File lib/puppet/functions/chop.rb 63 def do_chop(x) 64 # x can only be a String or Numeric because type constraints have been automatically applied 65 x.is_a?(String) ? x.chop : x 66 end
# File lib/puppet/functions/downcase.rb 86 def do_downcase(x) 87 x.is_a?(String) ? x.downcase : call_function('downcase', x) 88 end
# File lib/puppet/functions/lookup.rb 209 def do_lookup(scope, name, value_type, default_value, has_default, override, default_values_hash, merge, &block) 210 Puppet::Pops::Lookup.lookup(name, value_type, default_value, has_default, merge, 211 Puppet::Pops::Lookup::Invocation.new(scope, override, default_values_hash), &block) 212 end
# File lib/puppet/functions/lstrip.rb 54 def do_lstrip(x) 55 # x can only be a String or Numeric because type constraints have been automatically applied 56 x.is_a?(String) ? x.lstrip : x 57 end
# File lib/puppet/functions/match.rb 126 def do_match(s, regexp) 127 result = regexp.match(s) 128 result.to_a if result 129 end
# File lib/puppet/functions/rstrip.rb 54 def do_rstrip(x) 55 # x can only be a String or Numeric because type constraints have been automatically applied 56 x.is_a?(String) ? x.rstrip : x 57 end
# File lib/puppet/functions/strip.rb 54 def do_strip(x) 55 # x can only be a String or Numeric because type constraints have been automatically applied 56 x.is_a?(String) ? x.strip : x 57 end
# File lib/puppet/functions/upcase.rb 86 def do_upcase(x) 87 x.is_a?(String) ? x.upcase : call_function('upcase', x) 88 end
# File lib/puppet/face/epp.rb 368 def dump_parse(source, filename, options, show_filename = true) 369 output = "" 370 evaluating_parser = Puppet::Pops::Parser::EvaluatingParser::EvaluatingEppParser.new 371 begin 372 if options[:validate] 373 parse_result = evaluating_parser.parse_string(source, filename) 374 else 375 # side step the assert_and_report step 376 parse_result = evaluating_parser.parser.parse_string(source) 377 end 378 if show_filename && options[:header] 379 output << "--- #{filename}\n" 380 end 381 fmt = options[:format] 382 if fmt.nil? || fmt == 'old' 383 output << Puppet::Pops::Model::ModelTreeDumper.new.dump(parse_result) << "\n" 384 else 385 require_relative '../../puppet/pops/pn' 386 pn = Puppet::Pops::Model::PNTransformer.transform(parse_result) 387 case fmt 388 when 'json' 389 options[:pretty] ? JSON.pretty_unparse(pn.to_data) : JSON.dump(pn.to_data) 390 else 391 pn.format(options[:pretty] ? Puppet::Pops::PN::Indent.new(' ') : nil, output) 392 end 393 end 394 rescue Puppet::ParseError => detail 395 if show_filename 396 Puppet.err("--- #{filename}") 397 end 398 Puppet.err(detail.message) 399 "" 400 end 401 end
Produces the effective template file from a module/template or file reference @api private
# File lib/puppet/face/epp.rb 555 def effective_template(file, env) 556 template_file = Puppet::Parser::Files.find_template(file, env) 557 if !template_file.nil? 558 template_file 559 elsif Puppet::FileSystem.exist?(file) 560 file 561 else 562 nil 563 end 564 end
# File lib/puppet/provider/package/portage.rb 251 def eix_get_version_for_slot(versions_and_slots, slot) 252 # [2.7.12:2.7 3.4.5:3.4 3.5.2:3.5] 3.5 253 return nil if versions_and_slots.nil? 254 versions_and_slots = versions_and_slots.split(',') 255 # [2.7.12:2.7 3.4.5:3.4 3.5.2:3.5] 256 versions_and_slots.map! { |version_and_slot| version_and_slot.split(':') } 257 # [2.7.12: 2.7 258 # 3.4.5: 3.4 259 # 3.5.2: 3.5] 260 version_for_slot = versions_and_slots.find { |version_and_slot| version_and_slot.last == slot } 261 # [3.5.2: 3.5] 262 version_for_slot.first if version_for_slot 263 # 3.5.2 264 end
# File lib/puppet/provider/package/portage.rb 241 def eix_get_version_for_versions(versions, target) 242 # [2.7.10-r1,2.7.12,3.4.3-r1,3.4.5,3.5.2] 3.5.2 243 return nil if versions.nil? 244 versions = versions.split(',') 245 # [2.7.10-r1 2.7.12 3.4.3-r1 3.4.5 3.5.2] 246 versions.find { |version| version == target } 247 # 3.5.2 248 end
# File lib/puppet/functions/emerg.rb 11 def emerg(scope, *values) 12 Puppet::Util::Log.log_func(scope, :emerg, values) 13 end
# File lib/puppet/provider/package/dnfmodule.rb 117 def enable(args = @resource[:name]) 118 execute([command(:dnf), 'module', 'enable', '-d', '0', '-e', self.class.error_level, '-y', args]) 119 end
# File lib/puppet/provider/service/upstart.rb 276 def enable_post_0_9_0(script_text, over_text) 277 over_text = remove_manual_from(over_text) 278 279 if enabled_post_0_9_0?(script_text, over_text) == :false 280 if script_text.match(START_ON) 281 over_text << extract_start_on_block_from(script_text) 282 else 283 over_text << "\nstart on runlevel [2,3,4,5]" 284 end 285 end 286 287 write_script_to(overscript, over_text) 288 end
# File lib/puppet/provider/service/upstart.rb 258 def enable_pre_0_9_0(text) 259 # We also need to remove any manual stanzas to ensure that it is enabled 260 text = remove_manual_from(text) 261 262 if enabled_pre_0_9_0?(text) == :false 263 enabled_script = 264 if text.match(COMMENTED_START_ON) 265 uncomment_start_block_in(text) 266 else 267 add_default_start_to(text) 268 end 269 else 270 enabled_script = text 271 end 272 273 write_script_to(initscript, enabled_script) 274 end
if the service file exists in rc.conf.d then it's already enabled
# File lib/puppet/provider/service/bsd.rb 25 def enabled? 26 rcfile = File.join(rcconf_dir, @resource[:name]) 27 return :true if Puppet::FileSystem.exist?(rcfile) 28 29 :false 30 end
Static services cannot be enabled or disabled manually. Indirect services should not be enabled or disabled due to limitations in systemd (see github.com/systemd/systemd/issues/6681).
# File lib/puppet/provider/service/systemd.rb 45 def enabled_insync?(current) 46 case cached_enabled?[:output] 47 when 'static' 48 # masking static services is OK, but enabling/disabling them is not 49 if @resource[:enable] == :mask 50 current == @resource[:enable] 51 else 52 Puppet.debug("Unable to enable or disable static service #{@resource[:name]}") 53 return true 54 end 55 when 'indirect' 56 Puppet.debug("Service #{@resource[:name]} is in 'indirect' state and cannot be enabled/disabled") 57 return true 58 else 59 current == @resource[:enable] 60 end 61 end
# File lib/puppet/provider/service/upstart.rb 235 def enabled_post_0_9_0?(script_text, over_text) 236 # This version has manual stanzas and override files 237 # So we check to see if an uncommented start on or manual stanza is the last one in the 238 # conf file and any override files. The last one in the file wins. 239 enabled = :false 240 241 script_text.each_line do |line| 242 if line.match(START_ON) 243 enabled = :true 244 elsif line.match(MANUAL) 245 enabled = :false 246 end 247 end 248 over_text.each_line do |line| 249 if line.match(START_ON) 250 enabled = :true 251 elsif line.match(MANUAL) 252 enabled = :false 253 end 254 end if over_text 255 enabled 256 end
# File lib/puppet/provider/service/upstart.rb 211 def enabled_pre_0_6_7?(script_text) 212 # Upstart version < 0.6.7 means no manual stanza. 213 if script_text.match(START_ON) 214 return :true 215 else 216 return :false 217 end 218 end
# File lib/puppet/provider/service/upstart.rb 220 def enabled_pre_0_9_0?(script_text) 221 # Upstart version < 0.9.0 means no override files 222 # So we check to see if an uncommented start on or manual stanza is the last one in the file 223 # The last one in the file wins. 224 enabled = :false 225 script_text.each_line do |line| 226 if line.match(START_ON) 227 enabled = :true 228 elsif line.match(MANUAL) 229 enabled = :false 230 end 231 end 232 enabled 233 end
# File lib/puppet/provider/package/yum.rb 349 def enablerepo 350 scan_options(resource[:install_options], '--enablerepo') 351 end
# File lib/puppet/functions/eyaml_lookup_key.rb 99 def encrypted?(data) 100 /.*ENC\[.*?\]/ =~ data ? true : false 101 end
# File lib/puppet/provider/service/upstart.rb 370 def ensure_disabled_with_manual(text) 371 remove_manual_from(text) + "\nmanual" 372 end
Matches given Array against given pattern and returns an Array with mapped match results.
@param array [Array<String>] the array of strings to match @param pattern [String, Regexp, Puppet::Pops::Types::PPatternType
, Puppet::Pops::PRegexpType, Array] the pattern @return [Array<Array<String, nil>>] Array with matches (see {#match}), non matching entries produce a nil entry
# File lib/puppet/functions/match.rb 74 def enumerable_match(array, pattern) 75 array.map {|s| match(s, pattern) } 76 end
# File lib/puppet/face/node/clean.rb 94 def environment 95 @environment ||= Puppet.lookup(:current_environment) 96 end
# File lib/puppet/functions/epp.rb 46 def epp(scope, path, parameters = nil) 47 Puppet::Pops::Evaluator::EppEvaluator.epp(scope, path, scope.compiler.environment, parameters) 48 end
# File lib/puppet/face/help.rb 141 def erb(name) 142 template = (Pathname(__FILE__).dirname + "help" + name) 143 erb = ERB.new(template.read, nil, '-') 144 erb.filename = template.to_s 145 return erb 146 end
# File lib/puppet/functions/err.rb 11 def err(scope, *values) 12 Puppet::Util::Log.log_func(scope, :err, values) 13 end
# File lib/puppet/provider/service/freebsd.rb 16 def error(msg) 17 raise Puppet::Error, msg 18 end
Create any children via recursion or whatever.
# File lib/puppet/type/file.rb 530 def eval_generate 531 return [] unless self.recurse? 532 533 recurse 534 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 224 def exclude_from_docs?(appname) 225 %w{face_base indirection_base report status}.include? appname 226 end
# File lib/puppet/provider/package/pkg.rb 281 def exec_cmd(*cmd) 282 output = Puppet::Util::Execution.execute(cmd, :failonfail => false, :combine => true) 283 {:out => output, :exit => output.exitstatus} 284 end
# File lib/puppet/provider/user/hpux.rb 92 def exec_getprpw(user,opts) 93 Puppet::Util::Execution.execute("/usr/lbin/getprpw #{opts} #{user}", { :combine => true }) 94 end
# File lib/puppet/provider/service/systemd.rb 171 def exist? 172 result = execute([command(:systemctl), 'cat', '--', @resource[:name]], :failonfail => false) 173 result.exitstatus == 0 174 end
# File lib/puppet/provider/group/groupadd.rb 21 def exists? 22 return !!localgid if @resource.forcelocal? 23 super 24 end
Get expiry from system and convert to Puppet-style date
# File lib/puppet/provider/user/pw.rb 96 def expiry 97 expiry = self.get(:expiry) 98 expiry = :absent if expiry == 0 99 100 if expiry != :absent 101 t = Time.at(expiry) 102 expiry = "%4d-%02d-%02d" % [t.year, t.month, t.mday] 103 end 104 105 expiry 106 end
# File lib/puppet/provider/service/upstart.rb 356 def extract_start_on_block_from(text) 357 parens = 0 358 text.lines.map do |line| 359 if line.match(START_ON) || parens > 0 360 parens += unbalanced_parens_on(remove_trailing_comments_from(line)) 361 line 362 end 363 end.join('') 364 end
Extract value name from service or rcvar
# File lib/puppet/provider/service/freebsd.rb 31 def extract_value_name(name, rc_index, regex, regex_index) 32 value_name = self.rcvar[rc_index] 33 self.error("No #{name} name found in rcvar") if value_name.nil? 34 value_name = value_name.gsub!(regex, regex_index) 35 self.error("#{name} name is empty") if value_name.nil? 36 self.debug("#{name} name is #{value_name}") 37 value_name 38 end
# File lib/puppet/functions/eyaml_lookup_key.rb 23 def eyaml_lookup_key(key, options, context) 24 return context.cached_value(key) if context.cache_has_key(key) 25 26 # Can't do this with an argument_mismatch dispatcher since there is no way to declare a struct that at least 27 # contains some keys but may contain other arbitrary keys. 28 unless options.include?('path') 29 #TRANSLATORS 'eyaml_lookup_key':, 'path', 'paths' 'glob', 'globs', 'mapped_paths', and lookup_key should not be translated 30 raise ArgumentError, 31 _("'eyaml_lookup_key': one of 'path', 'paths' 'glob', 'globs' or 'mapped_paths' must be declared in hiera.yaml"\ 32 " when using this lookup_key function") 33 end 34 35 # nil key is used to indicate that the cache contains the raw content of the eyaml file 36 raw_data = context.cached_value(nil) 37 if raw_data.nil? 38 raw_data = load_data_hash(options, context) 39 context.cache(nil, raw_data) 40 end 41 context.not_found unless raw_data.include?(key) 42 context.cache(key, decrypt_value(raw_data[key], context, options, key)) 43 end
Make sure the file we wrote out is what we think it is. @param [Puppet::Parameter] property the param or property that wrote the file, or nil @param [String] path to the file @param [String] the checksum for the local file
@api private
# File lib/puppet/type/file.rb 1070 def fail_if_checksum_is_wrong(property, path, content_checksum) 1071 desired_checksum = desired_checksum(property, path) 1072 1073 if desired_checksum && content_checksum != desired_checksum 1074 self.fail _("File written to disk did not match desired checksum; discarding changes (%{content_checksum} vs %{desired_checksum})") % { content_checksum: content_checksum, desired_checksum: desired_checksum } 1075 end 1076 end
# File lib/puppet/provider/file/windows.rb 139 def file 140 @file ||= Puppet::FileSystem.pathname(resource[:path]) 141 end
# File lib/puppet/functions/filter.rb 108 def filter_Enumerable_1(enumerable) 109 result = [] 110 enum = Puppet::Pops::Types::Iterable.asserted_iterable(self, enumerable) 111 begin 112 loop do 113 it = enum.next 114 if yield(it) 115 result << it 116 end 117 end 118 rescue StopIteration 119 end 120 result 121 end
# File lib/puppet/functions/filter.rb 123 def filter_Enumerable_2(enumerable) 124 enum = Puppet::Pops::Types::Iterable.asserted_iterable(self, enumerable) 125 if enum.hash_style? 126 result = {} 127 enum.each { |k, v| result[k] = v if yield(k, v) } 128 result 129 else 130 result = [] 131 begin 132 index = 0 133 loop do 134 it = enum.next 135 if yield(index, it) 136 result << it 137 end 138 index += 1 139 end 140 rescue StopIteration 141 end 142 result 143 end 144 end
# File lib/puppet/functions/filter.rb 94 def filter_Hash_1(hash) 95 result = hash.select {|x, y| yield([x, y]) } 96 # Ruby 1.8.7 returns Array 97 result = Hash[result] unless result.is_a? Hash 98 result 99 end
# File lib/puppet/functions/filter.rb 101 def filter_Hash_2(hash) 102 result = hash.select {|x, y| yield(x, y) } 103 # Ruby 1.8.7 returns Array 104 result = Hash[result] unless result.is_a? Hash 105 result 106 end
# File lib/puppet/functions/find_file.rb 35 def find_file(scope, *args) 36 args.each do |file| 37 found = Puppet::Parser::Files.find_file(file, scope.compiler.environment) 38 if found && Puppet::FileSystem.exist?(found) 39 return found 40 end 41 end 42 nil 43 end
# File lib/puppet/functions/find_file.rb 31 def find_file_array(scope, array) 32 find_file(scope, *array) 33 end
# File lib/puppet/functions/find_template.rb 54 def find_template(scope, *args) 55 args.each do |file| 56 found = Puppet::Parser::Files.find_template(file, scope.compiler.environment) 57 if found && Puppet::FileSystem.exist?(found) 58 return found 59 end 60 end 61 nil 62 end
# File lib/puppet/functions/find_template.rb 50 def find_template_array(scope, array) 51 find_template(scope, *array) 52 end
# File lib/puppet/provider/group/groupadd.rb 132 def findgroup(key, value) 133 group_file = '/etc/group' 134 group_keys = [:group_name, :password, :gid, :user_list] 135 136 unless @groups 137 unless Puppet::FileSystem.exist?(group_file) 138 raise Puppet::Error.new("Forcelocal set for group resource '#{resource[:name]}', but #{group_file} does not exist") 139 end 140 141 @groups = [] 142 Puppet::FileSystem.each_line(group_file) do |line| 143 group = line.chomp.split(':') 144 @groups << Hash[group_keys.zip(group)] 145 end 146 end 147 148 @groups.find { |param| param[key] == value } || false 149 end
# File lib/puppet/provider/user/useradd.rb 77 def finduser(key, value) 78 passwd_file = '/etc/passwd' 79 passwd_keys = [:account, :password, :uid, :gid, :gecos, :directory, :shell] 80 81 unless @users 82 unless Puppet::FileSystem.exist?(passwd_file) 83 raise Puppet::Error.new("Forcelocal set for user resource '#{resource[:name]}', but #{passwd_file} does not exist") 84 end 85 86 @users = [] 87 Puppet::FileSystem.each_line(passwd_file) do |line| 88 user = line.chomp.split(':') 89 @users << Hash[passwd_keys.zip(user)] 90 end 91 end 92 @users.find { |param| param[key] == value } || false 93 end
We have to do some extra finishing, to retrieve our bucket if there is one.
# File lib/puppet/type/file.rb 523 def finish 524 # Look up our bucket, if there is one 525 bucket 526 super 527 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 18 def finkcmd(*args) 19 fink(*args) 20 end
Uses the wrapper to prevent failure when the service is not running; rcctl(8) return non-zero in that case.
# File lib/puppet/provider/service/openbsd.rb 87 def flags 88 output = execute([command(:rcctl), "get", @resource[:name], "flags"], 89 :failonfail => false, :combine => false, :squelch => false).chomp 90 self.debug("Flags are: \"#{output}\"") 91 output 92 end
# File lib/puppet/provider/service/openbsd.rb 94 def flags=(value) 95 self.debug("Changing flags from #{flags} to #{value}") 96 rcctl(:set, @resource[:name], :flags, value) 97 # If the service is already running, force a restart as the flags have been changed. 98 rcctl(:restart, @resource[:name]) if running? 99 end
# File lib/puppet/functions/flatten.rb 61 def flatten_args(*args) 62 args.flatten() 63 end
# File lib/puppet/network/formats.rb 212 def flatten_array(array) 213 a={} 214 array.each_with_index do |el, i| 215 if el.is_a? Hash 216 flatten_hash(el).map do |el_k, el_v| 217 a["#{i}.#{el_k}"] = el_v 218 end 219 else 220 a["#{i}"] = el 221 end 222 end 223 a 224 end
# File lib/puppet/network/formats.rb 190 def flatten_hash(hash) 191 hash.each_with_object({}) do |(k, v), h| 192 if v.is_a? Hash 193 flatten_hash(v).map do |h_k, h_v| 194 h["#{k}.#{h_k}"] = h_v 195 end 196 elsif v.is_a? Array 197 v.each_with_index do |el, i| 198 if el.is_a? Hash 199 flatten_hash(el).map do |el_k, el_v| 200 h["#{k}.#{i}.#{el_k}"] = el_v 201 end 202 else 203 h["#{k}.#{i}"] = el 204 end 205 end 206 else 207 h[k] = v 208 end 209 end 210 end
# File lib/puppet/provider/package/dnfmodule.rb 134 def flavor 135 @property_hash[:flavor] 136 end
# File lib/puppet/provider/package/dnfmodule.rb 138 def flavor=(value) 139 install if flavor != @resource.should(:flavor) 140 end
Only flush if we created or modified a group, not deleted
# File lib/puppet/provider/group/windows_adsi.rb 98 def flush 99 @group.commit if @group && !@deleted 100 end
# File lib/puppet/provider/user/directoryservice.rb 551 def flush_dscl_cache 552 dscacheutil '-flushcache' 553 end
# File lib/puppet/functions/each.rb 142 def foreach_Enumerable_1(enumerable) 143 enum = Puppet::Pops::Types::Iterable.asserted_iterable(self, enumerable) 144 begin 145 loop { yield(enum.next) } 146 rescue StopIteration 147 end 148 # produces the receiver 149 enumerable 150 end
# File lib/puppet/functions/each.rb 152 def foreach_Enumerable_2(enumerable) 153 enum = Puppet::Pops::Types::Iterable.asserted_iterable(self, enumerable) 154 if enum.hash_style? 155 enum.each { |entry| yield(*entry) } 156 else 157 begin 158 index = 0 159 loop do 160 yield(index, enum.next) 161 index += 1 162 end 163 rescue StopIteration 164 end 165 end 166 # produces the receiver 167 enumerable 168 end
# File lib/puppet/functions/each.rb 118 def foreach_Hash_1(hash) 119 enumerator = hash.each_pair 120 begin 121 hash.size.times do 122 yield(enumerator.next) 123 end 124 rescue StopIteration 125 end 126 # produces the receiver 127 hash 128 end
# File lib/puppet/functions/each.rb 130 def foreach_Hash_2(hash) 131 enumerator = hash.each_pair 132 begin 133 hash.size.times do 134 yield(*enumerator.next) 135 end 136 rescue StopIteration 137 end 138 # produces the receiver 139 hash 140 end
# File lib/puppet/util/log/destinations.rb 119 def format(msg) 120 # logstash_event format is documented at 121 # https://logstash.jira.com/browse/LOGSTASH-675 122 123 data = msg.to_hash 124 data['version'] = 1 125 data['@timestamp'] = data['time'] 126 data.delete('time') 127 128 data 129 end
# File lib/puppet/functions/strftime.rb 197 def format_timespan(time_object, format) 198 time_object.format(format) 199 end
# File lib/puppet/functions/strftime.rb 201 def format_timestamp(time_object, format, timezone = nil) 202 time_object.format(format, timezone) 203 end
# File lib/puppet/functions/unwrap.rb 51 def from_any(arg) 52 unwrapped = arg 53 if block_given? 54 yield(unwrapped) 55 else 56 unwrapped 57 end 58 end
# File lib/puppet/functions/unwrap.rb 42 def from_sensitive(arg) 43 unwrapped = arg.unwrap 44 if block_given? 45 yield(unwrapped) 46 else 47 unwrapped 48 end 49 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 115 def generate 116 return [] unless self.purge? 117 resource_type.instances. 118 reject { |r| catalog.resource_refs.include? r.ref }. 119 select { |r| check(r) }. 120 select { |r| r.class.validproperty?(:ensure) }. 121 select { |r| able_to_ensure_absent?(r) }. 122 each { |resource| 123 @parameters.each do |name, param| 124 resource[name] = param.value if param.metaparam? 125 end 126 127 # Mark that we're purging, so transactions can handle relationships 128 # correctly 129 resource.purging 130 } 131 end
# File lib/puppet/functions/size.rb 11 def generic_size(arg) 12 call_function('length', arg) 13 end
Gets a result from given value and a navigation string
# File lib/puppet/functions/get.rb 125 def get_from_value(value, navigation, default_value = nil, &block) 126 return default_value if value.nil? 127 return value if navigation.empty? 128 129 # Note: split_key always processes the initial segment as a string even if it could be an integer. 130 # This since it is designed for lookup keys. For a numeric first segment 131 # like '0.1' the wanted result is `[0,1]`, not `["0", 1]`. The workaround here is to 132 # prefix the navigation with `"x."` thus giving split_key a first segment that is a string. 133 # The fake segment is then dropped. 134 segments = split_key("x." + navigation) {|err| _("Syntax error in dotted-navigation string")} 135 segments.shift 136 137 begin 138 result = call_function('dig', value, *segments) 139 return result.nil? ? default_value : result 140 rescue Puppet::ErrorWithData => e 141 if block_given? 142 yield(e.error_data) 143 else 144 raise e 145 end 146 end 147 end
Gets a result from a $var name and a navigation string
# File lib/puppet/functions/getvar.rb 81 def get_from_var_name(scope, var_string, navigation, default_value = nil, &block) 82 catch(:undefined_variable) do 83 return call_function_with_scope(scope,'get', scope.lookupvar(var_string), navigation, default_value, &block) 84 end 85 default_value 86 end
# File lib/puppet/provider/package/openbsd.rb 174 def get_full_name(latest = false) 175 # In case of a real update (i.e., the package already exists) then 176 # pkg_add(8) can handle the flavors. However, if we're actually 177 # installing with 'latest', we do need to handle the flavors. This is 178 # done so we can feed pkg_add(8) the full package name to install to 179 # prevent ambiguity. 180 if latest && resource[:flavor] 181 "#{resource[:name]}--#{resource[:flavor]}" 182 elsif latest 183 # Don't depend on get_version for updates. 184 @resource[:name] 185 else 186 # If :ensure contains a version, use that instead of looking it up. 187 # This allows for installing packages with the same stem, but multiple 188 # version such as openldap-server. 189 if @resource[:ensure].to_s =~ /(\d[^-]*)$/ 190 use_version = @resource[:ensure] 191 else 192 use_version = get_version 193 end 194 195 [ @resource[:name], use_version, @resource[:flavor]].join('-').gsub(/-+$/, '') 196 end 197 end
# File lib/puppet/provider/package/pip.rb 215 def get_install_command_options() 216 should = @resource[:ensure] 217 command_options = %w{install -q} 218 command_options += install_options if @resource[:install_options] 219 220 if @resource[:source] 221 if String === should 222 command_options << "#{@resource[:source]}@#{should}#egg=#{@resource[:name]}" 223 else 224 command_options << "#{@resource[:source]}#egg=#{@resource[:name]}" 225 end 226 227 return command_options 228 end 229 230 if should == :latest 231 command_options << "--upgrade" << @resource[:name] 232 233 return command_options 234 end 235 236 unless String === should 237 command_options << @resource[:name] 238 239 return command_options 240 end 241 242 begin 243 should_range = PIP_VERSION_RANGE.parse(should, PIP_VERSION) 244 rescue PIP_VERSION_RANGE::ValidationFailure, PIP_VERSION::ValidationFailure 245 Puppet.debug("Cannot parse #{should} as a pip version range, falling through.") 246 command_options << "#{@resource[:name]}==#{should}" 247 248 return command_options 249 end 250 251 if should_range.is_a?(PIP_VERSION_RANGE::Eq) 252 command_options << "#{@resource[:name]}==#{should}" 253 254 return command_options 255 end 256 257 should = best_version(should_range) 258 259 if should == should_range 260 # when no suitable version for the given range was found, let pip handle 261 if should.is_a?(PIP_VERSION_RANGE::MinMax) 262 command_options << "#{@resource[:name]} #{should.split.join(',')}" 263 else 264 command_options << "#{@resource[:name]} #{should}" 265 end 266 else 267 command_options << "#{@resource[:name]}==#{should}" 268 end 269 270 command_options 271 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 564 def get_shadow_hash_data(users_plist) 565 if users_plist['ShadowHashData'] 566 password_hash_plist = users_plist['ShadowHashData'][0] 567 self.class.convert_binary_to_hash(password_hash_plist) 568 else 569 false 570 end 571 end
# File lib/puppet/provider/service/debian.rb 60 def get_start_link_count 61 Dir.glob("/etc/rc*.d/S??#{@resource[:name]}").length 62 end
# File lib/puppet/provider/user/directoryservice.rb 555 def get_users_plist(username) 556 # This method will retrieve the data stored in a user's plist and 557 # return it as a native Ruby hash. 558 path = "#{users_plist_dir}/#{username}.plist" 559 Puppet::Util::Plist.read_plist_file(path) 560 end
# File lib/puppet/provider/user/useradd.rb 266 def get_value_for_property(property) 267 return nil if property == :ensure 268 return nil if property_manages_password_age?(property) 269 return nil if property == :groups and @resource.forcelocal? 270 return nil if property == :expiry and @resource.forcelocal? 271 value = @resource.should(property) 272 return nil if !value || value == "" 273 274 value 275 end
# File lib/puppet/face/epp.rb 403 def get_values(compiler, options) 404 template_values = nil 405 values_file = options[:values_file] 406 if values_file 407 begin 408 if values_file =~ /\.yaml$/ 409 template_values = Puppet::Util::Yaml.safe_load_file(values_file, [Symbol]) 410 elsif values_file =~ /\.pp$/ 411 evaluating_parser = Puppet::Pops::Parser::EvaluatingParser.new 412 template_values = evaluating_parser.evaluate_file(compiler.topscope, values_file) 413 else 414 Puppet.err(_("Only .yaml or .pp can be used as a --values_file")) 415 end 416 rescue => e 417 Puppet.err(_("Could not load --values_file %{error}") % { error: e.message }) 418 end 419 if !(template_values.nil? || template_values.is_a?(Hash)) 420 Puppet.err(_("--values_file option must evaluate to a Hash or undef/nil, got: '%{template_class}'") % { template_class: template_values.class }) 421 end 422 end 423 424 values = options[:values] 425 if values 426 evaluating_parser = Puppet::Pops::Parser::EvaluatingParser.new 427 result = evaluating_parser.evaluate_string(compiler.topscope, values, 'values-hash') 428 case result 429 when nil 430 template_values 431 when Hash 432 template_values.nil? ? result : template_values.merge(result) 433 else 434 Puppet.err(_("--values option must evaluate to a Hash or undef, got: '%{values_class}'") % { values_class: result.class }) 435 end 436 else 437 template_values 438 end 439 end
# File lib/puppet/provider/package/openbsd.rb 199 def get_version 200 execpipe([command(:pkginfo), "-I", @resource[:name]]) do |process| 201 # our regex for matching pkg_info output 202 regex = /^(.*)-(\d[^-]*)[-]?(\w*)(.*)$/ 203 master_version = 0 204 version = -1 205 206 process.each_line do |line| 207 match = regex.match(line.split[0]) 208 if match 209 # now we return the first version, unless ensure is latest 210 version = match.captures[1] 211 return version unless @resource[:ensure] == "latest" 212 213 master_version = version unless master_version > version 214 end 215 end 216 217 return master_version unless master_version == 0 218 return '' if version == -1 219 raise Puppet::Error, _("%{version} is not available for this package") % { version: version } 220 end 221 rescue Puppet::ExecutionFailure 222 return nil 223 end
Get the process ID for a running process. Requires the 'pattern' parameter.
# File lib/puppet/provider/service/base.rb 31 def getpid 32 @resource.fail "Either stop/status commands or a pattern must be specified" unless @resource[:pattern] 33 regex = Regexp.new(@resource[:pattern]) 34 ps = getps 35 36 self.debug "Executing '#{ps}'" 37 table = Puppet::Util::Execution.execute(ps) 38 39 # The output of the PS command can be a mashup of several different 40 # encodings depending on which processes are running and what 41 # arbitrary data has been used to set their name in the process table. 42 # 43 # First, try a polite conversion to in order to match the UTF-8 encoding 44 # of our regular expression. 45 table = Puppet::Util::CharacterEncoding.convert_to_utf_8(table) 46 # If that fails, force to UTF-8 and then scrub as most uses are scanning 47 # for ACII-compatible program names. 48 table.force_encoding(Encoding::UTF_8) unless table.encoding == Encoding::UTF_8 49 table = table.scrub unless table.valid_encoding? 50 51 table.each_line { |line| 52 if regex.match(line) 53 self.debug "Process matched: #{line}" 54 ary = line.sub(/^[[:space:]]+/u, '').split(/[[:space:]]+/u) 55 return ary[1] 56 end 57 } 58 59 nil 60 end
get the proper 'ps' invocation for the platform ported from the facter 2.x implementation, since facter 3.x is dropping the fact (for which this was the only use)
# File lib/puppet/provider/service/base.rb 17 def getps 18 case Facter.value(:operatingsystem) 19 when 'OpenWrt' 20 'ps www' 21 when 'FreeBSD', 'NetBSD', 'OpenBSD', 'Darwin', 'DragonFly' 22 'ps auxwww' 23 else 24 'ps -ef' 25 end 26 end
# File lib/puppet/provider/group/groupadd.rb 26 def gid 27 return localgid if @resource.forcelocal? 28 get(:gid) 29 end
# File lib/puppet/provider/file/posix.rb 39 def gid2name(id) 40 return id.to_s if id.is_a?(Symbol) or id.is_a?(String) 41 return nil if id > Puppet[:maximum_uid].to_i 42 43 begin 44 group = Etc.getgrgid(id) 45 rescue TypeError, ArgumentError 46 return nil 47 end 48 49 if group.gid == "" 50 return nil 51 else 52 return group.name 53 end 54 end
# File lib/puppet/provider/group/windows_adsi.rb 106 def gid=(value) 107 fail "gid is read-only" 108 end
# File lib/puppet/provider/file/posix.rb 94 def group 95 stat = resource.stat 96 return :absent unless stat 97 98 currentvalue = stat.gid 99 100 # On OS X, files that are owned by -2 get returned as really 101 # large GIDs instead of negative ones. This isn't a Ruby bug, 102 # it's an OS X bug, since it shows up in perl, too. 103 if currentvalue > Puppet[:maximum_uid].to_i 104 self.warning _("Apparently using negative GID (%{currentvalue}) on a platform that does not consistently handle them") % { currentvalue: currentvalue } 105 currentvalue = :silly 106 end 107 108 currentvalue 109 end
Convert a gropu name to an id.
# File lib/puppet/provider/user/ldap.rb 115 def group2id(group) 116 Puppet::Type.type(:group).provider(:ldap).name2id(group) 117 end
# File lib/puppet/provider/file/posix.rb 111 def group=(should) 112 # Set our method appropriately, depending on links. 113 if resource[:links] == :manage 114 method = :lchown 115 else 116 method = :chown 117 end 118 119 begin 120 File.send(method, nil, should, resource[:path]) 121 rescue => detail 122 raise Puppet::Error, _("Failed to set group to '%{should}': %{detail}") % { should: should, detail: detail }, detail.backtrace 123 end 124 end
# File lib/puppet/functions/group_by.rb 41 def group_by_1(collection) 42 collection.group_by do |item| 43 yield(item) 44 end.freeze 45 end
# File lib/puppet/functions/group_by.rb 57 def group_by_2(collection) 58 collection.group_by do |k, v| 59 yield(k, v) 60 end.freeze 61 end
# File lib/puppet/functions/group_by.rb 47 def group_by_2a(array) 48 grouped = array.size.times.zip(array).group_by do |k, v| 49 yield(k, v) 50 end 51 52 grouped.each_with_object({}) do |(k, v), hsh| 53 hsh[k] = v.map { |item| item[1] } 54 end.freeze 55 end
# File lib/puppet/provider/user/ldap.rb 121 def group_manager 122 Puppet::Type.type(:group).provider(:ldap).manager 123 end
# File lib/puppet/provider/user/ldap.rb 125 def group_properties(values) 126 if values.empty? or values == :absent 127 {:ensure => :present} 128 else 129 {:ensure => :present, :members => values} 130 end 131 end
Find all groups this user is a member of in ldap.
# File lib/puppet/provider/user/ldap.rb 57 def groups 58 # We want to cache the current result, so we know if we 59 # have to remove old values. 60 unless @property_hash[:groups] 61 result = group_manager.search("memberUid=#{name}") 62 unless result 63 return @property_hash[:groups] = :absent 64 end 65 66 return @property_hash[:groups] = result.collect { |r| r[:name] }.sort.join(",") 67 end 68 @property_hash[:groups] 69 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 324 def groups=(value) 325 guid = self.class.get_attribute_from_dscl('Users', @resource.name, 'GeneratedUID')['dsAttrTypeStandard:GeneratedUID'][0] 326 groups_to_add = value.split(',') - groups.split(',') 327 groups_to_add.each do |group| 328 merge_attribute_with_dscl('Groups', group, 'GroupMembership', @resource.name) 329 merge_attribute_with_dscl('Groups', group, 'GroupMembers', guid) 330 end 331 end
# File lib/puppet/provider/user/useradd.rb 376 def groups? 377 !!@resource[:groups] 378 end
# File lib/puppet/provider/user/windows_adsi.rb 46 def groups_insync?(current, should) 47 return false unless current 48 49 # By comparing account SIDs we don't have to worry about case 50 # sensitivity, or canonicalization of account names. 51 52 # Cannot use munge of the group property to canonicalize @should 53 # since the default array_matching comparison is not commutative 54 55 # dupes automatically weeded out when hashes built 56 current_groups = Puppet::Util::Windows::ADSI::Group.name_sid_hash(current) 57 specified_groups = Puppet::Util::Windows::ADSI::Group.name_sid_hash(should) 58 59 current_sids = current_groups.keys.to_a 60 specified_sids = specified_groups.keys.to_a 61 62 if @resource[:membership] == :inclusive 63 current_sids.sort == specified_sids.sort 64 else 65 (specified_sids & current_sids) == specified_sids 66 end 67 end
# File lib/puppet/provider/user/windows_adsi.rb 69 def groups_to_s(groups) 70 return '' if groups.nil? || !groups.kind_of?(Array) 71 groups = groups.map do |group_name| 72 sid = Puppet::Util::Windows::SID.name_to_principal(group_name) 73 if sid.account =~ /\\/ 74 account, _ = Puppet::Util::Windows::ADSI::Group.parse_name(sid.account) 75 else 76 account = sid.account 77 end 78 resource.debug("#{sid.domain}\\#{account} (#{sid.sid})") 79 "#{sid.domain}\\#{account}" 80 end 81 return groups.join(',') 82 end
# File lib/puppet/util/log/destinations.rb 27 def handle(msg) 28 # XXX Syslog currently has a bug that makes it so you 29 # cannot log a message with a '%' in it. So, we get rid 30 # of them. 31 if msg.source == "Puppet" 32 msg.to_s.split("\n").each do |line| 33 @syslog.send(msg.level, line.gsub("%", '%%')) 34 end 35 else 36 msg.to_s.split("\n").each do |line| 37 @syslog.send(msg.level, "(%s) %s" % [msg.source.to_s.delete("%"), 38 line.gsub("%", '%%') 39 ] 40 ) 41 end 42 end 43 end
# File lib/puppet/provider/user/pw.rb 86 def has_sensitive_data?(property = nil) 87 #Check for sensitive values? 88 properties = property ? [property] : Puppet::Type.type(:user).validproperties 89 properties.any? do |prop| 90 p = @resource.parameter(prop) 91 p && p.respond_to?(:is_sensitive) && p.is_sensitive 92 end 93 end
# File lib/puppet/functions/lookup.rb 214 def hash_args(options_hash) 215 [ 216 options_hash['value_type'], 217 options_hash['default_value'], 218 options_hash.include?('default_value'), 219 options_hash['override'] || {}, 220 options_hash['default_values_hash'] || {}, 221 options_hash['merge'] 222 ] 223 end
Mark that our init script supports 'status' commands.
# File lib/puppet/provider/service/init.rb 109 def hasstatus=(value) 110 case value 111 when true, "true"; @parameters[:hasstatus] = true 112 when false, "false"; @parameters[:hasstatus] = false 113 else 114 raise Puppet::Error, "Invalid 'hasstatus' value #{value.inspect}" 115 end 116 end
# File lib/puppet/face/help.rb 86 def help_for_help?(args) 87 args.length == 1 && args.first == 'help' 88 end
# File lib/puppet/functions/hocon_data.rb 27 def hocon_data(options, context) 28 path = options['path'] 29 context.cached_file_data(path) do |content| 30 begin 31 Hocon.parse(content) 32 rescue Hocon::ConfigError => ex 33 raise Puppet::DataBinding::LookupError, _("Unable to parse (%{path}): %{message}") % { path: path, message: ex.message } 34 end 35 end 36 end
# File lib/puppet/provider/package/dpkg.rb 176 def hold 177 Tempfile.open('puppet_dpkg_set_selection') do |tmpfile| 178 tmpfile.write("#{@resource[:name]} hold\n") 179 tmpfile.flush 180 execute([:dpkg, "--set-selections"], :failonfail => false, :combine => false, :stdinfile => tmpfile.path.to_s) 181 end 182 end
# File lib/puppet/provider/user/windows_adsi.rb 128 def home 129 user['HomeDirectory'] 130 end
# File lib/puppet/provider/user/windows_adsi.rb 132 def home=(value) 133 user['HomeDirectory'] = value 134 end
# File lib/puppet/face/help.rb 205 def horribly_extract_summary_from(appname) 206 help = Puppet::Application[appname].help.split("\n") 207 # Now we find the line with our summary, extract it, and return it. This 208 # depends on the implementation coincidence of how our pages are 209 # formatted. If we can't match the pattern we expect we return the empty 210 # string to ensure we don't blow up in the summary. --daniel 2011-04-11 211 while line = help.shift do #rubocop:disable Lint/AssignmentInCondition 212 md = /^puppet-#{appname}\([^\)]+\) -- (.*)$/.match(line) 213 if md 214 return md[1] 215 end 216 end 217 return '' 218 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 21 def id2name(id) 22 if Puppet::Util::Windows::SID.valid_sid?(id) 23 Puppet::Util::Windows::SID.sid_to_name(id) 24 else 25 id 26 end 27 end
# File lib/puppet/provider/package/sun.rb 126 def if_have_value(prefix, value) 127 if value 128 [prefix, value] 129 else 130 [] 131 end 132 end
# File lib/puppet/functions/import.rb 4 def import(*args) 5 raise Puppet::Pops::SemanticError.new(Puppet::Pops::Issues::DISCONTINUED_IMPORT) 6 end
# File lib/puppet/functions/include.rb 39 def include(scope, *classes) 40 if Puppet[:tasks] 41 raise Puppet::ParseErrorWithIssue.from_issue_and_stack( 42 Puppet::Pops::Issues::CATALOG_OPERATION_NOT_SUPPORTED_WHEN_SCRIPTING, 43 {:operation => 'include'}) 44 end 45 46 classes = scope.transform_and_assert_classnames(classes.flatten) 47 result = classes.map {|name| Puppet::Pops::Types::TypeFactory.host_class(name) } 48 scope.compiler.evaluate_classes(classes, scope, false) 49 50 # Result is an Array[Class, 1, n] which allows chaining other operations 51 result 52 end
# File lib/puppet/functions/index.rb 134 def index_Enumerable_1(enumerable) 135 enum = Puppet::Pops::Types::Iterable.asserted_iterable(self, enumerable) 136 if enum.hash_style? 137 enum.each { |entry| return entry[0] if yield(entry[1]) } 138 else 139 enum.each_with_index { |e, i| return i if yield(e) } 140 end 141 nil 142 end
# File lib/puppet/functions/index.rb 144 def index_Enumerable_2(enumerable) 145 enum = Puppet::Pops::Types::Iterable.asserted_iterable(self, enumerable) 146 if enum.hash_style? 147 enum.each { |entry| return entry[0] if yield(*entry) } 148 else 149 enum.each_with_index { |e, i| return i if yield(i, e) } 150 end 151 nil 152 end
# File lib/puppet/functions/index.rb 124 def index_Hash_1(hash) 125 hash.each_pair { |x, y| return x if yield(y) } 126 nil 127 end
# File lib/puppet/functions/index.rb 129 def index_Hash_2(hash) 130 hash.each_pair.any? { |x, y| return x if yield(x, y) } 131 nil 132 end
# File lib/puppet/functions/index.rb 158 def index_value(enumerable, match) 159 enum = Puppet::Pops::Types::Iterable.asserted_iterable(self, enumerable) 160 if enum.hash_style? 161 enum.each { |entry| return entry[0] if entry[1] == match } 162 else 163 enum.each_with_index { |e, i| return i if e == match } 164 end 165 nil 166 end
# File lib/puppet/functions/info.rb 11 def info(scope, *values) 12 Puppet::Util::Log.log_func(scope, :info, values) 13 end
Get info on a package, optionally specifying a device.
# File lib/puppet/provider/package/sun.rb 64 def info2hash(device = nil) 65 args = ['-l'] 66 args << '-d' << device if device 67 args << @resource[:name] 68 begin 69 pkgs = self.class.parse_pkginfo(pkginfo(*args)) 70 errmsg = case pkgs.size 71 when 0 72 'No message' 73 when 1 74 pkgs[0]['ERROR'] 75 end 76 return self.class.namemap(pkgs[0]) if errmsg.nil? 77 # according to commit 41356a7 some errors do not raise an exception 78 # so even though pkginfo passed, we have to check the actual output 79 raise Puppet::Error, _("Unable to get information about package %{name} because of: %{errmsg}") % { name: @resource[:name], errmsg: errmsg } 80 rescue Puppet::ExecutionFailure 81 return {:ensure => :absent} 82 end 83 end
Where is our init script?
# File lib/puppet/provider/service/init.rb 119 def initscript 120 @initscript ||= self.search(@resource[:name]) 121 end
# File lib/puppet/functions/inline_epp.rb 57 def inline_epp(scope, template, parameters = nil) 58 Puppet::Pops::Evaluator::EppEvaluator.inline_epp(scope, template, parameters) 59 end
# File lib/puppet/functions/regsubst.rb 97 def inner_regsubst(target, re, replacement, op) 98 target.respond_to?(op) ? target.send(op, re, replacement) : target.collect { |e| e.send(op, re, replacement) } 99 end
# File lib/puppet/provider/package/aix.rb 92 def install(useversion = true) 93 source = @resource[:source] 94 unless source 95 self.fail _("A directory is required which will be used to find packages") 96 end 97 98 pkg = @resource[:name] 99 100 pkg += " #{@resource.should(:ensure)}" if (! @resource.should(:ensure).is_a? Symbol) and useversion 101 102 output = installp "-acgwXY", "-d", source, pkg 103 104 # If the package is superseded, it means we're trying to downgrade and we 105 # can't do that. 106 if output =~ /^#{Regexp.escape(@resource[:name])}\s+.*\s+Already superseded by.*$/ 107 self.fail _("aix package provider is unable to downgrade packages") 108 end 109 110 pkg_info = query 111 if pkg_info && [:broken, :inconsistent].include?(pkg_info[:status]) 112 self.fail _("Package '%{name}' is in a %{status} state and requires manual intervention") % { name: @resource[:name], status: pkg_info[:status] } 113 end 114 end
# File lib/puppet/provider/package/pacman.rb 225 def install_from_file 226 source = @resource[:source] 227 begin 228 source_uri = URI.parse source 229 rescue => detail 230 self.fail Puppet::Error, _("Invalid source '%{source}': %{detail}") % { source: source, detail: detail }, detail 231 end 232 233 source = case source_uri.scheme 234 when nil then source 235 when /https?/i then source 236 when /ftp/i then source 237 when /file/i then source_uri.path 238 when /puppet/i 239 fail _("puppet:// URL is not supported by pacman") 240 else 241 fail _("Source %{source} is not supported by pacman") % { source: source } 242 end 243 pacman "--noconfirm", "--noprogressbar", "-S" 244 pacman "--noconfirm", "--noprogressbar", "-U", source 245 end
# File lib/puppet/provider/package/pacman.rb 247 def install_from_repo 248 resource_name = @resource[:name] 249 250 # Refuse to install if not allowing virtual packages and the resource is a group 251 fail(_("Refusing to install package group %{resource_name}, because allow_virtual is false.") % { resource_name: resource_name }) if self.class.group?(resource_name) && !@resource.allow_virtual? 252 253 cmd = %w{--noconfirm --needed --noprogressbar} 254 cmd += install_options if @resource[:install_options] 255 cmd << "-S" << resource_name 256 257 if self.class.yaourt? 258 yaourt(*cmd) 259 else 260 pacman(*cmd) 261 end 262 end
# File lib/puppet/provider/package/apt.rb 226 def install_options 227 join_options(@resource[:install_options]) 228 end
# File lib/puppet/provider/package/apt.rb 230 def insync?(is) 231 # this is called after the generic version matching logic (insync? for the 232 # type), so we only get here if should != is 233 234 return false unless is && is != :absent 235 236 #if 'should' is a range and 'is' a debian version we should check if 'should' includes 'is' 237 should = @resource[:ensure] 238 239 return false unless is.is_a?(String) && should.is_a?(String) 240 241 begin 242 should_range = VersionRange.parse(should, DebianVersion) 243 rescue VersionRange::ValidationFailure, DebianVersion::ValidationFailure 244 Puppet.debug("Cannot parse #{should} as a debian version range") 245 return false 246 end 247 248 begin 249 is_version = DebianVersion.parse(is) 250 rescue DebianVersion::ValidationFailure 251 Puppet.debug("Cannot parse #{is} as a debian version") 252 return false 253 end 254 should_range.include?(is_version) 255 end
# File lib/puppet/network/formats.rb 8 def intern(klass, text) 9 data = MessagePack.unpack(text) 10 return data if data.is_a?(klass) 11 klass.from_data_hash(data) 12 end
# File lib/puppet/network/formats.rb 14 def intern_multiple(klass, text) 15 MessagePack.unpack(text).collect do |data| 16 klass.from_data_hash(data) 17 end 18 end
# File lib/puppet/functions/getvar.rb 59 def invalid_variable_error(navigation, default_value=nil, &block) 60 _("The given string does not start with a valid variable name") 61 end
# File lib/puppet/functions/defined.rb 109 def is_defined(scope, *vals) 110 vals.any? do |val| 111 case val 112 when String 113 if val =~ /^\$(.+)$/ 114 scope.exist?($1) 115 else 116 case val 117 when '' 118 next nil 119 when 'main' 120 # Find the main class (known as ''), it does not have to be in the catalog 121 Puppet::Pops::Evaluator::Runtime3ResourceSupport.find_main_class(scope) 122 else 123 # Find a resource type, definition or class definition 124 Puppet::Pops::Evaluator::Runtime3ResourceSupport.find_resource_type_or_class(scope, val) 125 end 126 end 127 when Puppet::Resource 128 # Find instance of given resource type and title that is in the catalog 129 scope.compiler.findresource(val.resource_type, val.title) 130 131 when Puppet::Pops::Types::PResourceType 132 raise ArgumentError, _('The given resource type is a reference to all kind of types') if val.type_name.nil? 133 type = Puppet::Pops::Evaluator::Runtime3ResourceSupport.find_resource_type(scope, val.type_name) 134 val.title.nil? ? type : scope.compiler.findresource(type, val.title) 135 136 when Puppet::Pops::Types::PClassType 137 raise ArgumentError, _('The given class type is a reference to all classes') if val.class_name.nil? 138 scope.compiler.findresource(:class, val.class_name) 139 140 when Puppet::Pops::Types::PTypeType 141 case val.type 142 when Puppet::Pops::Types::PResourceType 143 # It is most reasonable to take Type[File] and Type[File[foo]] to mean the same as if not wrapped in a Type 144 # Since the difference between File and File[foo] already captures the distinction of type vs instance. 145 is_defined(scope, val.type) 146 147 when Puppet::Pops::Types::PClassType 148 # Interpreted as asking if a class (and nothing else) is defined without having to be included in the catalog 149 # (this is the same as asking for just the class' name, but with the added certainty that it cannot be a defined type. 150 # 151 raise ArgumentError, _('The given class type is a reference to all classes') if val.type.class_name.nil? 152 Puppet::Pops::Evaluator::Runtime3ResourceSupport.find_hostclass(scope, val.type.class_name) 153 end 154 else 155 raise ArgumentError, _("Invalid argument of type '%{value_class}' to 'defined'") % { value_class: val.class } 156 end 157 end 158 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 232 def is_face_app?(appname) 233 clazz = Puppet::Application.find(appname) 234 235 clazz.ancestors.include?(Puppet::Application::FaceBase) 236 end
# File lib/puppet/provider/user/user_role_add.rb 81 def is_role? 82 user_attributes and user_attributes[:type] == "role" 83 end
# File lib/puppet/provider/service/upstart.rb 195 def is_upstart?(script = initscript) 196 Puppet::FileSystem.exist?(script) && script.match(/\/etc\/init\/\S+\.conf/) 197 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 386 def iterations=(value) 387 if (Puppet::Util::Package.versioncmp(self.class.get_os_version, '10.7') > 0) 388 assert_full_pbkdf2_password 389 390 sleep 3 391 flush_dscl_cache 392 users_plist = get_users_plist(@resource.name) 393 shadow_hash_data = get_shadow_hash_data(users_plist) 394 set_salted_pbkdf2(users_plist, shadow_hash_data, 'iterations', value) 395 flush_dscl_cache 396 end 397 end
# File lib/puppet/functions/tree_each.rb 187 def iterator(enum, options) 188 if depth_first?(options) 189 Puppet::Pops::Types::Iterable::DepthFirstTreeIterator.new(enum, options) 190 else 191 Puppet::Pops::Types::Iterable::BreadthFirstTreeIterator.new(enum, options) 192 end 193 end
# File lib/puppet/functions/join.rb 53 def join(arg, delimiter = '', puppet_formatting = false) 54 arg.join(delimiter) 55 end
# File lib/puppet/network/formats.rb 147 def json 148 @json ||= Puppet::Network::FormatHandler.format(:json) 149 end
# File lib/puppet/functions/json_data.rb 18 def json_data(options, context) 19 path = options['path'] 20 context.cached_file_data(path) do |content| 21 begin 22 Puppet::Util::Json.load(content) 23 rescue Puppet::Util::Json::ParseError => ex 24 # Filename not included in message, so we add it here. 25 raise Puppet::DataBinding::LookupError, "Unable to parse (%{path}): %{message}" % { path: path, message: ex.message } 26 end 27 end 28 end
# File lib/puppet/functions/keys.rb 22 def keys(hsh) 23 hsh.keys 24 end
# File lib/puppet/provider/user/user_role_add.rb 164 def keys=(keys_hash) 165 run([command(:modify)] + build_keys_cmd(keys_hash) << @resource[:name], "modify attribute key pairs") 166 end
# File lib/puppet/provider/package/aix.rb 150 def latest 151 upd = latest_info 152 153 unless upd.nil? 154 return "#{upd[:version]}" 155 else 156 raise Puppet::DevError, _("Tried to get latest on a missing package") if properties[:ensure] == :absent 157 158 return properties[:ensure] 159 end 160 end
Return a list of applications that are not simply just stubs for Faces.
# File lib/puppet/face/help.rb 149 def legacy_applications 150 Puppet::Application.available_application_names.reject do |appname| 151 (is_face_app?(appname)) or (exclude_from_docs?(appname)) 152 end.sort 153 end
# File lib/puppet/functions/strftime.rb 205 def legacy_strftime(format, timezone = nil) 206 file, line = Puppet::Pops::PuppetStack.top_of_stack 207 Puppet.warn_once('deprecations', 'legacy#strftime', 208 _('The argument signature (String format, [String timezone]) is deprecated for #strftime. See #strftime documentation and Timespan type for more info'), 209 file, line) 210 Puppet::Pops::Time::Timestamp.format_time(format, Time.now.utc, timezone) 211 end
# File lib/puppet/functions/lest.rb 48 def lest(arg) 49 if arg.nil? 50 yield() 51 else 52 arg 53 end 54 end
Prepare a module object for print in a tree view. Each node in the tree must be a Hash in the following format:
{ :text => "puppetlabs-mysql (v1.0.0)" }
The value of a module's :text is affected by three (3) factors: the format of the tree, its dependency status, and the location in the modulepath relative to its parent.
Returns a Hash
# File lib/puppet/face/module/list.rb 240 def list_build_node(mod, parent, params) 241 str = '' 242 str << (mod.forge_name ? mod.forge_name.tr('/', '-') : mod.name) 243 str << ' (' + colorize(:cyan, mod.version ? "v#{mod.version}" : '???') + ')' 244 245 unless File.dirname(mod.path) == params[:path] 246 str << " [#{File.dirname(mod.path)}]" 247 end 248 249 if @unmet_deps[:version_mismatch].include?(mod.forge_name) 250 if params[:label_invalid] 251 str << ' ' + colorize(:red, _('invalid')) 252 elsif parent.respond_to?(:forge_name) 253 unmet_parent = @unmet_deps[:version_mismatch][mod.forge_name][:parent] 254 if (unmet_parent[:name] == parent.forge_name && 255 unmet_parent[:version] == "v#{parent.version}") 256 str << ' ' + colorize(:red, _('invalid')) 257 end 258 end 259 end 260 261 { :text => str } 262 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/puppetlabs/code/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 205 def list_build_tree(list, ancestors=[], parent=nil, params={}) 206 list.map do |mod| 207 next if @seen[(mod.forge_name or mod.name)] 208 node = list_build_node(mod, parent, params) 209 @seen[(mod.forge_name or mod.name)] = true 210 211 unless ancestors.include?(mod) 212 node[:dependencies] ||= [] 213 missing_deps = mod.unmet_dependencies.select do |dep| 214 dep[:reason] == :missing 215 end 216 missing_deps.map do |mis_mod| 217 str = "#{colorize(:bg_red, _('UNMET DEPENDENCY'))} #{mis_mod[:name].tr('/', '-')} " 218 str << "(#{colorize(:cyan, mis_mod[:version_constraint])})" 219 node[:dependencies] << { :text => str } 220 end 221 node[:dependencies] += list_build_tree(mod.dependencies_as_modules, 222 ancestors + [mod], mod, params) 223 end 224 225 node 226 end.compact 227 end
# File lib/puppet/provider/package/pip.rb 336 def list_extra_flags(command_version) 337 klass = self.class 338 if klass.compare_pip_versions(command_version, '20.2.4') == 1 && 339 klass.compare_pip_versions(command_version, '21.1') == -1 340 '--use-deprecated=legacy-resolver' 341 end 342 end
# File lib/puppet/functions/eyaml_lookup_key.rb 45 def load_data_hash(options, context) 46 path = options['path'] 47 context.cached_file_data(path) do |content| 48 begin 49 data = Puppet::Util::Yaml.safe_load(content, [Symbol], path) 50 if data.is_a?(Hash) 51 Puppet::Pops::Lookup::HieraConfig.symkeys_to_string(data) 52 else 53 msg = _("%{path}: file does not contain a valid yaml hash") % { path: path } 54 raise Puppet::DataBinding::LookupError, msg if Puppet[:strict] == :error && data != false 55 Puppet.warning(msg) 56 {} 57 end 58 rescue Puppet::Util::Yaml::YamlLoadError => ex 59 # YamlLoadErrors include the absolute path to the file, so no need to add that 60 raise Puppet::DataBinding::LookupError, _("Unable to parse %{message}") % { message: ex.message } 61 end 62 end 63 end
# File lib/puppet/face/help.rb 121 def load_face_help(facename, actionname, version) 122 face = Puppet::Face[facename.to_sym, version] 123 if actionname 124 action = face.get_action(actionname.to_sym) 125 if ! action 126 fail ArgumentError, _("Unable to load action %{actionname} from %{face}") % { actionname: actionname, face: face } 127 end 128 end 129 130 [face, action] 131 end
# File lib/puppet/provider/user/useradd.rb 95 def local_username 96 finduser(:uid, @resource.uid) 97 end
# File lib/puppet/provider/user/useradd.rb 118 def localcomment 119 user = finduser(:account, resource[:name]) 120 user[:gecos] 121 end
# File lib/puppet/provider/group/groupadd.rb 31 def localgid 32 group = findgroup(:group_name, resource[:name]) 33 return group[:gid] if group 34 false 35 end
# File lib/puppet/provider/user/useradd.rb 123 def localgroups 124 @groups_of ||= {} 125 group_file = '/etc/group' 126 user = resource[:name] 127 128 return @groups_of[user] if @groups_of[user] 129 130 @groups_of[user] = [] 131 132 unless Puppet::FileSystem.exist?(group_file) 133 raise Puppet::Error.new("Forcelocal set for user resource '#{user}', but #{group_file} does not exist") 134 end 135 136 Puppet::FileSystem.each_line(group_file) do |line| 137 data = line.chomp.split(':') 138 if !data.empty? && data.last.split(',').include?(user) 139 @groups_of[user] << data.first 140 end 141 end 142 143 @groups_of[user] 144 end
# File lib/puppet/provider/user/useradd.rb 99 def localuid 100 user = finduser(:account, resource[:name]) 101 return user[:uid] if user 102 false 103 end
# File lib/puppet/provider/user/openbsd.rb 65 def loginclass=(value) 66 set("loginclass", value) 67 end
# File lib/puppet/provider/service/windows.rb 140 def logonaccount 141 return unless Puppet::Util::Windows::Service.exists?(@resource[:name]) 142 Puppet::Util::Windows::Service.logon_account(@resource[:name]) 143 end
# File lib/puppet/provider/service/windows.rb 145 def logonaccount=(value) 146 validate_logon_credentials 147 Puppet::Util::Windows::Service.set_startup_configuration(@resource[:name], options: {logon_account: value, logon_password: @resource[:logonpassword]}) 148 restart if @resource[:ensure] == :running && [:running, :paused].include?(status) 149 end
# File lib/puppet/provider/service/windows.rb 131 def logonaccount_insync?(current) 132 @normalized_logon_account ||= normalize_logonaccount 133 @resource[:logonaccount] = @normalized_logon_account 134 135 insync = @resource[:logonaccount] == current 136 self.logonpassword = @resource[:logonpassword] if insync 137 insync 138 end
# File lib/puppet/provider/service/windows.rb 151 def logonpassword=(value) 152 validate_logon_credentials 153 Puppet::Util::Windows::Service.set_startup_configuration(@resource[:name], options: {logon_password: value}) 154 end
# File lib/puppet/functions/lookup.rb 189 def lookup_1(scope, name, value_type=nil, merge=nil) 190 do_lookup(scope, name, value_type, nil, false, {}, {}, merge) 191 end
# File lib/puppet/functions/lookup.rb 193 def lookup_2(scope, name, value_type, merge, default_value) 194 do_lookup(scope, name, value_type, default_value, true, {}, {}, merge) 195 end
# File lib/puppet/functions/lookup.rb 197 def lookup_3(scope, name, value_type=nil, merge=nil, &block) 198 do_lookup(scope, name, value_type, nil, false, {}, {}, merge, &block) 199 end
# File lib/puppet/functions/lookup.rb 201 def lookup_4(scope, options_hash, &block) 202 do_lookup(scope, options_hash['name'], *hash_args(options_hash), &block) 203 end
# File lib/puppet/functions/lookup.rb 205 def lookup_5(scope, name, options_hash, &block) 206 do_lookup(scope, name, *hash_args(options_hash), &block) 207 end
# File lib/puppet/provider/user/user_role_add.rb 140 def managed_attributes 141 [:name, :type, :roles, :auths, :profiles, :project] 142 end
# File lib/puppet/provider/service/windows.rb 31 def manual_start 32 Puppet::Util::Windows::Service.set_startup_configuration(@resource[:name], options: {startup_type: :SERVICE_DEMAND_START}) 33 rescue => detail 34 raise Puppet::Error.new(_("Cannot enable %{resource_name} for manual start, error was: %{detail}") % { resource_name: @resource[:name], detail: detail }, detail ) 35 end
# File lib/puppet/functions/map.rb 108 def map_Enumerable_1(enumerable) 109 result = [] 110 enum = Puppet::Pops::Types::Iterable.asserted_iterable(self, enumerable) 111 begin 112 loop { result << yield(enum.next) } 113 rescue StopIteration 114 end 115 result 116 end
# File lib/puppet/functions/map.rb 118 def map_Enumerable_2(enumerable) 119 enum = Puppet::Pops::Types::Iterable.asserted_iterable(self, enumerable) 120 if enum.hash_style? 121 enum.map { |entry| yield(*entry) } 122 else 123 result = [] 124 begin 125 index = 0 126 loop do 127 result << yield(index, enum.next) 128 index = index + 1 129 end 130 rescue StopIteration 131 end 132 133 result 134 end 135 end
# File lib/puppet/functions/map.rb 90 def map_Hash_1(hash) 91 result = [] 92 begin 93 hash.map {|x, y| result << yield([x, y]) } 94 rescue StopIteration 95 end 96 result 97 end
# File lib/puppet/functions/map.rb 99 def map_Hash_2(hash) 100 result = [] 101 begin 102 hash.map {|x, y| result << yield(x, y) } 103 rescue StopIteration 104 end 105 result 106 end
# File lib/puppet/provider/package/apt.rb 58 def mark 59 @property_flush[:mark] 60 end
# File lib/puppet/provider/package/apt.rb 62 def mark=(value) 63 @property_flush[:mark] = value 64 end
Configure discovered resources to be purged.
# File lib/puppet/type/file.rb 570 def mark_children_for_purging(children) 571 children.each do |name, child| 572 next if child[:source] 573 child[:ensure] = :absent 574 end 575 end
# File lib/puppet/provider/service/systemd.rb 166 def mask 167 disable if exist? 168 systemctl_change_enable(:mask) 169 end
Matches given string against given pattern and returns an Array with matches. @param string [String] the string to match @param pattern [String, Regexp, Puppet::Pops::Types::PPatternType
, Puppet::Pops::PRegexpType, Array] the pattern @return [Array<String>] matches where first match is the entire match, and index 1-n are captures from left to right
# File lib/puppet/functions/match.rb 64 def match(string, pattern) 65 @@match_visitor.visit_this_1(self, pattern, string) 66 end
Returns the first matching entry
# File lib/puppet/functions/match.rb 118 def match_Array(array, s) 119 result = nil 120 array.flatten.find {|entry| result = match(s, entry) } 121 result 122 end
# File lib/puppet/functions/match.rb 80 def match_Object(obj, s) 81 msg = _("match() expects pattern of T, where T is String, Regexp, Regexp[r], Pattern[p], or Array[T]. Got %{klass}") % { klass: obj.class } 82 raise ArgumentError, msg 83 end
# File lib/puppet/functions/match.rb 109 def match_PPatternType(pattern_t, s) 110 # Since we want the actual match result (not just a boolean), an iteration over 111 # Pattern's regular expressions is needed. (They are of PRegexpType) 112 result = nil 113 pattern_t.patterns.find {|pattern| result = match(s, pattern) } 114 result 115 end
# File lib/puppet/functions/match.rb 104 def match_PRegexpType(regexp_t, s) 105 raise ArgumentError, _("Given Regexp Type has no regular expression") unless regexp_t.pattern 106 do_match(s, regexp_t.regexp) 107 end
# File lib/puppet/functions/match.rb 93 def match_PTypeAliasType(alias_t, s) 94 match(s, alias_t.resolved_type) 95 end
# File lib/puppet/functions/match.rb 97 def match_PVariantType(var_t, s) 98 # Find first matching type (or error out if one of the variants is not acceptable) 99 result = nil 100 var_t.types.find {|t| result = match(s, t) } 101 result 102 end
# File lib/puppet/functions/match.rb 89 def match_Regexp(regexp, s) 90 do_match(s, regexp) 91 end
# File lib/puppet/functions/match.rb 85 def match_String(pattern_string, s) 86 do_match(s, Regexp.new(pattern_string)) 87 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 321 def matches?(path) 322 return true unless self[:matches] 323 324 basename = File.basename(path) 325 flags = File::FNM_DOTMATCH | File::FNM_PATHNAME 326 if self[:matches].find {|pattern| File.fnmatch(pattern, basename, flags) } 327 return true 328 else 329 debug "No specified patterns match #{path}, not tidying" 330 return false 331 end 332 end
Helper that encapsulates the clear + svcadm [enable|disable] logic in one place. Makes it easy to test things out and also cleans up flush's code.
# File lib/puppet/provider/service/smf.rb 234 def maybe_clear_service_then_svcadm(cur_state, subcmd, flags) 235 # If the cur_state is maint or degraded, then we need to clear the service 236 # before we enable or disable it. 237 adm('clear', self.service_fmri) if [:maintenance, :degraded].include?(cur_state) 238 adm(subcmd, flags, self.service_fmri) 239 end
# File lib/puppet/provider/group/windows_adsi.rb 60 def member_valid?(user_name) 61 ! Puppet::Util::Windows::SID.name_to_principal(user_name).nil? 62 end
# File lib/puppet/provider/group/windows_adsi.rb 68 def members 69 @members ||= Puppet::Util::Windows::ADSI::Group.name_sid_hash(group.members, true) 70 71 # @members.keys returns an array of SIDs. We need to convert those SIDs into 72 # names so that `puppet resource` prints the right output. 73 members_to_s(@members.keys).split(',') 74 end
# File lib/puppet/provider/group/windows_adsi.rb 76 def members=(members) 77 group.set_members(members, @resource[:auth_membership]) 78 end
We could add this to the top-level members property since the implementation is not platform-specific; however, it is best to do it this way so that we do not accidentally break something. This is ok for now, since we do plan on moving this and the auth_membership management over to the property class in a future Puppet
release.
# File lib/puppet/provider/group/aix.rb 96 def members_insync?(current, should) 97 current.sort == @resource.parameter(:members).actual_should(current, should) 98 end
# File lib/puppet/provider/group/groupadd.rb 121 def members_to_s(current) 122 return '' if current.nil? || !current.kind_of?(Array) 123 current.join(',') 124 end
This method will merge in a given value using dscl
# File lib/puppet/provider/user/directoryservice.rb 485 def merge_attribute_with_dscl(path, username, keyname, value) 486 set_attribute_with_dscl('-merge', path, username, keyname, value) 487 end
# File lib/puppet/functions/hiera_array.rb 78 def merge_type 79 :unique 80 end
Adds methods to a singleton_class
# File lib/puppet/util/metaid.rb 7 def meta_def(name, &blk) 8 meta_eval { define_method name, &blk } 9 end
# File lib/puppet/util/metaid.rb 4 def meta_eval(&blk); singleton_class.instance_eval(&blk); end
Remove singleton_class
methods.
# File lib/puppet/util/metaid.rb 12 def meta_undef(name, &blk) 13 meta_eval { remove_method name } 14 end
# File lib/puppet/functions/hocon_data.rb 38 def missing_path(options, context) 39 "one of 'path', 'paths' 'glob', 'globs' or 'mapped_paths' must be declared in hiera.yaml when using this data_hash function" 40 end
Make a file resource to remove a given file.
# File lib/puppet/type/tidy.rb 243 def mkfile(path) 244 # Force deletion, so directories actually get deleted. 245 parameters = { 246 :path => path, :backup => self[:backup], 247 :ensure => :absent, :force => true 248 } 249 250 parameters[:noop] = self[:noop] unless self[:noop].nil? 251 252 Puppet::Type.type(:file).new(parameters) 253 end
# File lib/puppet/provider/file/posix.rb 126 def mode 127 stat = resource.stat 128 if stat 129 return (stat.mode & 007777).to_s(8).rjust(4, '0') 130 else 131 return :absent 132 end 133 end
# File lib/puppet/provider/file/posix.rb 135 def mode=(value) 136 begin 137 File.chmod(value.to_i(8), resource[:path]) 138 rescue => detail 139 error = Puppet::Error.new(_("failed to set mode %{mode} on %{path}: %{message}") % { mode: mode, path: resource[:path], message: detail.message }) 140 error.set_backtrace detail.backtrace 141 raise error 142 end 143 end
# File lib/puppet/provider/group/groupadd.rb 85 def modifycmd(param, value) 86 if @resource.forcelocal? || @resource[:members] 87 cmd = [command(:localmodify)] 88 @custom_environment = Puppet::Util::Libuser.getenv 89 else 90 cmd = [command(:modify)] 91 end 92 93 if param == :members 94 validate_members(value) 95 value = members_to_s(value) 96 purge_members if @resource[:auth_membership] && !members.empty? 97 end 98 99 cmd << flag(param) << value 100 # TODO the group type only really manages gid, so there are currently no 101 # tests for this behavior 102 cmd += check_allow_dup if param == :gid 103 cmd << @resource[:name] 104 105 cmd 106 end
# File lib/puppet/functions/module_directory.rb 34 def module_directory(scope, *names) 35 names.each do |module_name| 36 found = scope.compiler.environment.module(module_name) 37 return found.path if found 38 end 39 nil 40 end
# File lib/puppet/functions/module_directory.rb 30 def module_directory_array(scope, names) 31 module_directory(scope, *names) 32 end
munge the windows group permissions if the user or group are set to SYSTEM
when SYSTEM user is the group or user and the resoure is not managing them then treat the resource as insync if System has FullControl access.
@param [String] current - the current mode returned by the resource @param [String] should - what the mode should be
@return [String, nil] munged mode or nil if the resource should be out of sync
# File lib/puppet/provider/file/windows.rb 100 def munge_windows_system_group(current, should) 101 [ 102 { 103 'type' => 'group', 104 'resource' => resource[:group], 105 'set_to_user' => group, 106 'fullcontrol' => "070".to_i(8), 107 'remove_mask' => "707".to_i(8), 108 'should_mask' => (should[0].to_i(8) & "070".to_i(8)), 109 }, 110 { 111 'type' => 'owner', 112 'resource' => resource[:owner], 113 'set_to_user' => owner, 114 'fullcontrol' => "700".to_i(8), 115 'remove_mask' => "077".to_i(8), 116 'should_mask' => (should[0].to_i(8) & "700".to_i(8)), 117 } 118 ].each do |mode_part| 119 if mode_part['resource'].nil? && (mode_part['set_to_user'] == Puppet::Util::Windows::SID::LocalSystem) 120 if (current.to_i(8) & mode_part['fullcontrol']) == mode_part['fullcontrol'] 121 # Since the group is LocalSystem, and the permissions are FullControl, 122 # replace the value returned with the value expected. This will treat 123 # this specific situation as "insync" 124 current = ( (current.to_i(8) & mode_part['remove_mask']) | mode_part['should_mask'] ).to_s(8).rjust(4, '0') 125 else 126 # If the SYSTEM account does _not_ have FullControl in this scenario, we should 127 # force the resource out of sync no matter what. 128 #TRANSLATORS 'SYSTEM' is a Windows name and should not be translated 129 Puppet.debug { _("%{resource_name}: %{mode_part_type} set to SYSTEM. SYSTEM permissions cannot be set below FullControl ('7')") % { resource_name: resource[:name], mode_part_type: mode_part['type']} } 130 return nil 131 end 132 end 133 end 134 current 135 end
# File lib/puppet/gettext/stubs.rb 8 def n_(*args, &block) 9 plural = args[2] == 1 ? args[0] : args[1] 10 block ? block.call : plural 11 end
# File lib/puppet/provider/file/posix.rb 56 def name2gid(value) 57 Integer(value) rescue gid(value) || false 58 end
Determine if the account is valid, and if so, return the UID
# File lib/puppet/provider/file/windows.rb 15 def name2id(value) 16 Puppet::Util::Windows::SID.name_to_sid(value) 17 end
Determine if the user is valid, and if so, return the UID
# File lib/puppet/provider/file/posix.rb 35 def name2uid(value) 36 Integer(value) rescue uid(value) || false 37 end
# File lib/puppet/functions/new.rb 998 def new_function_for_type(t) 999 @new_function_cache ||= {} 1000 1001 unless @new_function_cache.key?(t) 1002 @new_function_cache[t] = t.new_function.new(nil, loader) 1003 end 1004 1005 @new_function_cache[t] 1006 end
# File lib/puppet/functions/new.rb 992 def new_instance(scope, t, *args) 993 return args[0] if args.size == 1 && !t.is_a?(Puppet::Pops::Types::PInitType) && t.instance?(args[0]) 994 result = assert_type(t, new_function_for_type(t).call(scope, *args)) 995 return block_given? ? yield(result) : result 996 end
Create a new file or directory object as a child to the current object.
# File lib/puppet/type/file.rb 579 def newchild(path) 580 full_path = ::File.join(self[:path], path) 581 582 # Add some new values to our original arguments -- these are the ones 583 # set at initialization. We specifically want to exclude any param 584 # values set by the :source property or any default values. 585 # LAK:NOTE This is kind of silly, because the whole point here is that 586 # the values set at initialization should live as long as the resource 587 # but values set by default or by :source should only live for the transaction 588 # or so. Unfortunately, we don't have a straightforward way to manage 589 # the different lifetimes of this data, so we kludge it like this. 590 # The right-side hash wins in the merge. 591 options = @original_parameters.merge(:path => full_path).reject { |param, value| value.nil? } 592 593 # These should never be passed to our children. 594 [:parent, :ensure, :recurse, :recurselimit, :max_files, :target, :alias, :source].each do |param| 595 options.delete(param) if options.include?(param) 596 end 597 598 self.class.new(options) 599 end
# File lib/puppet/functions/next.rb 11 def next_impl(value = nil) 12 file, line = Puppet::Pops::PuppetStack.top_of_stack 13 exc = Puppet::Pops::Evaluator::Next.new(value, file, line) 14 raise exc 15 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 504 def next_system_id(min_id=20) 505 dscl_output = dscl '.', '-list', '/Users', 'uid' 506 # We're ok with throwing away negative uids here. Also, remove nil values. 507 user_ids = dscl_output.split.compact.collect { |l| l.to_i if l =~ /^\d+$/ } 508 ids = user_ids.compact!.sort! { |a,b| a.to_f <=> b.to_f } 509 # We're just looking for an unused id in our sorted array. 510 ids.each_index do |i| 511 next_id = ids[i] + 1 512 return next_id if ids[i+1] != next_id and next_id >= min_id 513 end 514 end
# File lib/puppet/provider/service/windows.rb 158 def normalize_logonaccount 159 logon_account = @resource[:logonaccount].sub(/^\.\\/, "#{Puppet::Util::Windows::ADSI.computer_name}\\") 160 return 'LocalSystem' if Puppet::Util::Windows::User::localsystem?(logon_account) 161 162 @logonaccount_information ||= Puppet::Util::Windows::SID.name_to_principal(logon_account) 163 return logon_account unless @logonaccount_information 164 return ".\\#{@logonaccount_information.account}" if @logonaccount_information.domain == Puppet::Util::Windows::ADSI.computer_name 165 @logonaccount_information.domain_account 166 end
# File lib/puppet/functions/notice.rb 11 def notice(scope, *values) 12 Puppet::Util::Log.log_func(scope, :notice, values) 13 end
For compatibility reasons - return false rather than error on floats and integers (Yes, it is strange)
# File lib/puppet/functions/empty.rb 64 def numeric_empty(num) 65 deprecation_warning_for('Numeric') 66 false 67 end
Mix of data types - while only some compares are actually bad it will deprecate the entire call
# File lib/puppet/functions/max.rb 163 def on_any(*args) 164 assert_arg_count(args) 165 args.max do |a, b| 166 as = a.to_s 167 bs = b.to_s 168 if as =~ %r{\A^-?\d+([._eE]\d+)?\z} && bs =~ %r{\A-?\d+([._eE]\d+)?\z} 169 Puppet.warn_once('deprecations', 'max_function_numeric_coerce_string', 170 _("The max() function's auto conversion of String to Numeric is deprecated - change to convert input before calling, or use lambda")) 171 a.to_f <=> b.to_f 172 else 173 Puppet.warn_once('deprecations', 'max_function_string_coerce_any', 174 _("The max() function's auto conversion of Any to String is deprecated - change to convert input before calling, or use lambda")) 175 as <=> bs 176 end 177 end 178 end
# File lib/puppet/functions/max.rb 132 def on_any_with_block(*args, &block) 133 args.max {|x,y| block.call(x,y) } 134 end
# File lib/puppet/functions/downcase.rb 76 def on_array(a) 77 a.map {|x| do_downcase(x) } 78 end
# File lib/puppet/functions/compare.rb 98 def on_error(a, b, *ignore_case) 99 if !ignore_case.empty? 100 unless a.is_a?(String) && b.is_a?(String) 101 # TRANSLATORS 'compare' is a name 102 return _("compare(): The third argument (ignore case) can only be used when comparing strings") 103 end 104 unless ignore_case.size == 1 105 # TRANSLATORS 'compare' is a name 106 return _("compare(): Accepts at most 3 arguments, got %{actual_number}") % {actual_number: 2 + ignore_case.size} 107 end 108 unless ignore_case[0].is_a?(Boolean) 109 # TRANSLATORS 'compare' is a name 110 return _("compare(): The third argument (ignore case) must be a Boolean. Got %{type}") % { type: type_label(ignore_case[0]) } 111 end 112 end 113 114 if a.class != b.class 115 # TRANSLATORS 'compare' is a name 116 return _("compare(): Can only compare values of the same type (or for Timestamp/Timespan also against Numeric). Got %{type_a} and %{type_b}") % { 117 type_a: type_label(a), type_b: type_label(b) 118 } 119 end 120 end
# File lib/puppet/functions/downcase.rb 80 def on_hash(h) 81 result = {} 82 h.each_pair {|k,v| result[do_downcase(k)] = do_downcase(v) } 83 result 84 end
# File lib/puppet/functions/camelcase.rb 54 def on_iterable(a) 55 a.map {|x| do_camelcase(x) } 56 end
# File lib/puppet/functions/compare.rb 91 def on_not_comparable(a, b, *ignore_case) 92 # TRANSLATORS 'compare' is a name 93 _("compare(): Non comparable type. Only values of the types Numeric, String, Semver, Timestamp and Timestamp can be compared. Got %{type_a} and %{type_b}") % { 94 type_a: type_label(a), type_b: type_label(b) 95 } 96 end
# File lib/puppet/functions/abs.rb 42 def on_numeric(x) 43 x.abs 44 end
# File lib/puppet/functions/max.rb 152 def on_single_any_array(array, &block) 153 if block_given? 154 on_any_with_block(*array, &block) 155 else 156 on_any(*array) 157 end 158 end
# File lib/puppet/functions/max.rb 136 def on_single_numeric_array(array, &block) 137 if block_given? 138 on_any_with_block(*array, &block) 139 else 140 on_numeric(*array) 141 end 142 end
# File lib/puppet/functions/max.rb 144 def on_single_string_array(array, &block) 145 if block_given? 146 on_any_with_block(*array, &block) 147 else 148 on_string(*array) 149 end 150 end
# File lib/puppet/functions/abs.rb 46 def on_string(x) 47 Puppet.warn_once('deprecations', 'abs_function_numeric_coerce_string', 48 _("The abs() function's auto conversion of String to Numeric is deprecated - change to convert input before calling")) 49 50 # These patterns for conversion are backwards compatible with the stdlib 51 # version of this function. 52 # 53 if x =~ %r{^-?(?:\d+)(?:\.\d+){1}$} 54 x.to_f.abs 55 elsif x =~ %r{^-?\d+$} 56 x.to_i.abs 57 else 58 raise(ArgumentError, 'abs(): Requires float or integer to work with - was given non decimal string') 59 end 60 end
# File lib/puppet/functions/compare.rb 77 def on_time_num_first(a, b) 78 # Time data types can compare against Numeric but not the other way around 79 # the comparison is therefore done in reverse and the answer is inverted. 80 -(b <=> a) 81 end
# File lib/puppet/functions/compare.rb 83 def on_timespan(a, b) 84 a <=> b 85 end
# File lib/puppet/functions/compare.rb 87 def on_timestamp(a, b) 88 a <=> b 89 end
# File lib/puppet/functions/compare.rb 73 def on_version(a, b) 74 a <=> b 75 end
# File lib/puppet/provider/package/pkgng.rb 165 def origin 166 @property_hash[:origin] 167 end
Where is our override script?
# File lib/puppet/provider/service/upstart.rb 105 def overscript 106 @overscript ||= initscript.gsub(/\.conf$/,".override") 107 end
# File lib/puppet/provider/file/posix.rb 60 def owner 61 stat = resource.stat 62 unless stat 63 return :absent 64 end 65 66 currentvalue = stat.uid 67 68 # On OS X, files that are owned by -2 get returned as really 69 # large UIDs instead of negative ones. This isn't a Ruby bug, 70 # it's an OS X bug, since it shows up in perl, too. 71 if currentvalue > Puppet[:maximum_uid].to_i 72 self.warning _("Apparently using negative UID (%{currentvalue}) on a platform that does not consistently handle them") % { currentvalue: currentvalue } 73 currentvalue = :silly 74 end 75 76 currentvalue 77 end
# File lib/puppet/provider/file/posix.rb 79 def owner=(should) 80 # Set our method appropriately, depending on links. 81 if resource[:links] == :manage 82 method = :lchown 83 else 84 method = :chown 85 end 86 87 begin 88 File.send(method, should, nil, resource[:path]) 89 rescue => detail 90 raise Puppet::Error, _("Failed to set owner to '%{should}': %{detail}") % { should: should, detail: detail }, detail.backtrace 91 end 92 end
# File lib/puppet/provider/package/opkg.rb 79 def package_lists 80 Dir.entries('/var/opkg-lists/') 81 end
# File lib/puppet/provider/package/nim.rb 221 def parse_installp_package_string(package_string) 222 match = package_string.match(self.class::INSTALLP_PACKAGE_REGEX) 223 unless match 224 self.fail _("Unable to parse output from nimclient showres: package string does not match expected installp package string format:\n'%{package_string}'") % { package_string: package_string } 225 end 226 package_name = match.captures[0] 227 version = match.captures[1] 228 [package_name, version, :installp] 229 end
Helper function that parses the password from the given password filehandle. This is here to make testing easier for password
since we cannot configure Mocha to mock out a method and have it return a block's value, meaning we cannot test password
directly (not in a simple and obvious way, at least). @api private
# File lib/puppet/provider/user/aix.rb 162 def parse_password(f) 163 # From the docs, a user stanza is formatted as (newlines are explicitly 164 # stated here for clarity): 165 # <user>:\n 166 # <attribute1>=<value1>\n 167 # <attribute2>=<value2>\n 168 # 169 # First, find our user stanza 170 stanza = f.each_line.find { |line| line =~ /\A#{@resource[:name]}:/ } 171 return :absent unless stanza 172 173 # Now find the password line, if it exists. Note our call to each_line here 174 # will pick up right where we left off. 175 match_obj = nil 176 f.each_line.find do |line| 177 # Break if we find another user stanza. This means our user 178 # does not have a password. 179 break if line =~ /^\S+:$/ 180 181 match_obj = /password\s+=\s+(\S+)/.match(line) 182 end 183 return :absent unless match_obj 184 185 match_obj[1] 186 end
# File lib/puppet/provider/package/openbsd.rb 121 def parse_pkgconf 122 unless @resource[:source] 123 if Puppet::FileSystem.exist?("/etc/pkg.conf") 124 File.open("/etc/pkg.conf", "rb").readlines.each do |line| 125 matchdata = line.match(/^installpath\s*=\s*(.+)\s*$/i) 126 if matchdata 127 @resource[:source] = matchdata[1] 128 else 129 matchdata = line.match(/^installpath\s*\+=\s*(.+)\s*$/i) 130 if matchdata 131 if @resource[:source].nil? 132 @resource[:source] = matchdata[1] 133 else 134 @resource[:source] += ":" + matchdata[1] 135 end 136 end 137 end 138 end 139 140 unless @resource[:source] 141 raise Puppet::Error, 142 _("No valid installpath found in /etc/pkg.conf and no source was set") 143 end 144 else 145 raise Puppet::Error, 146 _("You must specify a package source or configure an installpath in /etc/pkg.conf") 147 end 148 end 149 end
# File lib/puppet/provider/package/pkgin.rb 53 def parse_pkgsearch_line 54 packages = pkgin(:search, resource[:name]).split("\n") 55 56 return [] if packages.length == 1 57 58 # Remove the last three lines of help text. 59 packages.slice!(-4, 4) 60 61 pkglist = packages.map{ |line| self.class.parse_pkgin_line(line) } 62 pkglist.select{ |package| resource[:name] == package[:name] } 63 end
# File lib/puppet/provider/package/nim.rb 231 def parse_rpm_package_string(package_string) 232 match = package_string.match(self.class::RPM_PACKAGE_REGEX) 233 unless match 234 self.fail _("Unable to parse output from nimclient showres: package string does not match expected rpm package string format:\n'%{package_string}'") % { package_string: package_string } 235 end 236 package_name = match.captures[0] 237 version = match.captures[1] 238 [package_name, version, :rpm] 239 end
# File lib/puppet/provider/package/nim.rb 211 def parse_showres_header_line(line) 212 # This method doesn't produce any meaningful output; it's basically just 213 # meant to validate that the header line for the package listing output 214 # looks sane, so we know we're dealing with the kind of output that we 215 # are capable of handling. 216 unless line.match(self.class::HEADER_LINE_REGEX) 217 self.fail _("Unable to parse output from nimclient showres: line does not match expected package header format:\n'%{line}'") % { line: line } 218 end 219 end
Parse the output of a `nimclient -o showres` command. Returns a two-dimensional hash, where the first-level keys are package names, the second-level keys are version number strings for all of the available version numbers for a package, and the values indicate the package type (:rpm / :installp)
# File lib/puppet/provider/package/nim.rb 188 def parse_showres_output(showres_output) 189 paragraphs = split_into_paragraphs(showres_output) 190 packages = {} 191 paragraphs.each do |para| 192 lines = para.split(/$/) 193 parse_showres_header_line(lines.shift) 194 lines.each do |l| 195 package, version, type = parse_showres_package_line(l) 196 packages[package] ||= {} 197 packages[package][version] = type 198 end 199 end 200 packages 201 end
# File lib/puppet/provider/package/nim.rb 241 def parse_showres_package_line(line) 242 match = line.match(self.class::PACKAGE_LINE_REGEX) 243 unless match 244 self.fail _("Unable to parse output from nimclient showres: line does not match expected package line format:\n'%{line}'") % { line: line } 245 end 246 247 package_type_flag = match.captures[0] 248 package_string = match.captures[1] 249 250 case package_type_flag 251 when "I","S" 252 parse_installp_package_string(package_string) 253 when "R" 254 parse_rpm_package_string(package_string) 255 else 256 self.fail _("Unrecognized package type specifier: '%{package_type_flag}' in package line:\n'%{line}'") % { package_type_flag: package_type_flag, line: line } 257 end 258 end
# File lib/puppet/functions/partition.rb 41 def partition_1(collection) 42 collection.partition do |item| 43 yield(item) 44 end.freeze 45 end
# File lib/puppet/functions/partition.rb 57 def partition_2(collection) 58 collection.partition do |k, v| 59 yield(k, v) 60 end.freeze 61 end
# File lib/puppet/functions/partition.rb 47 def partition_2a(array) 48 partitioned = array.size.times.zip(array).partition do |k, v| 49 yield(k, v) 50 end 51 52 partitioned.map do |part| 53 part.map { |item| item[1] } 54 end.freeze 55 end
# File lib/puppet/provider/user/useradd.rb 336 def passcmd 337 if @resource.forcelocal? 338 cmd = command(:localpassword) 339 @custom_environment = Puppet::Util::Libuser.getenv 340 else 341 cmd = command(:password) 342 end 343 age_limits = [:password_min_age, :password_max_age, :password_warn_days].select { |property| @resource.should(property) } 344 if age_limits.empty? 345 nil 346 else 347 [cmd, age_limits.collect { |property| [flag(property), @resource.should(property)]}, @resource[:name]].flatten 348 end 349 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 the /etc/security/passwd file.
# File lib/puppet/provider/user/aix.rb 194 def password 195 # AIX reference indicates this file is ASCII 196 # https://www.ibm.com/support/knowledgecenter/en/ssw_aix_72/com.ibm.aix.files/passwd_security.htm 197 Puppet::FileSystem.open("/etc/security/passwd", nil, "r:ASCII") do |f| 198 parse_password(f) 199 end 200 end
# File lib/puppet/provider/user/aix.rb 202 def password=(value) 203 user = @resource[:name] 204 205 begin 206 # Puppet execute does not support strings as input, only files. 207 # The password is expected to be in an encrypted format given -e is specified: 208 # https://www.ibm.com/support/knowledgecenter/ssw_aix_71/com.ibm.aix.cmds1/chpasswd.htm 209 # /etc/security/passwd is specified as an ASCII file per the AIX documentation 210 tempfile = nil 211 tempfile = Tempfile.new("puppet_#{user}_pw", :encoding => Encoding::ASCII) 212 tempfile << "#{user}:#{value}\n" 213 tempfile.close() 214 215 # Options '-e', '-c', use encrypted password and clear flags 216 # Must receive "user:enc_password" as input 217 # command, arguments = {:failonfail => true, :combine => true} 218 # Fix for bugs #11200 and #10915 219 cmd = [self.class.command(:chpasswd), *ia_module_args, '-e', '-c'] 220 execute_options = { 221 :failonfail => false, 222 :combine => true, 223 :stdinfile => tempfile.path 224 } 225 output = execute(cmd, execute_options) 226 227 # chpasswd can return 1, even on success (at least on AIX 6.1); empty output 228 # indicates success 229 if output != "" 230 raise Puppet::ExecutionFailure, "chpasswd said #{output}" 231 end 232 rescue Puppet::ExecutionFailure => detail 233 raise Puppet::Error, "Could not set password on #{@resource.class.name}[#{@resource.name}]: #{detail}", detail.backtrace 234 ensure 235 if tempfile 236 # Extra close will noop. This is in case the write to our tempfile 237 # fails. 238 tempfile.close() 239 tempfile.delete() 240 end 241 end 242 end
# File lib/puppet/provider/user/user_role_add.rb 197 def password_max_age 198 return :absent unless shadow_entry 199 shadow_entry[4].empty? ? -1 : shadow_entry[4] 200 end
# File lib/puppet/provider/user/user_role_add.rb 192 def password_min_age 193 return :absent unless shadow_entry 194 shadow_entry[3].empty? ? -1 : shadow_entry[3] 195 end
# File lib/puppet/provider/user/user_role_add.rb 202 def password_warn_days 203 return :absent unless shadow_entry 204 shadow_entry[5].empty? ? -1 : shadow_entry[5] 205 end
Component paths are special because they function as containers.
# File lib/puppet/type/component.rb 35 def pathbuilder 36 if reference.type == "Class" 37 myname = reference.title 38 else 39 myname = reference.to_s 40 end 41 p = self.parent 42 if p 43 return [p.pathbuilder, myname] 44 else 45 return [myname] 46 end 47 end
# File lib/puppet/provider/service/init.rb 123 def paths 124 @paths ||= @resource[:path].find_all do |path| 125 if File.directory?(path) 126 true 127 else 128 if Puppet::FileSystem.exist?(path) 129 self.debug "Search path #{path} is not a directory" 130 else 131 self.debug "Search path #{path} does not exist" 132 end 133 false 134 end 135 end 136 end
# File lib/puppet/type/file.rb 765 def perform_recursion(path) 766 Puppet::FileServing::Metadata.indirection.search( 767 path, 768 :links => self[:links], 769 :recurse => (self[:recurse] == :remote ? true : self[:recurse]), 770 :recurselimit => self[:recurselimit], 771 :max_files => self[:max_files], 772 :source_permissions => self[:source_permissions], 773 :ignore => self[:ignore], 774 :checksum_type => (self[:source] || self[:content]) ? self[:checksum] : :none, 775 :environment => catalog.environment_instance 776 ) 777 end
# File lib/puppet/provider/package/blastwave.rb 11 def pkgget_with_cat(*args) 12 Puppet::Util.withenv(:PAGER => "/usr/bin/cat") { pkgget(*args) } 13 end
Turn our pkgutil -c listing into a hash for a single package.
# File lib/puppet/provider/package/pkgutil.rb 79 def pkgsingle(resource) 80 # The --single option speeds up the execution, because it queries 81 # the package management system for one package only. 82 command = ["-c", "--single", resource[:name]] 83 self.class.parse_pkglist(run_pkgutil(resource, command), { :justme => resource[:name] }) 84 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 228 def plist_from_label(label) 229 job = self.class.jobsearch(label) 230 job_path = job[label] 231 if FileTest.file?(job_path) 232 job_plist = self.class.read_plist(job_path) 233 else 234 raise Puppet::Error.new("Unable to parse launchd plist at path: #{job_path}") 235 end 236 [job_path, job_plist] 237 end
# File lib/puppet/functions/hiera_include.rb 100 def post_lookup(scope, key, value) 101 raise Puppet::ParseError, _("Could not find data item %{key}") % { key: key } if value.nil? 102 call_function_with_scope(scope, 'include', value) unless value.empty? 103 end
# File lib/puppet/provider/package/sun.rb 118 def prepare_cmd(opt) 119 [if_have_value('-a', opt[:adminfile]), 120 if_have_value('-r', opt[:responsefile]), 121 if_have_value('-d', opt[:source]), 122 opt[:cmd_options] || [], 123 ['-n', @resource[:name]]].flatten 124 end
# File lib/puppet/provider/service/systemd.rb 223 def prepare_error_message(name, action, exception) 224 error_return = "Systemd #{action} for #{name} failed!\n" 225 journalctl_command = "journalctl -n 50 --since '5 minutes ago' -u #{name} --no-pager" 226 Puppet.debug("Running journalctl command to get logs for systemd #{action} failure: #{journalctl_command}") 227 journalctl_output = execute(journalctl_command) 228 error_return << "journalctl log for #{name}:\n#{journalctl_output}" 229 end
# File lib/puppet/type/file.rb 517 def present?(current_values) 518 super && current_values[:ensure] != :false 519 end
# File lib/puppet/reports/http.rb 16 def process 17 url = URI.parse(Puppet[:reporturl]) 18 headers = { "Content-Type" => "application/x-yaml" } 19 # This metric_id option is silently ignored by Puppet's http client 20 # (Puppet::Network::HTTP) but is used by Puppet Server's http client 21 # (Puppet::Server::HttpClient) to track metrics on the request made to the 22 # `reporturl` to store a report. 23 options = { 24 :metric_id => [:puppet, :report, :http], 25 :include_system_store => Puppet[:report_include_system_store], 26 } 27 28 # Puppet's http client implementation accepts userinfo in the URL 29 # but puppetserver's does not. So pass credentials explicitly. 30 if url.user && url.password 31 options[:basic_auth] = { 32 user: url.user, 33 password: url.password 34 } 35 end 36 37 client = Puppet.runtime[:http] 38 client.post(url, self.to_yaml, headers: headers, options: options) do |response| 39 unless response.success? 40 Puppet.err _("Unable to submit report to %{url} [%{code}] %{message}") % { url: Puppet[:reporturl].to_s, code: response.code, message: response.reason } 41 end 42 end 43 end
# File lib/puppet/provider/user/user_role_add.rb 132 def profiles 133 user_attributes[:profiles] if user_attributes 134 end
# File lib/puppet/provider/user/user_role_add.rb 136 def project 137 user_attributes[:project] if user_attributes 138 end
Hack things a bit so we only ever check the ensure property.
# File lib/puppet/type/tidy.rb 266 def properties 267 [] 268 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 1105 def property_fix 1106 properties.each do |thing| 1107 next unless [:mode, :owner, :group, :seluser, :selrole, :seltype, :selrange].include?(thing.name) 1108 1109 # Make sure we get a new stat object 1110 @stat = :needs_stat 1111 currentvalue = thing.retrieve 1112 thing.sync unless thing.safe_insync?(currentvalue) 1113 end 1114 end
# File lib/puppet/provider/user/useradd.rb 380 def property_manages_password_age?(property) 381 property.to_s =~ /password_.+_age|password_warn_days/ 382 end
# File lib/puppet/provider/package/apt.rb 216 def purge 217 self.run_preseed if @resource[:responsefile] 218 args = ['-y', '-q'] 219 args << '--allow-change-held-packages' if self.properties[:mark] == :hold 220 args << :remove << '--purge' << @resource[:name] 221 aptget(*args) 222 # workaround a "bug" in apt, that already removed packages are not purged 223 super 224 end
# File lib/puppet/provider/group/groupadd.rb 126 def purge_members 127 localmodify('-m', members_to_s(members), @resource.name) 128 end
# File lib/puppet/provider/package/portage.rb 106 def qatom 107 output_format = self.qatom_output_format 108 result_format = self.qatom_result_format 109 result_fields = self.qatom_result_fields 110 @atom ||= begin 111 package_info = {} 112 # do the search 113 should = @resource[:ensure] 114 case should 115 # The terms present, absent, purged, installed, latest in :ensure 116 # resolve as Symbols, and we do not need specific package version in this case 117 when true, false, Symbol 118 search = @resource[:name] 119 else 120 search = '=' + @resource[:name] + '-' + "#{should}" 121 end 122 search_output = qatom_bin(*([search, '--format', output_format])) 123 # verify if the search found anything 124 match = result_format.match(search_output) 125 if match 126 result_fields.zip(match.captures) do |field, value| 127 # some fields can be empty or (null) (if we are not passed a category in the package name for instance) 128 if value == '(null)' || value == '<unset>' 129 package_info[field] = nil 130 elsif !value or value.empty? 131 package_info[field] = nil 132 else 133 package_info[field] = value 134 end 135 end 136 end 137 @atom = package_info 138 rescue Puppet::ExecutionFailure => detail 139 raise Puppet::Error.new(detail) 140 end 141 end
# File lib/puppet/provider/package/portage.rb 143 def qatom_output_format 144 '"[%[CATEGORY]] [%[PN]] [%[PV]] [%[PR]] [%[SLOT]] [%[pfx]] [%[sfx]]"' 145 end
# File lib/puppet/provider/package/portage.rb 151 def qatom_result_fields 152 [:category, :pn, :pv, :pr, :slot, :pfx, :sfx] 153 end
# File lib/puppet/provider/package/portage.rb 147 def qatom_result_format 148 /^\"\[(\S*)\]\s+\[(\S*)\]\s+\[(\S*)\]\s+\[(\S*)\]\s+\[(\S*)\]\s+\[(\S*)\]\s+\[(\S*)\](.*)\"$/ 149 end
# File lib/puppet/provider/package/aix.rb 162 def query 163 self.class.pkglist(:pkgname => @resource[:name]) 164 end
Add a new setting to the rc files
# File lib/puppet/provider/service/freebsd.rb 87 def rc_add(service, rcvar, yesno) 88 append = "\# Added by Puppet\n#{rcvar}_enable=\"#{yesno}\"\n" 89 # First, try the one-file-per-service style 90 if Puppet::FileSystem.exist?(rcconf_dir) 91 File.open(rcconf_dir + "/#{service}", File::WRONLY | File::APPEND | File::CREAT, 0644) { 92 |f| f << append 93 self.debug("Appended to #{f.path}") 94 } 95 else 96 # Else, check the local rc file first, but don't create it 97 if Puppet::FileSystem.exist?(rcconf_local) 98 File.open(rcconf_local, File::WRONLY | File::APPEND) { 99 |f| f << append 100 self.debug("Appended to #{f.path}") 101 } 102 else 103 # At last use the standard rc.conf file 104 File.open(rcconf, File::WRONLY | File::APPEND | File::CREAT, 0644) { 105 |f| f << append 106 self.debug("Appended to #{f.path}") 107 } 108 end 109 end 110 end
Edit rc files and set the service to yes/no
# File lib/puppet/provider/service/freebsd.rb 61 def rc_edit(yesno) 62 service = self.service_name 63 rcvar = self.rcvar_name 64 self.debug("Editing rc files: setting #{rcvar} to #{yesno} for #{service}") 65 self.rc_add(service, rcvar, yesno) if not self.rc_replace(service, rcvar, yesno) 66 end
Try to find an existing setting in the rc files and replace the value
# File lib/puppet/provider/service/freebsd.rb 70 def rc_replace(service, rcvar, yesno) 71 success = false 72 # Replace in all files, not just in the first found with a match 73 [rcconf, rcconf_local, rcconf_dir + "/#{service}"].each do |filename| 74 if Puppet::FileSystem.exist?(filename) 75 s = File.read(filename) 76 if s.gsub!(/^(#{rcvar}(_enable)?)=\"?(YES|NO)\"?/, "\\1=\"#{yesno}\"") 77 Puppet::FileSystem.replace_file(filename) { |f| f << s } 78 self.debug("Replaced in #{filename}") 79 success = true 80 end 81 end 82 end 83 success 84 end
# File lib/puppet/provider/service/freebsd.rb 8 def rcconf() '/etc/rc.conf' end
# File lib/puppet/provider/service/bsd.rb 10 def rcconf_dir 11 '/etc/rc.conf.d' 12 end
# File lib/puppet/provider/service/freebsd.rb 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 22 def rcvar 23 rcvar = execute([self.initscript, :rcvar], :failonfail => true, :combine => false, :squelch => false) 24 rcvar = rcvar.split("\n") 25 rcvar.delete_if {|str| str =~ /^#\s*$/} 26 rcvar[1] = rcvar[1].gsub(/^\$/, '') 27 rcvar 28 end
Extract rcvar name
# File lib/puppet/provider/service/freebsd.rb 46 def rcvar_name 47 extract_value_name('rcvar', 1, /(.*?)(_enable)?=(.*)/, '\1') 48 end
Extract rcvar value
# File lib/puppet/provider/service/freebsd.rb 51 def rcvar_value 52 value = self.rcvar[1] 53 self.error("No rcvar value found in rcvar") if value.nil? 54 value = value.gsub!(/(.*)(_enable)?="?(\w+)"?/, '\3') 55 self.error("rcvar value is empty") if value.nil? 56 self.debug("rcvar value is #{value}") 57 value 58 end
@return [String] The type of the current file, cast to a string.
# File lib/puppet/type/file.rb 1002 def read_current_type 1003 stat_info = stat 1004 if stat_info 1005 stat_info.ftype.to_s 1006 else 1007 nil 1008 end 1009 end
# File lib/puppet/provider/service/upstart.rb 303 def read_override_file 304 if Puppet::FileSystem.exist?(overscript) 305 read_script_from(overscript) 306 else 307 "" 308 end 309 end
# File lib/puppet/provider/service/upstart.rb 374 def read_script_from(filename) 375 File.open(filename) do |file| 376 file.read 377 end 378 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 627 def recurse 628 children = (self[:recurse] == :remote) ? {} : recurse_local 629 630 if self[:target] 631 recurse_link(children) 632 elsif self[:source] 633 recurse_remote(children) 634 end 635 636 # If we're purging resources, then delete any resource that isn't on the 637 # remote system. 638 mark_children_for_purging(children) if self.purge? 639 640 result = children.values.sort_by { |a| a[:path] } 641 remove_less_specific_files(result) 642 end
A simple method for determining whether we should be recursing.
# File lib/puppet/type/file.rb 672 def recurse? 673 self[:recurse] == true or self[:recurse] == :remote 674 end
Recurse the target of the link.
# File lib/puppet/type/file.rb 677 def recurse_link(children) 678 perform_recursion(self[:target]).each do |meta| 679 if meta.relative_path == "." 680 self[:ensure] = :directory 681 next 682 end 683 684 children[meta.relative_path] ||= newchild(meta.relative_path) 685 if meta.ftype == "directory" 686 children[meta.relative_path][:ensure] = :directory 687 else 688 children[meta.relative_path][:ensure] = :link 689 children[meta.relative_path][:target] = meta.full_path 690 end 691 end 692 children 693 end
Recurse the file itself, returning a Metadata instance for every found file.
# File lib/puppet/type/file.rb 696 def recurse_local 697 result = perform_recursion(self[:path]) 698 return {} unless result 699 result.inject({}) do |hash, meta| 700 next hash if meta.relative_path == "." 701 702 hash[meta.relative_path] = newchild(meta.relative_path) 703 hash 704 end 705 end
Recurse against our remote file.
# File lib/puppet/type/file.rb 708 def recurse_remote(children) 709 recurse_remote_metadata.each do |meta| 710 if meta.relative_path == "." 711 self[:checksum] = meta.checksum_type 712 parameter(:source).metadata = meta 713 next 714 end 715 children[meta.relative_path] ||= newchild(meta.relative_path) 716 children[meta.relative_path][:source] = meta.source 717 children[meta.relative_path][:checksum] = meta.checksum_type 718 children[meta.relative_path].parameter(:source).metadata = meta 719 end 720 721 children 722 end
# File lib/puppet/type/file.rb 724 def recurse_remote_metadata 725 sourceselect = self[:sourceselect] 726 727 total = self[:source].collect do |source| 728 # For each inlined file resource, the catalog contains a hash mapping 729 # source path to lists of metadata returned by a server-side search. 730 recursive_metadata = catalog.recursive_metadata[title] 731 if recursive_metadata 732 result = recursive_metadata[source] 733 else 734 result = perform_recursion(source) 735 end 736 737 next unless result 738 top = result.find { |r| r.relative_path == "." } 739 return [] if top && top.ftype != "directory" 740 result.each do |data| 741 if data.relative_path == '.' 742 data.source = source 743 else 744 # REMIND: appending file paths to URL may not be safe, e.g. foo+bar 745 data.source = "#{source}/#{data.relative_path}" 746 end 747 end 748 break result if result and ! result.empty? and sourceselect == :first 749 result 750 end.flatten.compact 751 752 # This only happens if we have sourceselect == :all 753 unless sourceselect == :first 754 found = [] 755 total.reject! do |data| 756 result = found.include?(data.relative_path) 757 found << data.relative_path unless result 758 result 759 end 760 end 761 762 total 763 end
# File lib/puppet/functions/reduce.rb 152 def reduce_with_memo(enumerable, given_memo) 153 enum = Puppet::Pops::Types::Iterable.asserted_iterable(self, enumerable) 154 enum.reduce(given_memo) do |memo, x| 155 begin 156 yield(memo, x) 157 rescue StopIteration 158 return memo 159 end 160 end 161 end
# File lib/puppet/functions/reduce.rb 141 def reduce_without_memo(enumerable) 142 enum = Puppet::Pops::Types::Iterable.asserted_iterable(self, enumerable) 143 enum.reduce do |memo, x| 144 begin 145 yield(memo, x) 146 rescue StopIteration 147 return memo 148 end 149 end 150 end
# File lib/puppet/type/component.rb 49 def ref 50 reference.to_s 51 end
# File lib/puppet/type/component.rb 62 def refresh 63 catalog.adjacent(self).each do |child| 64 if child.respond_to?(:refresh) 65 child.refresh 66 child.log "triggering #{:refresh}" 67 end 68 end 69 end
# File lib/puppet/functions/regsubst.rb 92 def regsubst_regexp(target, pattern, replacement, flags = nil) 93 pattern = (pattern.pattern || '') if pattern.is_a?(Puppet::Pops::Types::PRegexpType) 94 inner_regsubst(target, pattern, replacement, flags == 'G' ? :gsub : :sub) 95 end
# File lib/puppet/functions/regsubst.rb 76 def regsubst_string(target, pattern, replacement, flags = nil, encoding = nil) 77 re_flags = 0 78 operation = :sub 79 if !flags.nil? 80 flags.split(//).each do |f| 81 case f 82 when 'G' then operation = :gsub 83 when 'E' then re_flags |= Regexp::EXTENDED 84 when 'I' then re_flags |= Regexp::IGNORECASE 85 when 'M' then re_flags |= Regexp::MULTILINE 86 end 87 end 88 end 89 inner_regsubst(target, Regexp.compile(pattern, re_flags, encoding), replacement, operation) 90 end
# File lib/puppet/provider/package/portage.rb 98 def reinstall 99 self.install 100 end
@return [Boolean] if the directory was removed (which is always true currently) @api private
# File lib/puppet/type/file.rb 1027 def remove_directory(wanted_type) 1028 if force? 1029 debug "Removing existing directory for replacement with #{wanted_type}" 1030 FileUtils.rmtree(self[:path]) 1031 stat_needed 1032 true 1033 else 1034 notice _("Not removing directory; use 'force' to override") 1035 false 1036 end 1037 end
Back up and remove the file or directory at `self`.
@param [Symbol] should The file type replacing the current content. @return [Boolean] True if the file was removed, else False @raises [fail???] If the file could not be backed up or could not be removed.
# File lib/puppet/type/file.rb 784 def remove_existing(should) 785 wanted_type = should.to_s 786 current_type = read_current_type 787 788 if current_type.nil? 789 return false 790 end 791 792 if self[:backup] 793 if can_backup?(current_type) 794 backup_existing 795 else 796 self.warning _("Could not back up file of type %{current_type}") % { current_type: current_type } 797 end 798 end 799 800 if wanted_type != "link" and current_type == wanted_type 801 return false 802 end 803 804 case current_type 805 when "directory" 806 return remove_directory(wanted_type) 807 when "link", "file", "fifo", "socket" 808 return remove_file(current_type, wanted_type) 809 else 810 # Including: “blockSpecial”, “characterSpecial”, “unknown” 811 self.fail _("Could not remove files of type %{current_type}") % { current_type: current_type } 812 end 813 end
@return [Boolean] if the file was removed (which is always true currently) @api private
# File lib/puppet/type/file.rb 1041 def remove_file(current_type, wanted_type) 1042 debug "Removing existing #{current_type} for replacement with #{wanted_type}" 1043 Puppet::FileSystem.unlink(self[:path]) 1044 stat_needed 1045 true 1046 end
# File lib/puppet/type/file.rb 644 def remove_less_specific_files(files) 645 existing_files = catalog.vertices.select { |r| r.is_a?(self.class) } 646 self.class.remove_less_specific_files(files, self[:path], existing_files) do |file| 647 file[:path] 648 end 649 end
# File lib/puppet/provider/user/user_role_add.rb 144 def remove_managed_attributes 145 managed = managed_attributes 146 user_attributes.select { |k,v| !managed.include?(k) }.inject({}) { |hash, array| hash[array[0]] = array[1]; hash } 147 end
# File lib/puppet/provider/service/upstart.rb 327 def remove_manual_from(text) 328 text.gsub(MANUAL, "") 329 end
# File lib/puppet/provider/service/upstart.rb 319 def remove_trailing_comments_from(line) 320 line.gsub(/^(\s*[^#]*).*/, '\1') 321 end
# File lib/puppet/provider/service/upstart.rb 315 def remove_trailing_comments_from_commented_line_of(line) 316 line.gsub(/^(\s*#+\s*[^#]*).*/, '\1') 317 end
# File lib/puppet/network/formats.rb 66 def render(instance) 67 instance.to_yaml 68 end
# File lib/puppet/face/help.rb 98 def render_application_help(applicationname) 99 return Puppet::Application[applicationname].help 100 rescue StandardError, LoadError => detail 101 message = [] 102 message << _('Could not load help for the application %{application_name}.') % { application_name: applicationname } 103 message << _('Please check the error logs for more information.') 104 message << '' 105 message << _('Detail: "%{detail}"') % { detail: detail.message } 106 fail ArgumentError, message.join("\n"), detail.backtrace 107 end
# File lib/puppet/face/help.rb 109 def render_face_help(facename, actionname, version) 110 face, action = load_face_help(facename, actionname, version) 111 return template_for(face, action).result(binding) 112 rescue StandardError, LoadError => detail 113 message = [] 114 message << _('Could not load help for the face %{face_name}.') % { face_name: facename } 115 message << _('Please check the error logs for more information.') 116 message << '' 117 message << _('Detail: "%{detail}"') % { detail: detail.message } 118 fail ArgumentError, message.join("\n"), detail.backtrace 119 end
# File lib/puppet/face/help.rb 90 def render_face_man(facename) 91 # set 'face' as it's used in the erb processing. 92 face = Puppet::Face[facename.to_sym, :current] 93 # avoid unused variable warning 94 _face = face 95 erb('man.erb').result(binding) 96 end
# File lib/puppet/face/epp.rb 451 def render_file(epp_template_name, compiler, options, show_filename, file_nbr) 452 template_args = get_values(compiler, options) 453 output = "" 454 begin 455 if show_filename && options[:header] 456 output << "\n" unless file_nbr == 1 457 output << "--- #{epp_template_name}\n" 458 end 459 # Change to an absolute file only if reference is to a an existing file. Note that an absolute file must be used 460 # or the template must be found on the module path when calling the epp evaluator. 461 template_file = Puppet::Parser::Files.find_template(epp_template_name, compiler.environment) 462 if template_file.nil? && Puppet::FileSystem.exist?(epp_template_name) 463 epp_template_name = File.expand_path(epp_template_name) 464 end 465 result = Puppet::Pops::Evaluator::EppEvaluator.epp(compiler.topscope, epp_template_name, compiler.environment, template_args) 466 if result.instance_of?(Puppet::Pops::Types::PSensitiveType::Sensitive) 467 output << result.unwrap 468 else 469 output << result 470 end 471 rescue Puppet::ParseError => detail 472 Puppet.err("--- #{epp_template_name}") if show_filename 473 raise detail 474 end 475 output 476 end
# File lib/puppet/face/epp.rb 441 def render_inline(epp_source, compiler, options) 442 template_args = get_values(compiler, options) 443 result = Puppet::Pops::Evaluator::EppEvaluator.inline_epp(compiler.topscope, epp_source, template_args) 444 if result.instance_of?(Puppet::Pops::Types::PSensitiveType::Sensitive) 445 result.unwrap 446 else 447 result 448 end 449 end
# File lib/puppet/network/formats.rb 20 def render_multiple(instances) 21 instances.to_msgpack 22 end
# File lib/puppet/provider/package/pkgng.rb 90 def repo_tag_from_urn(urn) 91 # extract repo tag from URN: urn:freebsd:repo:<tag> 92 match = /^urn:freebsd:repo:(.+)$/.match(urn) 93 raise ArgumentError urn.inspect unless match 94 match[1] 95 end
# File lib/puppet/face/config.rb 110 def report_section_and_environment(section_name, environment_name) 111 $stderr.puts colorize(:hyellow, 112 _("Resolving settings from section '%{section_name}' in environment '%{environment_name}'") % 113 { section_name: section_name, environment_name: environment_name }) 114 end
# File lib/puppet/functions/require.rb 47 def require_impl(scope, *classes) 48 if Puppet[:tasks] 49 raise Puppet::ParseErrorWithIssue.from_issue_and_stack( 50 Puppet::Pops::Issues::CATALOG_OPERATION_NOT_SUPPORTED_WHEN_SCRIPTING, 51 {:operation => 'require'}) 52 end 53 54 # Make call patterns uniform and protected against nested arrays, also make 55 # names absolute if so desired. 56 classes = scope.transform_and_assert_classnames(classes.flatten) 57 58 result = classes.map {|name| Puppet::Pops::Types::TypeFactory.host_class(name) } 59 60 # This is the same as calling the include function (but faster) since it again 61 # would otherwise need to perform the optional absolute name transformation 62 # (for no reason since they are already made absolute here). 63 # 64 scope.compiler.evaluate_classes(classes, scope, false) 65 krt = scope.environment.known_resource_types 66 67 classes.each do |klass| 68 # lookup the class in the scopes 69 klass = (classobj = krt.find_hostclass(klass)) ? classobj.name : nil 70 raise Puppet::ParseError.new(_("Could not find class %{klass}") % { klass: klass }) unless klass 71 ref = Puppet::Resource.new(:class, klass) 72 resource = scope.resource 73 resource.set_parameter(:require, [resource[:require]].flatten.compact << ref) 74 end 75 result 76 end
# File lib/puppet/provider/package/dnfmodule.rb 130 def reset 131 execute([command(:dnf), 'module', 'reset', '-d', '0', '-e', self.class.error_level, '-y', @resource[:name]]) 132 end
# File lib/puppet/provider/file/windows.rb 143 def resolved_path 144 path = file() 145 # under POSIX, :manage means use lchown - i.e. operate on the link 146 return path.to_s if resource[:links] == :manage 147 148 # otherwise, use chown -- that will resolve the link IFF it is a link 149 # otherwise it will operate on the path 150 Puppet::FileSystem.symlink?(path) ? Puppet::FileSystem.readlink(path) : path.to_s 151 end
# File lib/puppet/type/resources.rb 133 def resource_type 134 unless defined?(@resource_type) 135 type = Puppet::Type.type(self[:name]) 136 unless type 137 raise Puppet::DevError, _("Could not find resource type") 138 end 139 @resource_type = type 140 end 141 @resource_type 142 end
# File lib/puppet/provider/service/daemontools.rb 181 def restart 182 svc "-t", self.service 183 end
# File lib/puppet/provider/service/init.rb 169 def restartcmd 170 (@resource[:hasrestart] == :true) && [initscript, :restart] 171 end
# File lib/puppet/type/file.rb 815 def retrieve 816 # This check is done in retrieve to ensure it happens before we try to use 817 # metadata in `copy_source_values`, but so it only fails the resource and not 818 # catalog validation (because that would be a breaking change from Puppet 4). 819 if Puppet::Util::Platform.windows? && parameter(:source) && 820 [:use, :use_when_creating].include?(self[:source_permissions]) 821 #TRANSLATORS "source_permissions => ignore" should not be translated 822 err_msg = _("Copying owner/mode/group from the source file on Windows is not supported; use source_permissions => ignore.") 823 if self[:owner] == nil || self[:group] == nil || self[:mode] == nil 824 # Fail on Windows if source permissions are being used and the file resource 825 # does not have mode owner, group, and mode all set (which would take precedence). 826 self.fail err_msg 827 else 828 # Warn if use source permissions is specified on Windows 829 self.warning err_msg 830 end 831 end 832 833 # `checksum_value` implies explicit management of all metadata, so skip metadata 834 # retrieval. Otherwise, if source is set, retrieve metadata for source. 835 if (source = parameter(:source)) && property(:checksum_value).nil? 836 source.copy_source_values 837 end 838 super 839 end
# File lib/puppet/functions/return.rb 11 def return_impl(value = nil) 12 file, line = Puppet::Pops::PuppetStack.top_of_stack 13 raise Puppet::Pops::Evaluator::Return.new(value, file, line) 14 end
# File lib/puppet/functions/reverse_each.rb 85 def reverse_each(iterable) 86 # produces an Iterable 87 Puppet::Pops::Types::Iterable.asserted_iterable(self, iterable, true).reverse_each 88 end
# File lib/puppet/functions/reverse_each.rb 90 def reverse_each_block(iterable, &block) 91 Puppet::Pops::Types::Iterable.asserted_iterable(self, iterable).reverse_each(&block) 92 nil 93 end
# File lib/puppet/provider/user/user_role_add.rb 124 def roles 125 user_attributes[:roles] if user_attributes 126 end
# File lib/puppet/provider/user/windows_adsi.rb 24 def roles=(value) 25 current = roles.split(',') 26 should = value.split(',') 27 28 add_list = should - current 29 Puppet::Util::Windows::User::set_rights(@resource[:name], add_list) unless add_list.empty? 30 31 if @resource[:role_membership] == :inclusive 32 remove_list = current - should 33 Puppet::Util::Windows::User::remove_rights(@resource[:name], remove_list) unless remove_list.empty? 34 end 35 end
# File lib/puppet/provider/package/gem.rb 188 def rubygem_version(command) 189 command_options = ["--version"] 190 self.class.execute_gem_command(command, command_options) 191 end
# File lib/puppet/provider/exec/posix.rb 53 def run(command, check = false) 54 if resource[:umask] 55 Puppet::Util::withumask(resource[:umask]) { super(command, check) } 56 else 57 super(command, check) 58 end 59 end
# File lib/puppet/provider/package/pkgutil.rb 150 def run_pkgutil(resource, *args) 151 # Allow source to be one or more URLs pointing to a repository that all 152 # get passed to pkgutil via one or more -t options 153 if resource[:source] 154 sources = [resource[:source]].flatten 155 pkguti(*[sources.map{|src| [ "-t", src ]}, *args].flatten) 156 else 157 pkguti(*args.flatten) 158 end 159 end
preseeds answers to dpkg-set-selection from the “responsefile”
# File lib/puppet/provider/package/apt.rb 197 def run_preseed 198 response = @resource[:responsefile] 199 if response && Puppet::FileSystem.exist?(response) 200 self.info(_("Preseeding %{response} to debconf-set-selections") % { response: response }) 201 202 preseed response 203 else 204 self.info _("No responsefile specified or non existent, not preseeding anything") 205 end 206 end
# File lib/puppet/provider/service/openbsd.rb 79 def running? 80 output = execute([command(:rcctl), "check", @resource[:name]], 81 :failonfail => false, :combine => false, :squelch => false).chomp 82 return true if output =~ /\(ok\)/ 83 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 403 def salt=(value) 404 if (Puppet::Util::Package.versioncmp(self.class.get_os_version, '10.7') > 0) 405 assert_full_pbkdf2_password 406 407 sleep 3 408 flush_dscl_cache 409 users_plist = get_users_plist(@resource.name) 410 shadow_hash_data = get_shadow_hash_data(users_plist) 411 set_salted_pbkdf2(users_plist, shadow_hash_data, 'salt', value) 412 flush_dscl_cache 413 end 414 end
Scan a structure that looks like the package type 'install_options' structure for all hashes that have a specific key.
@api private @param options [Array<String | Hash>, nil] The options structure. If the
options are nil an empty array will be returned.
@param key [String] The key to look for in all contained hashes @return [Array<String>] All hash values with the given key.
# File lib/puppet/provider/package/yum.rb 369 def scan_options(options, key) 370 return [] unless options.is_a?(Enumerable) 371 values = options.map do | repo | 372 value = if repo.is_a?(String) 373 next unless repo.include?('=') 374 Hash[*repo.strip.split('=')] # make it a hash 375 else 376 repo 377 end 378 value[key] 379 end 380 values.compact.uniq 381 end
# File lib/puppet/functions/scanf.rb 37 def scanf(data, format) 38 result = data.scanf(format) 39 if block_given? 40 result = yield(result) 41 end 42 result 43 end
# File lib/puppet/provider/service/init.rb 138 def search(name) 139 paths.each do |path| 140 fqname = File.join(path,name) 141 if Puppet::FileSystem.exist? fqname 142 return fqname 143 else 144 self.debug("Could not find #{name} in #{path}") 145 end 146 end 147 148 paths.each do |path| 149 fqname_sh = File.join(path,"#{name}.sh") 150 if Puppet::FileSystem.exist? fqname_sh 151 return fqname_sh 152 else 153 self.debug("Could not find #{name}.sh in #{path}") 154 end 155 end 156 raise Puppet::Error, "Could not find init script for '#{name}'" 157 end
# File lib/puppet/functions/empty.rb 53 def sensitive_string_empty(str) 54 str.unwrap.empty? 55 end
returns the full path of this service when enabled (ie in the service directory)
# File lib/puppet/provider/service/daemontools.rb 102 def service 103 File.join(self.servicedir, resource[:name]) 104 end
Use either a specified command or the default for our provider.
@return [Puppet::Util::Execution::ProcessOutput]
# File lib/puppet/provider/service/service.rb 58 def service_command(type, fof = true) 59 c = @resource[type] 60 if c 61 cmd = [c] 62 else 63 cmd = [send("#{type}cmd")].flatten 64 end 65 service_execute(type, cmd, fof) 66 end
# File lib/puppet/provider/service/init.rb 173 def service_execute(type, command, fof = true, squelch = false, combine = true) 174 if type == :start && Facter.value(:osfamily) == "Solaris" 175 command = ["/usr/bin/ctrun -l child", command].flatten.join(" ") 176 end 177 super(type, command, fof, squelch, combine) 178 end
# File lib/puppet/provider/service/smf.rb 63 def service_exists? 64 self.service_fmri 65 true 66 rescue Puppet::ExecutionFailure 67 false 68 end
Returns the service's FMRI. We fail if multiple FMRIs correspond to @resource.
If the service does not exist or we fail to get any FMRIs from svcs, this method will raise a Puppet::Error
# File lib/puppet/provider/service/smf.rb 85 def service_fmri 86 return @fmri if @fmri 87 88 # `svcs -l` is better to use because we can detect service instances 89 # that have not yet been activated or enabled (i.e. it lets us detect 90 # services that svcadm has not yet touched). `svcs -H -o fmri` is a bit 91 # more limited. 92 lines = svcs("-l", @resource[:name]).chomp.lines.to_a 93 lines.select! { |line| line =~ /^fmri/ } 94 fmris = lines.map! { |line| line.split(' ')[-1].chomp } 95 unless fmris.length == 1 96 raise Puppet::Error, _("Failed to get the FMRI of the %{service} service: The pattern '%{service}' matches multiple FMRIs! These are the FMRIs it matches: %{all_fmris}") % { service: @resource[:name], all_fmris: fmris.join(', ') } 97 end 98 99 @fmri = fmris.first 100 end
Extract service name
# File lib/puppet/provider/service/freebsd.rb 41 def service_name 42 extract_value_name('service', 0, /# (\S+).*/, '\1') 43 end
# File lib/puppet/provider/service/smf.rb 149 def service_states 150 # Gets the current and next state of the service. We have a next state because SMF 151 # manages services asynchronously. If there is no 'next' state, svcs will put a '-' 152 # to indicate as such. 153 current_state, next_state = svcs("-H", "-o", "state,nstate", self.service_fmri).chomp.split(' ') 154 155 { 156 :current => current_state, 157 :next => next_state == "-" ? nil : next_state 158 } 159 end
find the service dir on this node
# File lib/puppet/provider/service/daemontools.rb 87 def servicedir 88 unless @servicedir 89 ["/service", "/etc/service","/var/lib/svscan"].each do |path| 90 if Puppet::FileSystem.exist?(path) 91 @servicedir = path 92 break 93 end 94 end 95 raise "Could not find service directory" unless @servicedir 96 end 97 @servicedir 98 end
# File lib/puppet/provider/user/directoryservice.rb 489 def set_attribute_with_dscl(dscl_command, path, username, keyname, value) 490 begin 491 dscl '.', dscl_command, "/#{path}/#{username}", keyname, value 492 rescue Puppet::ExecutionFailure => detail 493 raise Puppet::Error, "Could not set the dscl #{keyname} key with value: #{value} - #{detail.inspect}", detail.backtrace 494 end 495 end
This method accepts a passed value and one of three fields: 'salt', 'entropy', or 'iterations'. These fields correspond with the fields utilized in a PBKDF2 password hashing system (see en.wikipedia.org/wiki/PBKDF2 ) where 'entropy' is the password hash, 'salt' is the password hash salt value, and 'iterations' is an integer recommended to be > 10,000. The remaining arguments are the user's plist itself, and the shadow_hash_data hash containing the existing PBKDF2 values.
# File lib/puppet/provider/user/directoryservice.rb 647 def set_salted_pbkdf2(users_plist, shadow_hash_data, field, value) 648 shadow_hash_data = Hash.new unless shadow_hash_data 649 shadow_hash_data['SALTED-SHA512-PBKDF2'] = Hash.new unless shadow_hash_data['SALTED-SHA512-PBKDF2'] 650 case field 651 when 'salt', 'entropy' 652 shadow_hash_data['SALTED-SHA512-PBKDF2'][field] = Puppet::Util::Plist.string_to_blob(base64_decode_string(value)) 653 when 'iterations' 654 shadow_hash_data['SALTED-SHA512-PBKDF2'][field] = Integer(value) 655 else 656 raise Puppet::Error "Puppet has tried to set an incorrect field for the 'SALTED-SHA512-PBKDF2' hash. Acceptable fields are 'salt', 'entropy', or 'iterations'." 657 end 658 659 # on 10.8, this field *must* contain 8 stars, or authentication will 660 # fail. 661 users_plist['passwd'] = ('*' * 8) 662 663 # Convert shadow_hash_data to a binary plist, and call the 664 # set_shadow_hash_data method to serialize and write the data 665 # back to the user's plist. 666 binary_plist = self.class.convert_hash_to_binary(shadow_hash_data) 667 set_shadow_hash_data(users_plist, binary_plist) 668 end
Puppet
requires a salted-sha512 password hash for 10.7 users to be passed in Hex, but the embedded plist stores that value as a Base64 encoded string. This method converts the string and calls the set_shadow_hash_data
method to serialize and write the plist to disk.
# File lib/puppet/provider/user/directoryservice.rb 629 def set_salted_sha512(users_plist, shadow_hash_data, value) 630 unless shadow_hash_data 631 shadow_hash_data = Hash.new 632 shadow_hash_data['SALTED-SHA512'] = '' 633 end 634 shadow_hash_data['SALTED-SHA512'] = base64_decode_string(value) 635 binary_plist = self.class.convert_hash_to_binary(shadow_hash_data) 636 set_shadow_hash_data(users_plist, binary_plist) 637 end
Overrides the default implementation to do nothing. This type contains data from class/define parameters, but does not have actual parameters or properties at the Type level. We can simply ignore anything flagged as sensitive here, since any contained resources will handle that sensitivity themselves. There is no risk of this information leaking into reports, since no Component instances survive the graph transmutation.
# File lib/puppet/type/component.rb 83 def set_sensitive_parameters(sensitive_parameters) 84 end
This method will embed the binary plist data comprising the user's password hash (and Salt/Iterations value if the OS is 10.8 or greater) into the ShadowHashData key of the user's plist.
# File lib/puppet/provider/user/directoryservice.rb 587 def set_shadow_hash_data(users_plist, binary_plist) 588 binary_plist = Puppet::Util::Plist.string_to_blob(binary_plist) 589 if users_plist.has_key?('ShadowHashData') 590 users_plist['ShadowHashData'][0] = binary_plist 591 else 592 users_plist['ShadowHashData'] = [binary_plist] 593 end 594 write_and_import_shadow_hash_data(users_plist['ShadowHashData'].first) 595 end
Set the checksum, from another property. There are multiple properties that modify the contents of a file, and they need the ability to make sure that the checksum value is in sync.
# File lib/puppet/type/file.rb 844 def setchecksum(sum = nil) 845 if @parameters.include? :checksum 846 if sum 847 @parameters[:checksum].checksum = sum 848 else 849 # If they didn't pass in a sum, then tell checksum to 850 # figure it out. 851 currentvalue = @parameters[:checksum].retrieve 852 @parameters[:checksum].checksum = currentvalue 853 end 854 end 855 end
# File lib/puppet/provider/service/smf.rb 70 def setup_service 71 return unless @resource[:manifest] 72 return if self.service_exists? 73 74 Puppet.notice("Importing #{@resource[:manifest]} for #{@resource[:name]}") 75 svccfg(:import, @resource[:manifest]) 76 rescue Puppet::ExecutionFailure => detail 77 raise Puppet::Error.new( "Cannot config #{@resource[:name]} to enable it: #{detail}", detail ) 78 end
# File lib/puppet/provider/service/daemontools.rb 127 def setupservice 128 if resource[:manifest] 129 Puppet.notice "Configuring #{resource[:name]}" 130 command = [ resource[:manifest], resource[:name] ] 131 system("#{command}") 132 end 133 rescue Puppet::ExecutionFailure => detail 134 raise Puppet::Error.new( "Cannot config #{self.service} to enable it: #{detail}", detail) 135 end
Read in /etc/shadow, find the line for this user (skipping comments, because who knows) and return it No abstraction, all esoteric knowledge of file formats, yay
# File lib/puppet/provider/user/user_role_add.rb 178 def shadow_entry 179 return @shadow_entry if defined? @shadow_entry 180 @shadow_entry = File.readlines(target_file_path). 181 reject { |r| r =~ /^[^\w]/ }. 182 # PUP-229: don't suppress the empty fields 183 collect { |l| l.chomp.split(':', -1) }. 184 find { |user, _| user == @resource[:name] } 185 end
# File lib/puppet/provider/user/user_role_add.rb 31 def shell=(value) 32 check_valid_shell 33 set("shell", value) 34 end
Should this thing be a normal file? This is a relatively complex way of determining whether we're trying to create a normal file, and it's here so that the logic isn't visible in the content property.
# File lib/puppet/type/file.rb 860 def should_be_file? 861 return true if self[:ensure] == :file 862 863 # I.e., it's set to something like "directory" 864 return false if self[:ensure] && self[:ensure] != :present 865 866 # The user doesn't really care, apparently 867 if self[:ensure] == :present 868 return true unless stat 869 return(stat.ftype == "file" ? true : false) 870 end 871 872 # If we've gotten here, then :ensure isn't set 873 return true if self[:content] 874 return true if stat and stat.ftype == "file" 875 false 876 end
The hidden singleton lurks behind everyone
# File lib/puppet/util/metaid.rb 3 def singleton_class; class << self; self; end; end
# File lib/puppet/functions/slice.rb 71 def slice_Common(o, slice_size, filler, pblock) 72 serving_size = asserted_slice_serving_size(pblock, slice_size) 73 74 enumerator = o.each_slice(slice_size) 75 result = [] 76 if serving_size == 1 77 begin 78 if pblock 79 loop do 80 pblock.call(enumerator.next) 81 end 82 else 83 loop do 84 result << enumerator.next 85 end 86 end 87 rescue StopIteration 88 end 89 else 90 begin 91 loop do 92 a = enumerator.next 93 if a.size < serving_size 94 a = a.dup.fill(filler, a.length...serving_size) 95 end 96 pblock.call(*a) 97 end 98 rescue StopIteration 99 end 100 end 101 if pblock 102 o 103 else 104 result 105 end 106 end
# File lib/puppet/functions/slice.rb 65 def slice_Enumerable(enumerable, slice_size, &pblock) 66 enum = Puppet::Pops::Types::Iterable.asserted_iterable(self, enumerable) 67 result = slice_Common(enum, slice_size, nil, block_given? ? pblock : nil) 68 block_given? ? enumerable : result 69 end
# File lib/puppet/functions/slice.rb 60 def slice_Hash(hash, slice_size, &pblock) 61 result = slice_Common(hash, slice_size, [], block_given? ? pblock : nil) 62 block_given? ? hash : result 63 end
# File lib/puppet/functions/sort.rb 71 def sort_array(a, &block) 72 a.sort(&block) 73 end
# File lib/puppet/functions/sort.rb 67 def sort_string(s, &block) 68 sort_array(s.split(''), &block).join('') 69 end
# File lib/puppet/provider/package/apt.rb 259 def source 260 @source ||= @resource[:source] 261 end
# File lib/puppet/functions/split.rb 42 def split_Regexp(str, pattern) 43 str.split(pattern) 44 end
# File lib/puppet/functions/split.rb 46 def split_RegexpType(str, pattern) 47 str.split(pattern.regexp) 48 end
# File lib/puppet/functions/split.rb 38 def split_String(str, pattern) 39 str.split(Regexp.compile(pattern)) 40 end
This method basically just splits the multi-line input string into chunks based on lines that contain nothing but whitespace. It also strips any leading or trailing whitespace (including newlines) from the resulting strings and then returns them as an array.
# File lib/puppet/provider/package/nim.rb 207 def split_into_paragraphs(showres_output) 208 showres_output.split(/^\s*$/).map { |p| p.strip! } 209 end
# File lib/puppet/provider/package/hpux.rb 41 def standard_args 42 ["-x", "mount_all_filesystems=false"] 43 end
Run the 'start' parameter command, or the specified 'startcmd'.
# File lib/puppet/provider/service/base.rb 95 def start 96 service_command(:start) 97 nil 98 end
The command used to start. Generated if the 'binary' argument is passed.
# File lib/puppet/provider/service/base.rb 102 def startcmd 103 if @resource[:binary] 104 return @resource[:binary] 105 else 106 raise Puppet::Error, 107 "Services must specify a start command or a binary" 108 end 109 end
Stat our file. Depending on the value of the 'links' attribute, we use either 'stat' or 'lstat', and we expect the properties to use the resulting stat object accordingly (mostly by testing the 'ftype' value).
We use the initial value :needs_stat to ensure we only stat the file once, but can also keep track of a failed stat (@stat == nil). This also allows us to re-stat on demand by setting @stat = :needs_stat.
# File lib/puppet/type/file.rb 886 def stat 887 return @stat unless @stat == :needs_stat 888 889 method = :stat 890 891 # Files are the only types that support links 892 if (self.class.name == :file and self[:links] != :follow) or self.class.name == :tidy 893 method = :lstat 894 end 895 896 @stat = begin 897 Puppet::FileSystem.send(method, self[:path]) 898 rescue Errno::ENOENT 899 nil 900 rescue Errno::ENOTDIR 901 nil 902 rescue Errno::EACCES 903 warning _("Could not stat; permission denied") 904 nil 905 rescue Errno::EINVAL 906 warning _("Could not stat; invalid pathname") 907 nil 908 end 909 end
# File lib/puppet/type/file.rb 1048 def stat_needed 1049 @stat = :needs_stat 1050 end
Check if the process is running. Prefer the 'status' parameter, then 'statuscmd' method, then look in the process table. We give the object the option to not return a status command, which might happen if, for instance, it has an init script (and thus responds to 'statuscmd') but does not have 'hasstatus' enabled.
# File lib/puppet/provider/service/base.rb 68 def status 69 if @resource[:status] or statuscmd 70 # Don't fail when the exit status is not 0. 71 status = service_command(:status, false) 72 73 # Explicitly calling exitstatus to facilitate testing 74 if status.exitstatus == 0 75 return :running 76 else 77 return :stopped 78 end 79 else 80 pid = getpid 81 if pid 82 self.debug "PID is #{pid}" 83 return :running 84 else 85 return :stopped 86 end 87 end 88 end
There is no default command, which causes other methods to be used
# File lib/puppet/provider/service/base.rb 91 def statuscmd 92 end
# File lib/puppet/functions/step.rb 89 def step(iterable, step) 90 # produces an Iterable 91 Puppet::Pops::Types::Iterable.asserted_iterable(self, iterable, true).step(step) 92 end
# File lib/puppet/functions/step.rb 94 def step_block(iterable, step, &block) 95 Puppet::Pops::Types::Iterable.asserted_iterable(self, iterable).step(step, &block) 96 nil 97 end
Stop the service. If a 'stop' parameter is specified, it takes precedence; otherwise checks if the object responds to a 'stopcmd' method, and if so runs that; otherwise, looks for the process in the process table. This method will generally not be overridden by submodules.
# File lib/puppet/provider/service/base.rb 116 def stop 117 if @resource[:stop] or stopcmd 118 service_command(:stop) 119 nil 120 else 121 pid = getpid 122 unless pid 123 self.info _("%{name} is not running") % { name: self.name } 124 return false 125 end 126 begin 127 output = kill pid 128 rescue Puppet::ExecutionFailure 129 @resource.fail Puppet::Error, "Could not kill #{self.name}, PID #{pid}: #{output}", $! 130 end 131 return true 132 end 133 end
There is no default command, which causes other methods to be used
# File lib/puppet/provider/service/base.rb 136 def stopcmd 137 end
# File lib/puppet/functions/empty.rb 57 def string_empty(str) 58 str.empty? 59 end
# File lib/puppet/functions/index.rb 154 def string_index(str, match) 155 str.index(match) 156 end
# File lib/puppet/functions/length.rb 36 def string_length(s) 37 s.length 38 end
# File lib/puppet/type/file/checksum.rb 24 def sum(content) 25 content = content.is_a?(Puppet::Pops::Types::PBinaryType::Binary) ? content.binary_buffer : content 26 type = digest_algorithm 27 "{#{type}}" + send(type, content) 28 end
# File lib/puppet/type/file/checksum.rb 30 def sum_file(path) 31 type = digest_algorithm 32 method = type.to_s + "_file" 33 "{#{type}}" + send(method, path).to_s 34 end
# File lib/puppet/type/file/checksum.rb 36 def sum_stream(&block) 37 type = digest_algorithm 38 method = type.to_s + "_stream" 39 checksum = send(method, &block) 40 "{#{type}}#{checksum}" 41 end
# File lib/puppet/network/formats.rb 75 def supported?(klass) 76 true 77 end
Returns true if the provider supports incomplete services.
# File lib/puppet/provider/service/smf.rb 103 def supports_incomplete_services? 104 Puppet::Util::Package.versioncmp(Facter.value(:operatingsystemrelease), '11.1') >= 0 105 end
# File lib/puppet/type/resources.rb 163 def system_users 164 %w{root nobody bin noaccess daemon sys} 165 end
This helper ensures that the enable state cache is always reset after a systemctl enable operation. A particular service state is not guaranteed after such an operation, so the cache must be emptied to prevent inconsistencies in the provider's believed state of the service and the actual state. @param action [String,Symbol] One of 'enable', 'disable', 'mask' or 'unmask'
# File lib/puppet/provider/service/systemd.rb 68 def systemctl_change_enable(action) 69 output = systemctl(action, '--', @resource[:name]) 70 rescue 71 raise Puppet::Error, "Could not #{action} #{self.name}: #{output}", $!.backtrace 72 ensure 73 @cached_enabled = nil 74 end
This helper makes it possible to test this on stub data without having to do too many crazy things!
# File lib/puppet/provider/user/user_role_add.rb 171 def target_file_path 172 "/etc/shadow" 173 end
# File lib/puppet/face/help.rb 133 def template_for(face, action) 134 if action.nil? 135 erb('face.erb') 136 else 137 erb('action.erb') 138 end 139 end
@deprecated because the exit status is not returned, use service_execute
instead
# File lib/puppet/provider/service/service.rb 24 def texecute(type, command, fof = true, squelch = false, combine = true) 25 begin 26 execute(command, :failonfail => fof, :override_locale => false, :squelch => squelch, :combine => combine) 27 rescue Puppet::ExecutionFailure => detail 28 @resource.fail Puppet::Error, "Could not #{type} #{@resource.ref}: #{detail}", detail 29 end 30 nil 31 end
# File lib/puppet/functions/then.rb 73 def then(arg) 74 return nil if arg.nil? 75 yield(arg) 76 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 107 def tidy?(path, stat) 108 basename = File.basename(path) 109 flags = File::FNM_DOTMATCH | File::FNM_PATHNAME 110 return(value.find {|pattern| File.fnmatch(pattern, basename, flags) } ? true : false) 111 end
We want our title to just be the whole reference, rather than @title.
# File lib/puppet/type/component.rb 54 def title 55 ref 56 end
# File lib/puppet/type/component.rb 58 def title=(str) 59 @reference = Puppet::Resource.new(str) 60 end
# File lib/puppet/util/log/destinations.rb 224 def to_native(level) 225 Puppet::Util::Windows::EventLog.to_native(level) 226 end
# File lib/puppet/type/file.rb 911 def to_resource 912 resource = super 913 resource.delete(:target) if resource[:target] == :notlink 914 resource 915 end
# File lib/puppet/type/component.rb 71 def to_s 72 reference.to_s 73 end
# File lib/puppet/provider/user/user_role_add.rb 91 def transition(type) 92 cmd = [command(:modify)] 93 cmd << "-K" << "type=#{type}" 94 cmd += add_properties 95 cmd << @resource[:name] 96 end
# File lib/puppet/functions/tree_each.rb 173 def tree_Enumerable1(enum, options = {}, &block) 174 iterator(enum, options).each {|_, v| yield(v) } 175 enum 176 end
# File lib/puppet/functions/tree_each.rb 178 def tree_Enumerable2(enum, options = {}, &block) 179 iterator(enum, options).each {|path, v| yield(path, v) } 180 enum 181 end
# File lib/puppet/functions/tree_each.rb 183 def tree_Iterable(enum, options = {}, &block) 184 Puppet::Pops::Types::Iterable.on(iterator(enum, options)) 185 end
# File lib/puppet/provider/user/hpux.rb 81 def trusted 82 # Check to see if the HP-UX box is running in trusted compute mode 83 # UID for root should always be 0 84 trusted_sys = exec_getprpw('root','-m uid') 85 if trusted_sys.chomp == "uid=0" 86 return true 87 else 88 return false 89 end 90 end
# File lib/puppet/functions/type.rb 61 def type_detailed(value, _ = nil) 62 Puppet::Pops::Types::TypeCalculator.infer_set(value) 63 end
# File lib/puppet/functions/type.rb 69 def type_generalized(value, _) 70 Puppet::Pops::Types::TypeCalculator.infer(value).generalize 71 end
# File lib/puppet/face/node/clean.rb 98 def type_is_ensurable(resource) 99 if (type = Puppet::Type.type(resource.restype)) && type.validattr?(:ensure) 100 return true 101 else 102 type = environment.known_resource_types.find_definition(resource.restype) 103 return true if type && type.arguments.keys.include?('ensure') 104 end 105 return false 106 end
# File lib/puppet/functions/compare.rb 122 def type_label(x) 123 Puppet::Pops::Model::ModelLabelProvider.new.label(x) 124 end
# File lib/puppet/functions/type.rb 65 def type_parameterized(value, _) 66 Puppet::Pops::Types::TypeCalculator.infer(value) 67 end
@deprecated because the exitstatus is not returned, use service_command
instead
# File lib/puppet/provider/service/service.rb 34 def ucommand(type, fof = true) 35 c = @resource[type] 36 if c 37 cmd = [c] 38 else 39 cmd = [send("#{type}cmd")].flatten 40 end 41 texecute(type, cmd, fof) 42 end
# File lib/puppet/provider/user/useradd.rb 57 def uid 58 return localuid if @resource.forcelocal? 59 get(:uid) 60 end
We use users and groups interchangeably, so use the same methods for both (the type expects different methods, so we have to oblige).
# File lib/puppet/provider/file/posix.rb 17 def uid2name(id) 18 return id.to_s if id.is_a?(Symbol) or id.is_a?(String) 19 return nil if id > Puppet[:maximum_uid].to_i 20 21 begin 22 user = Etc.getpwuid(id) 23 rescue TypeError, ArgumentError 24 return nil 25 end 26 27 if user.uid == "" 28 return nil 29 else 30 return user.name 31 end 32 end
# File lib/puppet/provider/user/windows_adsi.rb 158 def uid=(value) 159 fail "uid is read-only" 160 end
# File lib/puppet/provider/service/upstart.rb 323 def unbalanced_parens_on(line) 324 line.count('(') - line.count(')') 325 end
# File lib/puppet/provider/service/upstart.rb 311 def uncomment(line) 312 line.gsub(/^(\s*)#+/, '\1') 313 end
# File lib/puppet/provider/service/upstart.rb 344 def uncomment_start_block_in(text) 345 parens = 0 346 text.lines.map do |line| 347 if line.match(COMMENTED_START_ON) || parens > 0 348 parens += unbalanced_parens_on(remove_trailing_comments_from_commented_line_of(line)) 349 uncomment(line) 350 else 351 line 352 end 353 end.join('') 354 end
For compatibility reasons - return true rather than error on undef (Yes, it is strange, but undef was passed as empty string in 3.x API)
# File lib/puppet/functions/empty.rb 76 def undef_empty(x) 77 true 78 end
# File lib/puppet/provider/package/dpkg.rb 184 def unhold 185 Tempfile.open('puppet_dpkg_set_selection') do |tmpfile| 186 tmpfile.write("#{@resource[:name]} install\n") 187 tmpfile.flush 188 execute([:dpkg, "--set-selections"], :failonfail => false, :combine => false, :stdinfile => tmpfile.path.to_s) 189 end 190 end
# File lib/puppet/provider/package/aix.rb 80 def uninstall 81 # Automatically process dependencies when installing/uninstalling 82 # with the -g option to installp. 83 installp "-gu", @resource[:name] 84 85 # installp will return an exit code of zero even if it didn't uninstall 86 # anything... so let's make sure it worked. 87 unless query().nil? 88 self.fail _("Failed to uninstall package '%{name}'") % { name: @resource[:name] } 89 end 90 end
# File lib/puppet/provider/package/gem.rb 290 def uninstall_options 291 join_options(resource[:uninstall_options]) 292 end
# File lib/puppet/functions/unique.rb 125 def unique_array(array,&block) 126 array.uniq(&block) 127 end
# File lib/puppet/functions/unique.rb 111 def unique_hash(hash, &block) 112 block = lambda {|v| v } unless block_given? 113 result = Hash.new {|h, k| h[k] = {:keys =>[], :values =>[]} } 114 hash.each_pair do |k,v| 115 rc = result[ block.call(v) ] 116 rc[:keys] << k 117 rc[:values] << v 118 end 119 # reduce the set of possibly duplicated value entries 120 inverted = {} 121 result.each_pair {|k,v| inverted[v[:keys]] = v[:values].uniq } 122 inverted 123 end
# File lib/puppet/functions/unique.rb 129 def unique_iterable(iterable, &block) 130 Puppet::Pops::Types::Iterable.on(iterable).uniq(&block) 131 end
# File lib/puppet/functions/unique.rb 107 def unique_string(string, &block) 108 string.split('').uniq(&block).join('') 109 end
# File lib/puppet/provider/service/systemd.rb 176 def unmask 177 systemctl_change_enable(:unmask) 178 end
# File lib/puppet/provider/package/aix.rb 166 def update 167 self.install(false) 168 end
# File lib/puppet/provider/service/upstart.rb 100 def upstart_version 101 @upstart_version ||= initctl("--version").match(/initctl \(upstart ([^\)]*)\)/)[1] 102 end
# File lib/puppet/provider/user/windows_adsi.rb 16 def user 17 @user ||= Puppet::Util::Windows::ADSI::User.new(@resource[:name]) 18 end
# File lib/puppet/provider/user/user_role_add.rb 68 def user_attributes 69 @user_attributes ||= UserAttr.get_attributes_by_name(@resource[:name]) 70 end
Make sure we don't purge users with specific uids
# File lib/puppet/type/resources.rb 145 def user_check(resource) 146 return true unless self[:name] == "user" 147 return true unless self[:unless_system_user] 148 resource[:audit] = :uid 149 current_values = resource.retrieve_resource 150 current_uid = current_values[resource.property(:uid)] 151 unless_uids = self[:unless_uid] 152 153 return false if system_users.include?(resource[:name]) 154 return false if unless_uids && unless_uids.include?(current_uid) 155 if current_uid.is_a?(String) 156 # Windows user; is a system user if any regex matches. 157 WINDOWS_SYSTEM_SID_REGEXES.none? { |regex| current_uid =~ regex } 158 else 159 current_uid > self[:unless_system_user] 160 end 161 end
# File lib/puppet/provider/user/directoryservice.rb 471 def users_plist_dir 472 '/var/db/dslocal/nodes/Default/users' 473 end
# File lib/puppet/provider/file/windows.rb 85 def validate 86 if [:owner, :group, :mode].any?{|p| resource[p]} and !supports_acl?(resource[:path]) 87 resource.fail(_("Can only manage owner, group, and mode on filesystems that support Windows ACLs, such as NTFS")) 88 end 89 end
# File lib/puppet/reports/store.rb 62 def validate_host(host) 63 if host =~ Regexp.union(/[#{SEPARATOR}]/, /\A\.\.?\Z/) 64 raise ArgumentError, _("Invalid node name %{host}") % { host: host.inspect } 65 end 66 end
# File lib/puppet/provider/service/windows.rb 168 def validate_logon_credentials 169 unless Puppet::Util::Windows::User::localsystem?(@normalized_logon_account) 170 raise Puppet::Error.new("\"#{@normalized_logon_account}\" is not a valid account") unless @logonaccount_information && [:SidTypeUser, :SidTypeWellKnownGroup].include?(@logonaccount_information.account_type) 171 172 user_rights = Puppet::Util::Windows::User::get_rights(@logonaccount_information.domain_account) unless Puppet::Util::Windows::User::default_system_account?(@normalized_logon_account) 173 raise Puppet::Error.new("\"#{@normalized_logon_account}\" has the 'Log On As A Service' right set to denied.") if user_rights =~ /SeDenyServiceLogonRight/ 174 raise Puppet::Error.new("\"#{@normalized_logon_account}\" is missing the 'Log On As A Service' right.") unless user_rights.nil? || user_rights =~ /SeServiceLogonRight/ 175 end 176 177 is_a_predefined_local_account = Puppet::Util::Windows::User::default_system_account?(@normalized_logon_account) || @normalized_logon_account == 'LocalSystem' 178 account_info = @normalized_logon_account.split("\\") 179 able_to_logon = Puppet::Util::Windows::User.password_is?(account_info[1], @resource[:logonpassword], account_info[0]) unless is_a_predefined_local_account 180 raise Puppet::Error.new("The given password is invalid for user '#{@normalized_logon_account}'.") unless is_a_predefined_local_account || able_to_logon 181 end
@api private
# File lib/puppet/face/parser.rb 211 def validate_manifest(manifest = nil) 212 env = Puppet.lookup(:current_environment) 213 loaders = Puppet::Pops::Loaders.new(env) 214 215 Puppet.override( {:loaders => loaders } , _('For puppet parser validate')) do 216 begin 217 validation_environment = manifest ? env.override_with(:manifest => manifest) : env 218 validation_environment.check_for_reparse 219 validation_environment.known_resource_types.clear 220 rescue Puppet::ParseError => parse_error 221 return parse_error 222 end 223 end 224 225 nil 226 end
# File lib/puppet/provider/group/groupadd.rb 77 def validate_members(members) 78 members.each do |member| 79 member.split(',').each do |user| 80 Etc.getpwnam(user.strip) 81 end 82 end 83 end
This only gets called if there is a value to validate, but not if it's absent
# File lib/puppet/provider/package/windows.rb 119 def validate_source(value) 120 fail(_("The source parameter cannot be empty when using the Windows provider.")) if value.empty? 121 end
@api private
# File lib/puppet/face/epp.rb 479 def validate_template(template) 480 parser = Puppet::Pops::Parser::EvaluatingParser::EvaluatingEppParser.new() 481 parser.parse_file(template) 482 true 483 rescue => detail 484 Puppet.log_exception(detail) 485 false 486 end
@api private
# File lib/puppet/face/epp.rb 489 def validate_template_string(source) 490 parser = Puppet::Pops::Parser::EvaluatingParser::EvaluatingEppParser.new() 491 parser.parse_string(source, '<stdin>') 492 true 493 rescue => detail 494 Puppet.log_exception(detail) 495 false 496 end
# File lib/puppet/provider/exec/shell.rb 22 def validatecmd(command) 23 true 24 end
# File lib/puppet/functions/values.rb 22 def values(hsh) 23 hsh.values 24 end
# File lib/puppet/provider/package/pkgng.rb 146 def version 147 @property_hash[:version] 148 end
# File lib/puppet/provider/package/pkgng.rb 150 def version= 151 pkg(['install', '-qfy', "#{resource[:name]}-#{resource[:version]}"]) 152 end
# File lib/puppet/provider/service/upstart.rb 207 def version_is_post_0_9_0 208 Puppet::Util::Package.versioncmp(upstart_version, "0.9.0") >= 0 209 end
# File lib/puppet/provider/service/upstart.rb 199 def version_is_pre_0_6_7 200 Puppet::Util::Package.versioncmp(upstart_version, "0.6.7") == -1 201 end
# File lib/puppet/provider/service/upstart.rb 203 def version_is_pre_0_9_0 204 Puppet::Util::Package.versioncmp(upstart_version, "0.9.0") == -1 205 end
# File lib/puppet/functions/versioncmp.rb 33 def versioncmp(a, b) 34 Puppet::Util::Package.versioncmp(a, b) 35 end
Wait for the service to transition into the specified state before returning. This is necessary due to the asynchronous nature of SMF services. desired_states should include only online, offline, disabled, or uninitialized. See PUP-5474 for long-term solution to this issue.
# File lib/puppet/provider/service/smf.rb 165 def wait(*desired_states) 166 Timeout.timeout(60) do 167 loop do 168 states = self.service_states 169 break if desired_states.include?(states[:current]) && states[:next].nil? 170 Kernel.sleep(1) 171 end 172 end 173 rescue Timeout::Error 174 raise Puppet::Error.new("Timed out waiting for #{@resource[:name]} to transition states") 175 end
# File lib/puppet/face/config.rb 97 def warn_default_section(section_name) 98 messages = [] 99 messages << _("No section specified; defaulting to '%{section_name}'.") % 100 { section_name: section_name } 101 #TRANSLATORS '--section' is a command line option and should not be translated 102 messages << _("Set the config section by using the `--section` flag.") 103 #TRANSLATORS `puppet config --section user print foo` is a command line example and should not be translated 104 messages << _("For example, `puppet config --section user print foo`.") 105 messages << _("For more information, see https://puppet.com/docs/puppet/latest/configuration.html") 106 107 Puppet.warning(messages.join("\n")) 108 end
# File lib/puppet/face/module/list.rb 106 def warn_unmet_dependencies(environment) 107 error_types = [:non_semantic_version, :version_mismatch, :missing] 108 109 @unmet_deps = {} 110 error_types.each do |type| 111 @unmet_deps[type] = Hash.new do |hash, key| 112 hash[key] = { :errors => [], :parent => nil } 113 end 114 end 115 116 # Prepare the unmet dependencies for display on the console. 117 environment.modules.sort_by {|mod| mod.name}.each do |mod| 118 unmet_grouped = Hash.new { |h,k| h[k] = [] } 119 unmet_grouped = mod.unmet_dependencies.inject(unmet_grouped) do |acc, dep| 120 acc[dep[:reason]] << dep 121 acc 122 end 123 unmet_grouped.each do |type, deps| 124 unless deps.empty? 125 unmet_grouped[type].sort_by { |dep| dep[:name] }.each do |dep| 126 dep_name = dep[:name].tr('/', '-') 127 installed_version = dep[:mod_details][:installed_version] 128 version_constraint = dep[:version_constraint] 129 parent_name = dep[:parent][:name].tr('/', '-') 130 parent_version = dep[:parent][:version] 131 132 msg = _("'%{parent_name}' (%{parent_version}) requires '%{dependency_name}' (%{dependency_version})") % { parent_name: parent_name, parent_version: parent_version, dependency_name: dep_name, dependency_version: version_constraint } 133 @unmet_deps[type][dep[:name]][:errors] << msg 134 @unmet_deps[type][dep[:name]][:parent] = { 135 :name => dep[:parent][:name], 136 :version => parent_version 137 } 138 @unmet_deps[type][dep[:name]][:version] = installed_version 139 end 140 end 141 end 142 end 143 144 # Display unmet dependencies by category. 145 error_display_order = [:non_semantic_version, :version_mismatch, :missing] 146 error_display_order.each do |type| 147 unless @unmet_deps[type].empty? 148 @unmet_deps[type].keys.sort.each do |dep| 149 name = dep.tr('/', '-') 150 errors = @unmet_deps[type][dep][:errors] 151 version = @unmet_deps[type][dep][:version] 152 153 msg = case type 154 when :version_mismatch 155 _("Module '%{name}' (v%{version}) fails to meet some dependencies:\n") % { name: name, version: version } 156 when :non_semantic_version 157 _("Non semantic version dependency %{name} (v%{version}):\n") % { name: name, version: version } 158 else 159 _("Missing dependency '%{name}':\n") % { name: name } 160 end 161 162 errors.each { |error_string| msg << " #{error_string}\n" } 163 Puppet.warning msg.chomp 164 end 165 end 166 end 167 end
# File lib/puppet/functions/warning.rb 11 def warning(scope, *values) 12 Puppet::Util::Log.log_func(scope, :warning, values) 13 end
# File lib/puppet/functions/with.rb 29 def with(*args) 30 yield(*args) 31 end
Write out the file. To write content, pass the property as an argument to delegate writing to; must implement a write
method that takes the file as an argument.
# File lib/puppet/type/file.rb 920 def write(property = nil) 921 remove_existing(:file) 922 923 mode = self.should(:mode) # might be nil 924 mode_int = mode ? symbolic_mode_to_int(mode, Puppet::Util::DEFAULT_POSIX_MODE) : nil 925 926 if write_temporary_file? 927 if self[:validate_cmd] 928 validate_callback = proc { |path| 929 output = Puppet::Util::Execution.execute(self[:validate_cmd].gsub(self[:validate_replacement], path), :failonfail => true, :combine => true) 930 output.split(/\n/).each { |line| 931 self.debug(line) 932 } 933 } 934 end 935 936 Puppet::Util.replace_file(self[:path], mode_int, staging_location: self[:staging_location], validate_callback: validate_callback) do |file| 937 file.binmode 938 devfail 'a property should have been provided if write_temporary_file? returned true' if property.nil? 939 content_checksum = property.write(file) 940 file.flush 941 begin 942 file.fsync 943 rescue NotImplementedError 944 # fsync may not be implemented by Ruby on all platforms, but 945 # there is absolutely no recovery path if we detect that. So, we just 946 # ignore the return code. 947 # 948 # However, don't be fooled: that is accepting that we are running in 949 # an unsafe fashion. If you are porting to a new platform don't stub 950 # that out. 951 end 952 953 fail_if_checksum_is_wrong(property, file.path, content_checksum) 954 end 955 else 956 umask = mode ? 000 : 022 957 Puppet::Util.withumask(umask) { ::File.open(self[:path], 'wb', mode_int ) { |f| property.write(f) if property } } 958 end 959 960 # make sure all of the modes are actually correct 961 property_fix 962 end
This method writes the ShadowHashData plist in a temporary file, then imports it using dsimport. macOS versions 10.15 and newer do not support directly managing binary plists, so we have to use an intermediary. dsimport is an archaic utilitary with hard-to-find documentation
See web.archive.org/web/20090106120111/http://support.apple.com/kb/TA21305?viewlocale=en_US for information regarding the dsimport syntax
# File lib/puppet/provider/user/directoryservice.rb 605 def write_and_import_shadow_hash_data(data_plist) 606 Tempfile.create("dsimport_#{@resource.name}", :encoding => Encoding::ASCII) do |dsimport_file| 607 dsimport_file.write <<-DSIMPORT 608 0x0A 0x5C 0x3A 0x2C dsRecTypeStandard:Users 2 dsAttrTypeStandard:RecordName base64:dsAttrTypeNative:ShadowHashData 609 #{@resource.name}:#{Base64.strict_encode64(data_plist)} 610 DSIMPORT 611 dsimport_file.flush 612 # Delete the user's existing ShadowHashData, since dsimport appends, not replaces 613 dscl('.', 'delete', "/Users/#{@resource.name}", 'ShadowHashData') 614 dsimport(dsimport_file.path, '/Local/Default', 'M') 615 end 616 end
This method is only called on version 10.7 or greater. On 10.7 machines, passwords are set using a salted-SHA512 hash, and on 10.8 machines, passwords are set using PBKDF2. It's possible to have users on 10.8 who have upgraded from 10.7 and thus have a salted-SHA512 password hash. If we encounter this, do what 10.8 does - remove that key and give them a 10.8-style PBKDF2 password.
# File lib/puppet/provider/user/directoryservice.rb 522 def write_password_to_users_plist(value) 523 users_plist = get_users_plist(@resource.name) 524 shadow_hash_data = get_shadow_hash_data(users_plist) 525 if self.class.get_os_version == '10.7' 526 set_salted_sha512(users_plist, shadow_hash_data, value) 527 else 528 # It's possible that a user could exist on the system and NOT have 529 # a ShadowHashData key (especially if the system was upgraded from 10.6). 530 # In this case, a conditional check is needed to determine if the 531 # shadow_hash_data variable is a Hash (it would be false if the key 532 # didn't exist for this user on the system). If the shadow_hash_data 533 # variable IS a Hash and contains the 'SALTED-SHA512' key (indicating an 534 # older 10.7-style password hash), it will be deleted and a newer 535 # 10.8-style (PBKDF2) password hash will be generated. 536 if (shadow_hash_data.class == Hash) && (shadow_hash_data.has_key?('SALTED-SHA512')) 537 shadow_hash_data.delete('SALTED-SHA512') 538 end 539 540 # Starting with macOS 11 Big Sur, the AuthenticationAuthority field 541 # could be missing entirely and without it the managed user cannot log in 542 if needs_sha512_pbkdf2_authentication_authority_to_be_added?(users_plist) 543 Puppet.debug("Adding 'SALTED-SHA512-PBKDF2' AuthenticationAuthority key for ShadowHash to user '#{@resource.name}'") 544 merge_attribute_with_dscl('Users', @resource.name, 'AuthenticationAuthority', ERB::Util.html_escape(SHA512_PBKDF2_AUTHENTICATION_AUTHORITY)) 545 end 546 547 set_salted_pbkdf2(users_plist, shadow_hash_data, 'entropy', value) 548 end 549 end
# File lib/puppet/provider/service/upstart.rb 380 def write_script_to(file, text) 381 Puppet::Util.replace_file(file, 0644) do |f| 382 f.write(text) 383 end 384 end
# File lib/puppet/type/file.rb 1097 def write_temporary_file? 1098 # Unfortunately we don't know the source file size before fetching it so 1099 # let's assume the file won't be empty. Why isn't it part of the metadata? 1100 (c = property(:content) and c.length) || @parameters[:source] 1101 end
# File lib/puppet/functions/yaml_data.rb 21 def yaml_data(options, context) 22 path = options['path'] 23 context.cached_file_data(path) do |content| 24 begin 25 data = Puppet::Util::Yaml.safe_load(content, [Symbol], path) 26 if data.is_a?(Hash) 27 Puppet::Pops::Lookup::HieraConfig.symkeys_to_string(data) 28 else 29 msg = _("%{path}: file does not contain a valid yaml hash" % { path: path }) 30 raise Puppet::DataBinding::LookupError, msg if Puppet[:strict] == :error && data != false 31 Puppet.warning(msg) 32 {} 33 end 34 rescue Puppet::Util::Yaml::YamlLoadError => ex 35 # YamlLoadErrors include the absolute path to the file, so no need to add that 36 raise Puppet::DataBinding::LookupError, _("Unable to parse %{message}") % { message: ex.message } 37 end 38 end 39 end
on zypper versions <1.0, the version option returns 1 some versions of zypper output on stderr
# File lib/puppet/provider/package/zypper.rb 48 def zypper_version 49 cmd = [self.class.command(:zypper),"--version"] 50 execute(cmd, { :failonfail => false, :combine => true}) 51 end