class Puppet::Settings
The class for handling configuration files.
Constants
- ALLOWED_SECTION_NAMES
The acceptable sections of the puppet.conf configuration file.
- DEPRECATION_REFS
- NONE
- PuppetOptionParser
local reference for convenience
- REQUIRED_APP_SETTINGS
These are the settings that every app is required to specify; there are reasonable defaults defined in application.rb.
- SETTING_TYPES
Attributes
Public Class Methods
This method is intended for puppet internal use only; it is a convenience method that returns reasonable application default settings values for a given run_mode.
# File lib/puppet/settings.rb 57 def self.app_defaults_for_run_mode(run_mode) 58 { 59 :name => run_mode.to_s, 60 :run_mode => run_mode.name, 61 :confdir => run_mode.conf_dir, 62 :codedir => run_mode.code_dir, 63 :vardir => run_mode.var_dir, 64 :publicdir => run_mode.public_dir, 65 :rundir => run_mode.run_dir, 66 :logdir => run_mode.log_dir, 67 } 68 end
A utility method (public, is used by application.rb and perhaps elsewhere) that munges a command-line option string into the format that Puppet.settings
expects. (This mostly has to deal with handling the “no-” prefix on flag/boolean options).
@param [String] opt the command line option that we are munging @param [String, TrueClass, FalseClass] val the value for the setting (as determined by the OptionParser)
# File lib/puppet/settings.rb 361 def self.clean_opt(opt, val) 362 # rewrite --[no-]option to --no-option if that's what was given 363 if opt =~ /\[no-\]/ and !val 364 opt = opt.gsub(/\[no-\]/,'no-') 365 end 366 # otherwise remove the [no-] prefix to not confuse everybody 367 opt = opt.gsub(/\[no-\]/, '') 368 [opt, val] 369 end
# File lib/puppet/settings.rb 70 def self.default_certname() 71 hostname = hostname_fact 72 domain = domain_fact 73 if domain and domain != "" 74 fqdn = [hostname, domain].join(".") 75 else 76 fqdn = hostname 77 end 78 fqdn.to_s.gsub(/\.$/, '') 79 end
# File lib/puppet/settings.rb 89 def self.default_config_file_name 90 "puppet.conf" 91 end
# File lib/puppet/settings.rb 85 def self.domain_fact() 86 Facter.value :domain 87 end
# File lib/puppet/settings.rb 81 def self.hostname_fact() 82 Facter.value :hostname 83 end
Create a new collection of config settings.
# File lib/puppet/settings.rb 134 def initialize 135 @config = {} 136 @shortnames = {} 137 138 @created = [] 139 140 # Keep track of set values. 141 @value_sets = { 142 :cli => Values.new(:cli, @config), 143 :memory => Values.new(:memory, @config), 144 :application_defaults => Values.new(:application_defaults, @config), 145 :overridden_defaults => Values.new(:overridden_defaults, @config), 146 } 147 @configuration_file = nil 148 149 # And keep a per-environment cache 150 @cache = Concurrent::Hash.new { |hash, key| hash[key] = Concurrent::Hash.new } 151 @values = Concurrent::Hash.new { |hash, key| hash[key] = Concurrent::Hash.new } 152 153 # The list of sections we've used. 154 @used = [] 155 156 @hooks_to_call_on_application_initialization = [] 157 @deprecated_setting_names = [] 158 @deprecated_settings_that_have_been_configured = [] 159 160 @translate = Puppet::Settings::ValueTranslator.new 161 @config_file_parser = Puppet::Settings::ConfigFile.new(@translate) 162 end
Public Instance Methods
Retrieve a config value @param param [Symbol] the name of the setting @return [Object] the value of the setting @api private
# File lib/puppet/settings.rb 168 def [](param) 169 if @deprecated_setting_names.include?(param) 170 issue_deprecation_warning(setting(param), "Accessing '#{param}' as a setting is deprecated.") 171 end 172 value(param) 173 end
Set a config value. This doesn't set the defaults, it sets the value itself. @param param [Symbol] the name of the setting @param value [Object] the new value of the setting @api private
# File lib/puppet/settings.rb 179 def []=(param, value) 180 if @deprecated_setting_names.include?(param) 181 issue_deprecation_warning(setting(param), "Modifying '#{param}' as a setting is deprecated.") 182 end 183 @value_sets[:memory].set(param, value) 184 unsafe_flush_cache 185 end
Generate the list of valid arguments, in a format that GetoptLong can understand, and add them to the passed option list.
# File lib/puppet/settings.rb 203 def addargs(options) 204 # Add all of the settings as valid options. 205 self.each { |name, setting| 206 setting.getopt_args.each { |args| options << args } 207 } 208 209 options 210 end
# File lib/puppet/settings.rb 372 def app_defaults_initialized? 373 @app_defaults_initialized 374 end
# File lib/puppet/settings.rb 711 def apply_metadata_from_section(section) 712 section.settings.each do |setting| 713 type = @config[setting.name] if setting.has_metadata? 714 if type 715 type.set_meta(setting.meta) 716 end 717 end 718 end
Is our setting a boolean setting?
# File lib/puppet/settings.rb 224 def boolean?(param) 225 param = param.to_sym 226 @config.include?(param) and @config[param].kind_of?(BooleanSetting) 227 end
Remove all set values, potentially skipping cli values.
# File lib/puppet/settings.rb 230 def clear 231 unsafe_clear 232 end
Clears all cached settings for a particular environment to ensure that changes to environment.conf are reflected in the settings if the environment timeout has expired.
param [String, Symbol] environment the name of environment to clear settings for
@api private
# File lib/puppet/settings.rb 266 def clear_environment_settings(environment) 267 268 if environment.nil? 269 return 270 end 271 272 @cache[environment.to_sym].clear 273 @values[environment.to_sym] = {} 274 end
# File lib/puppet/settings.rb 295 def clearused 296 @cache.clear 297 @used = [] 298 end
The order in which to search for values, without defaults.
@param environment [String,Symbol] symbolic reference to an environment name @param run_mode [Symbol] symbolic reference to a Puppet
run mode @return [Array<SearchPathElement>] @api private
# File lib/puppet/settings.rb 834 def configsearchpath(environment = nil, run_mode = preferred_run_mode) 835 searchpath = [ 836 SearchPathElement.new(:memory, :values), 837 SearchPathElement.new(:cli, :values), 838 ] 839 searchpath << SearchPathElement.new(environment.intern, :environment) if environment 840 841 if run_mode 842 if [:master, :server].include?(run_mode) 843 searchpath << SearchPathElement.new(:server, :section) 844 searchpath << SearchPathElement.new(:master, :section) 845 else 846 searchpath << SearchPathElement.new(run_mode, :section) 847 end 848 end 849 850 searchpath << SearchPathElement.new(:main, :section) 851 end
Define a group of settings.
@param [Symbol] section a symbol to use for grouping multiple settings together into a conceptual unit. This value
(and the conceptual separation) is not used very often; the main place where it will have a potential impact is when code calls Settings#use method. See docs on that method for further details, but basically that method just attempts to do any preparation that may be necessary before code attempts to leverage the value of a particular setting. This has the most impact for file/directory settings, where #use will attempt to "ensure" those files / directories.
@param [Hash] defs the settings to be defined. This argument is a hash of hashes; each key should be a symbol,
which is basically the name of the setting that you are defining. The value should be another hash that specifies the parameters for the particular setting. Legal values include: [:default] => not required; this is the value for the setting if no other value is specified (via cli, config file, etc.) For string settings this may include "variables", demarcated with $ or ${} which will be interpolated with values of other settings. The default value may also be a Proc that will be called only once to evaluate the default when the setting's value is retrieved. [:desc] => required; a description of the setting, used in documentation / help generation [:type] => not required, but highly encouraged! This specifies the data type that the setting represents. If you do not specify it, it will default to "string". Legal values include: :string - A generic string setting :boolean - A boolean setting; values are expected to be "true" or "false" :file - A (single) file path; puppet may attempt to create this file depending on how the settings are used. This type also supports additional options such as "mode", "owner", "group" :directory - A (single) directory path; puppet may attempt to create this file depending on how the settings are used. This type also supports additional options such as "mode", "owner", "group" :path - This is intended to be used for settings whose value can contain multiple directory paths, represented as strings separated by the system path separator (e.g. system path, module path, etc.). [:mode] => an (optional) octal value to be used as the permissions/mode for :file and :directory settings [:owner] => optional owner username/uid for :file and :directory settings [:group] => optional group name/gid for :file and :directory settings
# File lib/puppet/settings.rb 1003 def define_settings(section, defs) 1004 section = section.to_sym 1005 call = [] 1006 defs.each do |name, hash| 1007 raise ArgumentError, _("setting definition for '%{name}' is not a hash!") % { name: name } unless hash.is_a? Hash 1008 1009 name = name.to_sym 1010 hash[:name] = name 1011 hash[:section] = section 1012 raise ArgumentError, _("Setting %{name} is already defined") % { name: name } if @config.include?(name) 1013 tryconfig = newsetting(hash) 1014 short = tryconfig.short 1015 if short 1016 other = @shortnames[short] 1017 if other 1018 raise ArgumentError, _("Setting %{name} is already using short name '%{short}'") % { name: other.name, short: short } 1019 end 1020 @shortnames[short] = tryconfig 1021 end 1022 @config[name] = tryconfig 1023 1024 # Collect the settings that need to have their hooks called immediately. 1025 # We have to collect them so that we can be sure we're fully initialized before 1026 # the hook is called. 1027 if tryconfig.has_hook? 1028 if tryconfig.call_hook_on_define? 1029 call << tryconfig 1030 elsif tryconfig.call_hook_on_initialize? 1031 @hooks_to_call_on_application_initialization |= [ tryconfig ] 1032 end 1033 end 1034 1035 @deprecated_setting_names << name if tryconfig.deprecated? 1036 end 1037 1038 call.each do |setting| 1039 setting.handle(self.value(setting.name)) 1040 end 1041 end
Return a value's description.
# File lib/puppet/settings.rb 428 def description(name) 429 obj = @config[name.to_sym] 430 if obj 431 obj.desc 432 else 433 nil 434 end 435 end
Iterate over each section name.
# File lib/puppet/settings.rb 440 def eachsection 441 yielded = [] 442 @config.each_value do |object| 443 section = object.section 444 unless yielded.include? section 445 yield section 446 yielded << section 447 end 448 end 449 end
Clear @cache, @used and the Environment.
Whenever an object is returned by Settings
, a copy is stored in @cache. As long as Setting attributes that determine the content of returned objects remain unchanged, Settings
can keep returning objects from @cache without re-fetching or re-generating them.
Whenever a Settings
attribute changes, such as @values or @preferred_run_mode, this method must be called to clear out the caches so that updated objects will be returned.
# File lib/puppet/settings.rb 286 def flush_cache 287 unsafe_flush_cache 288 end
# File lib/puppet/settings.rb 539 def generate_config 540 puts to_config 541 true 542 end
# File lib/puppet/settings.rb 544 def generate_manifest 545 puts to_manifest 546 true 547 end
# File lib/puppet/settings.rb 300 def global_defaults_initialized?() 301 @global_defaults_initialized 302 end
Handle a command-line argument.
# File lib/puppet/settings.rb 460 def handlearg(opt, value = nil) 461 @cache.clear 462 463 if value.is_a?(FalseClass) 464 value = "false" 465 elsif value.is_a?(TrueClass) 466 value = "true" 467 end 468 469 value &&= @translate[value] 470 str = opt.sub(/^--/,'') 471 472 bool = true 473 newstr = str.sub(/^no-/, '') 474 if newstr != str 475 str = newstr 476 bool = false 477 end 478 str = str.intern 479 480 if @config[str].is_a?(Puppet::Settings::BooleanSetting) 481 if value == "" or value.nil? 482 value = bool 483 end 484 end 485 486 s = @config[str] 487 if s 488 @deprecated_settings_that_have_been_configured << s if s.completely_deprecated? 489 end 490 491 @value_sets[:cli].set(str, value) 492 unsafe_flush_cache 493 end
# File lib/puppet/settings.rb 495 def include?(name) 496 name = name.intern if name.is_a? String 497 @config.include?(name) 498 end
# File lib/puppet/settings.rb 376 def initialize_app_defaults(app_defaults) 377 REQUIRED_APP_SETTINGS.each do |key| 378 raise SettingsError, "missing required app default setting '#{key}'" unless app_defaults.has_key?(key) 379 end 380 381 app_defaults.each do |key, value| 382 if key == :run_mode 383 self.preferred_run_mode = value 384 else 385 @value_sets[:application_defaults].set(key, value) 386 unsafe_flush_cache 387 end 388 end 389 apply_metadata 390 call_hooks_deferred_to_application_initialization 391 issue_deprecations 392 393 REQUIRED_APP_SETTINGS.each do |key| 394 create_ancestors(Puppet[key]) 395 end 396 397 @app_defaults_initialized = true 398 end
# File lib/puppet/settings.rb 304 def initialize_global_settings(args = [], require_config = true) 305 raise Puppet::DevError, _("Attempting to initialize global default settings more than once!") if global_defaults_initialized? 306 307 # The first two phases of the lifecycle of a puppet application are: 308 # 1) Parse the command line options and handle any of them that are 309 # registered, defined "global" puppet settings (mostly from defaults.rb). 310 # 2) Parse the puppet config file(s). 311 312 parse_global_options(args) 313 parse_config_files(require_config) 314 315 @global_defaults_initialized = true 316 end
Generate the list of valid arguments, in a format that OptionParser can understand, and add them to the passed option list.
# File lib/puppet/settings.rb 214 def optparse_addargs(options) 215 # Add all of the settings as valid options. 216 self.each { |name, setting| 217 options << setting.optparse_args 218 } 219 220 options 221 end
Create a new default value for the given setting. The default overrides are higher precedence than the defaults given in defaults.rb, but lower precedence than any other values for the setting. This allows one setting `a` to change the default of setting `b`, but still allow a user to provide a value for setting `b`.
@param param [Symbol] the name of the setting @param value [Object] the new default value for the setting @api private
# File lib/puppet/settings.rb 196 def override_default(param, value) 197 @value_sets[:overridden_defaults].set(param, value) 198 unsafe_flush_cache 199 end
# File lib/puppet/settings.rb 580 def parse_config(text, file = "text") 581 begin 582 data = @config_file_parser.parse_file(file, text, ALLOWED_SECTION_NAMES) 583 rescue => detail 584 Puppet.log_exception(detail, "Could not parse #{file}: #{detail}") 585 return 586 end 587 588 # If we get here and don't have any data, we just return and don't muck with the current state of the world. 589 return if data.nil? 590 591 # If we get here then we have some data, so we need to clear out any 592 # previous settings that may have come from config files. 593 unsafe_clear(false, false) 594 595 # Screen settings which have been deprecated and removed from puppet.conf 596 # but are still valid on the command line and/or in environment.conf 597 screen_non_puppet_conf_settings(data) 598 599 # Make note of deprecated settings we will warn about later in initialization 600 record_deprecations_from_puppet_conf(data) 601 602 # And now we can repopulate with the values from our last parsing of the config files. 603 @configuration_file = data 604 605 # Determine our environment, if we have one. 606 if @config[:environment] 607 env = self.value(:environment).to_sym 608 else 609 env = NONE 610 end 611 612 # Call any hooks we should be calling. 613 value_sets = value_sets_for(env, preferred_run_mode) 614 @config.values.select(&:has_hook?).each do |setting| 615 value_sets.each do |source| 616 if source.include?(setting.name) 617 # We still have to use value to retrieve the value, since 618 # we want the fully interpolated value, not $vardir/lib or whatever. 619 # This results in extra work, but so few of the settings 620 # will have associated hooks that it ends up being less work this 621 # way overall. 622 if setting.call_hook_on_initialize? 623 @hooks_to_call_on_application_initialization |= [ setting ] 624 else 625 setting.handle(ChainedValues.new( 626 preferred_run_mode, 627 env, 628 value_sets, 629 @config).interpolate(setting.name)) 630 end 631 break 632 end 633 end 634 end 635 636 call_hooks_deferred_to_application_initialization :ignore_interpolation_dependency_errors => true 637 apply_metadata 638 end
This method just turns a file into a new ConfigFile::Conf instance @param file [String] absolute path to the configuration file @return [Puppet::Settings::ConfigFile::Conf] @api private
# File lib/puppet/settings.rb 1239 def parse_file(file, allowed_sections = []) 1240 @config_file_parser.parse_file(file, read_file(file), allowed_sections) 1241 end
Patches the value for a param in a section. This method is required to support the use case of unifying –dns-alt-names and –dns_alt_names in the certificate face. Ideally this should be cleaned up. See PUP-3684 for more information. For regular use of setting a value, the method `[]=` should be used. @api private
# File lib/puppet/settings.rb 967 def patch_value(param, value, type) 968 if @value_sets[type] 969 @value_sets[type].set(param, value) 970 unsafe_flush_cache 971 end 972 end
Iterate across all of the objects in a given section.
# File lib/puppet/settings.rb 775 def persection(section) 776 section = section.to_sym 777 self.each { |name, obj| 778 if obj.section == section 779 yield obj 780 end 781 } 782 end
The currently configured run mode that is preferred for constructing the application configuration.
# File lib/puppet/settings.rb 560 def preferred_run_mode 561 @preferred_run_mode_name || :user 562 end
PRIVATE! This only exists because we need a hook to validate the run mode when it's being set, and
it should never, ever, ever, ever be called from outside of this file.
This method is also called when –run_mode MODE is used on the command line to set the default
@param mode [String|Symbol] the name of the mode to have in effect @api private
# File lib/puppet/settings.rb 570 def preferred_run_mode=(mode) 571 mode = mode.to_s.downcase.intern 572 raise ValidationError, "Invalid run mode '#{mode}'" unless [:server, :master, :agent, :user].include?(mode) 573 @preferred_run_mode_name = mode 574 # Changing the run mode has far-reaching consequences. Flush any cached 575 # settings so they will be re-generated. 576 flush_cache 577 mode 578 end
Prints the contents of a config file with the available config settings, or it prints a single value of a config setting.
# File lib/puppet/settings.rb 502 def print_config_options 503 if Puppet::Util::Log.sendlevel?(:info) 504 Puppet::Util::Log.newdestination(:console) 505 message = (_("Using --configprint is deprecated. Use 'puppet config <subcommand>' instead.")) 506 Puppet.deprecation_warning(message) 507 end 508 509 env = value(:environment) 510 val = value(:configprint) 511 if val == "all" 512 hash = {} 513 each do |name, obj| 514 val = value(name,env) 515 val = val.inspect if val == "" 516 hash[name] = val 517 end 518 hash.sort { |a,b| a[0].to_s <=> b[0].to_s }.each do |name, v| 519 puts "#{name} = #{v}" 520 end 521 else 522 val.split(/\s*,\s*/).sort.each do |v| 523 if include?(v) 524 #if there is only one value, just print it for back compatibility 525 if v == val 526 puts value(val,env) 527 break 528 end 529 puts "#{v} = #{value(v,env)}" 530 else 531 puts "invalid setting: #{v}" 532 return false 533 end 534 end 535 end 536 true 537 end
# File lib/puppet/settings.rb 549 def print_configs 550 return print_config_options if value(:configprint) != "" 551 return generate_config if value(:genconfig) 552 generate_manifest if value(:genmanifest) 553 end
# File lib/puppet/settings.rb 555 def print_configs? 556 (value(:configprint) != "" || value(:genconfig) || value(:genmanifest)) && true 557 end
Reparse our config file, if necessary.
# File lib/puppet/settings.rb 785 def reparse_config_files 786 if files 787 filename = any_files_changed? 788 if filename 789 Puppet.notice "Config file #{filename} changed; triggering re-parse of all config files." 790 parse_config_files 791 reuse 792 end 793 end 794 end
# File lib/puppet/settings.rb 819 def reuse 820 return unless defined?(@used) 821 new = @used 822 @used = [] 823 self.use(*new) 824 end
The order in which to search for values.
@param environment [String,Symbol] symbolic reference to an environment name @param run_mode [Symbol] symbolic reference to a Puppet
run mode @return [Array<SearchPathElement>] @api private
# File lib/puppet/settings.rb 859 def searchpath(environment = nil, run_mode = preferred_run_mode) 860 searchpath = configsearchpath(environment, run_mode) 861 searchpath << SearchPathElement.new(:application_defaults, :values) 862 searchpath << SearchPathElement.new(:overridden_defaults, :values) 863 end
Get values from a search path entry. @api private
# File lib/puppet/settings.rb 914 def searchpath_values(source) 915 case source.type 916 when :values 917 @value_sets[source.name] 918 when :section 919 section = @configuration_file.sections[source.name] if @configuration_file 920 if section 921 ValuesFromSection.new(source.name, section) 922 end 923 when :environment 924 ValuesFromEnvironmentConf.new(source.name) 925 else 926 raise Puppet::DevError, _("Unknown searchpath case: %{source_type} for the %{source} settings path element.") % { source_type: source.type, source: source} 927 end 928 end
# File lib/puppet/settings.rb 881 def service_group_available? 882 return @service_group_available if defined?(@service_group_available) 883 884 if self[:group] 885 group = Puppet::Type.type(:group).new :name => self[:group], :audit => :ensure 886 887 if group.suitable? 888 @service_group_available = group.exists? 889 else 890 raise Puppet::Error, (_("Cannot manage group permissions, because the provider for '%{name}' is not functional") % { name: group }) 891 end 892 else 893 @service_group_available = false 894 end 895 end
# File lib/puppet/settings.rb 865 def service_user_available? 866 return @service_user_available if defined?(@service_user_available) 867 868 if self[:user] 869 user = Puppet::Type.type(:user).new :name => self[:user], :audit => :ensure 870 871 if user.suitable? 872 @service_user_available = user.exists? 873 else 874 raise Puppet::Error, (_("Cannot manage owner permissions, because the provider for '%{name}' is not functional") % { name: user }) 875 end 876 else 877 @service_user_available = false 878 end 879 end
Allow later inspection to determine if the setting was set on the command line, or through some other code path. Used for the `dns_alt_names` option during cert generate. –daniel 2011-10-18
@param param [String, Symbol] the setting to look up @return [Object, nil] the value of the setting or nil if unset
# File lib/puppet/settings.rb 903 def set_by_cli(param) 904 param = param.to_sym 905 @value_sets[:cli].lookup(param) 906 end
# File lib/puppet/settings.rb 908 def set_by_cli?(param) 909 !!set_by_cli(param) 910 end
Allow later inspection to determine if the setting was set by user config, rather than a default setting.
# File lib/puppet/settings.rb 932 def set_by_config?(param, environment = nil, run_mode = preferred_run_mode) 933 param = param.to_sym 934 configsearchpath(environment, run_mode).any? do |source| 935 vals = searchpath_values(source) 936 if vals 937 vals.lookup(param) 938 end 939 end 940 end
Allow later inspection to determine if the setting was set in a specific section
@param param [String, Symbol] the setting to look up @param section [Symbol] the section in which to look up the setting @return [Object, nil] the value of the setting or nil if unset
# File lib/puppet/settings.rb 948 def set_in_section(param, section) 949 param = param.to_sym 950 vals = searchpath_values(SearchPathElement.new(section, :section)) 951 if vals 952 vals.lookup(param) 953 end 954 end
# File lib/puppet/settings.rb 956 def set_in_section?(param, section) 957 !!set_in_section(param, section) 958 end
Returns a given setting by name @param name [Symbol] The name of the setting to fetch @return [Puppet::Settings::BaseSetting] The setting object
# File lib/puppet/settings.rb 454 def setting(param) 455 param = param.to_sym 456 @config[param] 457 end
# File lib/puppet/settings.rb 93 def stringify_settings(section, settings = :all) 94 values_from_the_selected_section = 95 values(nil, section.to_sym) 96 97 loader_settings = { 98 :environmentpath => values_from_the_selected_section.interpolate(:environmentpath), 99 :basemodulepath => values_from_the_selected_section.interpolate(:basemodulepath), 100 } 101 102 Puppet.override(Puppet.base_context(loader_settings), 103 _("New environment loaders generated from the requested section.")) do 104 # And now we can lookup values that include those from environments configured from 105 # the requested section 106 values = values(Puppet[:environment].to_sym, section.to_sym) 107 108 to_be_rendered = {} 109 settings = Puppet.settings.to_a.collect(&:first) if settings == :all 110 settings.sort.each do |setting_name| 111 to_be_rendered[setting_name] = values.print(setting_name.to_sym) 112 end 113 114 stringifyhash(to_be_rendered) 115 end 116 end
# File lib/puppet/settings.rb 118 def stringifyhash(hash) 119 newhash = {} 120 hash.each do |key, val| 121 key = key.to_s 122 if val.is_a? Hash 123 newhash[key] = stringifyhash(val) 124 elsif val.is_a? Symbol 125 newhash[key] = val.to_s 126 else 127 newhash[key] = val 128 end 129 end 130 newhash 131 end
Convert the settings we manage into a catalog full of resources that model those settings.
# File lib/puppet/settings.rb 1044 def to_catalog(*sections) 1045 sections = nil if sections.empty? 1046 1047 catalog = Puppet::Resource::Catalog.new("Settings", Puppet::Node::Environment::NONE) 1048 @config.keys.find_all { |key| @config[key].is_a?(FileSetting) }.each do |key| 1049 file = @config[key] 1050 next if file.value.nil? 1051 next unless (sections.nil? or sections.include?(file.section)) 1052 resource = file.to_resource 1053 next unless resource 1054 next if catalog.resource(resource.ref) 1055 1056 Puppet.debug {"Using settings: adding file resource '#{key}': '#{resource.inspect}'"} 1057 1058 catalog.add_resource(resource) 1059 end 1060 1061 add_user_resources(catalog, sections) 1062 add_environment_resources(catalog, sections) 1063 1064 catalog 1065 end
Convert our list of config settings into a configuration file.
# File lib/puppet/settings.rb 1068 def to_config 1069 str = %{The configuration file for #{Puppet.run_mode.name}. Note that this file 1070 is likely to have unused settings in it; any setting that's 1071 valid anywhere in Puppet can be in any config file, even if it's not used. 1072 1073 Every section can specify three special parameters: owner, group, and mode. 1074 These parameters affect the required permissions of any files specified after 1075 their specification. Puppet will sometimes use these parameters to check its 1076 own configured state, so they can be used to make Puppet a bit more self-managing. 1077 1078 The file format supports octothorpe-commented lines, but not partial-line comments. 1079 1080 Generated on #{Time.now}. 1081 1082 }.gsub(/^/, "# ") 1083 1084 # Add a section heading that matches our name. 1085 str += "[#{preferred_run_mode}]\n" 1086 eachsection do |section| 1087 persection(section) do |obj| 1088 str += obj.to_config + "\n" unless obj.name == :genconfig 1089 end 1090 end 1091 1092 return str 1093 end
Convert to a parseable manifest
# File lib/puppet/settings.rb 1096 def to_manifest 1097 catalog = to_catalog 1098 catalog.resource_refs.collect do |ref| 1099 catalog.resource(ref).to_manifest 1100 end.join("\n\n") 1101 end
Create the necessary objects to use a section. This is idempotent; you can 'use' a section as many times as you want.
# File lib/puppet/settings.rb 1105 def use(*sections) 1106 if Puppet[:settings_catalog] 1107 sections = sections.collect { |s| s.to_sym } 1108 sections = sections.reject { |s| @used.include?(s) } 1109 1110 Puppet.warning(":master section deprecated in favor of :server section") if sections.include?(:master) 1111 1112 # add :server if sections include :master or :master if sections include :server 1113 sections |= [:master, :server] if (sections & [:master, :server]).any? 1114 1115 sections = sections.collect { |s| s.to_sym } 1116 sections = sections.reject { |s| @used.include?(s) } 1117 1118 return if sections.empty? 1119 1120 Puppet.debug { "Applying settings catalog for sections #{sections.join(', ')}" } 1121 1122 begin 1123 catalog = to_catalog(*sections).to_ral 1124 rescue => detail 1125 Puppet.log_and_raise(detail, "Could not create resources for managing Puppet's files and directories in sections #{sections.inspect}: #{detail}") 1126 end 1127 1128 catalog.host_config = false 1129 catalog.apply do |transaction| 1130 if transaction.any_failed? 1131 report = transaction.report 1132 status_failures = report.resource_statuses.values.select { |r| r.failed? } 1133 status_fail_msg = status_failures. 1134 collect(&:events). 1135 flatten. 1136 select { |event| event.status == 'failure' }. 1137 collect { |event| "#{event.resource}: #{event.message}" }.join("; ") 1138 1139 raise "Got #{status_failures.length} failure(s) while initializing: #{status_fail_msg}" 1140 end 1141 end 1142 1143 sections.each { |s| @used << s } 1144 @used.uniq! 1145 else 1146 Puppet.debug("Skipping settings catalog for sections #{sections.join(', ')}") 1147 end 1148 end
# File lib/puppet/settings.rb 1150 def valid?(param) 1151 param = param.to_sym 1152 @config.has_key?(param) 1153 end
Find the correct value using our search path.
@param param [String, Symbol] The value to look up @param environment [String, Symbol] The environment to check for the value @param bypass_interpolation [true, false] Whether to skip interpolation
@return [Object] The looked up value
@raise [InterpolationError]
# File lib/puppet/settings.rb 1179 def value(param, environment = nil, bypass_interpolation = false) 1180 environment &&= environment.to_sym 1181 value_sym(param.to_sym, environment, bypass_interpolation) 1182 end
Find the correct value using symbols and our search path.
@param param [Symbol] The value to look up @param environment [Symbol] The environment to check for the value @param bypass_interpolation [true, false] Whether to skip interpolation
@return [Object] The looked up value
@raise [InterpolationError]
# File lib/puppet/settings.rb 1193 def value_sym(param, environment = nil, bypass_interpolation = false) 1194 # Check the cache first. It needs to be a per-environment 1195 # cache so that we don't spread values from one env 1196 # to another. 1197 cached_env = @cache[environment || NONE] 1198 1199 # Avoid two lookups in cache_env unless val is nil. When it is, it's important 1200 # to check if the key is included so that further processing (that will result 1201 # in nil again) is avoided. 1202 val = cached_env[param] 1203 return val if !val.nil? || cached_env.include?(param) 1204 1205 # Short circuit to nil for undefined settings. 1206 return nil unless @config.include?(param) 1207 1208 vals = values(environment, preferred_run_mode) 1209 val = bypass_interpolation ? vals.lookup(param) : vals.interpolate(param) 1210 cached_env[param] = val 1211 val 1212 end
Retrieve an object that can be used for looking up values of configuration settings.
@param environment [Symbol] The name of the environment in which to lookup @param section [Symbol] The name of the configuration section in which to lookup @return [Puppet::Settings::ChainedValues] An object to perform lookups @api public
# File lib/puppet/settings.rb 1162 def values(environment, section) 1163 @values[environment][section] ||= ChainedValues.new( 1164 section, 1165 environment, 1166 value_sets_for(environment, section), 1167 @config) 1168 end
(#15337) All of the logic to determine the configuration file to use
should be centralized into this method. The simplified approach is:
-
If there is an explicit configuration file, use that. (–confdir or –config)
-
If we're running as a root process, use the system puppet.conf (usually /etc/puppetlabs/puppet/puppet.conf)
-
Otherwise, use the user puppet.conf (usually ~/.puppetlabs/etc/puppet/puppet.conf)
@api private @todo this code duplicates {Puppet::Util::RunMode#which_dir} as described
in {https://projects.puppetlabs.com/issues/16637 #16637}
# File lib/puppet/settings.rb 1227 def which_configuration_file 1228 if explicit_config_file? or Puppet.features.root? then 1229 return main_config_file 1230 else 1231 return user_config_file 1232 end 1233 end
Private Instance Methods
# File lib/puppet/settings.rb 1300 def add_environment_resources(catalog, sections) 1301 configured_environment = self[:environment] 1302 1303 if configured_environment == "production" && !production_environment_exists? 1304 environment_path = self[:environmentpath] 1305 first_environment_path = environment_path.split(File::PATH_SEPARATOR).first 1306 1307 if Puppet::FileSystem.exist?(first_environment_path) 1308 production_environment_path = File.join(first_environment_path, configured_environment) 1309 parameters = { :ensure => 'directory' } 1310 parameters[:mode] = '0750' 1311 if Puppet.features.root? 1312 parameters[:owner] = Puppet[:user] if service_user_available? 1313 parameters[:group] = Puppet[:group] if service_group_available? 1314 end 1315 catalog.add_resource(Puppet::Resource.new(:file, production_environment_path, :parameters => parameters)) 1316 end 1317 end 1318 end
# File lib/puppet/settings.rb 1332 def add_user_resources(catalog, sections) 1333 return unless Puppet.features.root? 1334 return if Puppet::Util::Platform.windows? 1335 return unless self[:mkusers] 1336 1337 @config.each do |name, setting| 1338 next unless setting.respond_to?(:owner) 1339 next unless sections.nil? or sections.include?(setting.section) 1340 1341 user = setting.owner 1342 if user && user != "root" && catalog.resource(:user, user).nil? 1343 resource = Puppet::Resource.new(:user, user, :parameters => {:ensure => :present}) 1344 resource[:gid] = self[:group] if self[:group] 1345 catalog.add_resource resource 1346 end 1347 group = setting.group 1348 if group && ! %w{root wheel}.include?(group) && catalog.resource(:group, group).nil? 1349 catalog.add_resource Puppet::Resource.new(:group, group, :parameters => {:ensure => :present}) 1350 end 1351 end 1352 end
Checks to see if any of the config files have been modified @return the filename of the first file that is found to have changed, or
nil if no files have changed
# File lib/puppet/settings.rb 811 def any_files_changed? 812 files.each do |file| 813 return file.to_str if file.changed? 814 end 815 nil 816 end
# File lib/puppet/settings.rb 696 def apply_metadata 697 # We have to do it in the reverse of the search path, 698 # because multiple sections could set the same value 699 # and I'm too lazy to only set the metadata once. 700 if @configuration_file 701 searchpath(nil, preferred_run_mode).reverse_each do |source| 702 section = @configuration_file.sections[source.name] if source.type == :section 703 if section 704 apply_metadata_from_section(section) 705 end 706 end 707 end 708 end
# File lib/puppet/settings.rb 414 def call_hooks_deferred_to_application_initialization(options = {}) 415 @hooks_to_call_on_application_initialization.each do |setting| 416 begin 417 setting.handle(self.value(setting.name)) 418 rescue InterpolationError => err 419 raise InterpolationError, err.message, err.backtrace unless options[:ignore_interpolation_dependency_errors] 420 #swallow. We're not concerned if we can't call hooks because dependencies don't exist yet 421 #we'll get another chance after application defaults are initialized 422 end 423 end 424 end
Private method for internal test use only; allows to do a comprehensive clear of all settings between tests.
@return nil
# File lib/puppet/settings.rb 1368 def clear_everything_for_tests() 1369 unsafe_clear(true, true) 1370 @configuration_file = nil 1371 @global_defaults_initialized = false 1372 @app_defaults_initialized = false 1373 end
This method is here to get around some life-cycle issues. We need to be able to determine the config file name before the settings / defaults are fully loaded. However, we also need to respect any overrides of this value that the user may have specified on the command line.
The easiest way to do this is to attempt to read the setting, and if we catch an error (meaning that it hasn't been set yet), we'll fall back to the default value.
# File lib/puppet/settings.rb 685 def config_file_name 686 begin 687 return self[:config_file_name] if self[:config_file_name] 688 rescue SettingsError 689 # This just means that the setting wasn't explicitly set on the command line, so we will ignore it and 690 # fall through to the default name. 691 end 692 return self.class.default_config_file_name 693 end
Create ancestor directories.
@param dir [String] absolute path for a required application default directory @api private
# File lib/puppet/settings.rb 405 def create_ancestors(dir) 406 parent_dir = File.dirname(dir) 407 408 if !File.exist?(parent_dir) 409 FileUtils.mkdir_p(parent_dir) 410 end 411 end
# File lib/puppet/settings.rb 1376 def explicit_config_file? 1377 # Figure out if the user has provided an explicit configuration file. If 1378 # so, return the path to the file, if not return nil. 1379 # 1380 # The easiest way to determine whether an explicit one has been specified 1381 # is to simply attempt to evaluate the value of ":config". This will 1382 # obviously be successful if they've passed an explicit value for :config, 1383 # but it will also result in successful interpolation if they've only 1384 # passed an explicit value for :confdir. 1385 # 1386 # If they've specified neither, then the interpolation will fail and we'll 1387 # get an exception. 1388 # 1389 begin 1390 return true if self[:config] 1391 rescue InterpolationError 1392 # This means we failed to interpolate, which means that they didn't 1393 # explicitly specify either :config or :confdir... so we'll fall out to 1394 # the default value. 1395 return false 1396 end 1397 end
# File lib/puppet/settings.rb 1280 def issue_deprecation_warning(setting, msg = nil) 1281 name = setting.name 1282 ref = DEPRECATION_REFS.find { |params,reference| params.include?(name) } 1283 ref = ref[1] if ref 1284 case 1285 when msg 1286 msg << " #{ref}" if ref 1287 Puppet.deprecation_warning(msg) 1288 when setting.completely_deprecated? 1289 message = _("Setting %{name} is deprecated.") % { name: name } 1290 message += " #{ref}" 1291 Puppet.deprecation_warning(message, "setting-#{name}") 1292 when setting.allowed_on_commandline? 1293 #TRANSLATORS 'puppet.conf' is a file name and should not be translated 1294 message = _("Setting %{name} is deprecated in puppet.conf.") % { name: name } 1295 message += " #{ref}" 1296 Puppet.deprecation_warning(message, "puppet-conf-setting-#{name}") 1297 end 1298 end
# File lib/puppet/settings.rb 1274 def issue_deprecations 1275 @deprecated_settings_that_have_been_configured.each do |setting| 1276 issue_deprecation_warning(setting) 1277 end 1278 end
# File lib/puppet/settings.rb 663 def main_config_file 664 if explicit_config_file? 665 return self[:config] 666 else 667 return File.join(Puppet::Util::RunMode[:server].conf_dir, config_file_name) 668 end 669 end
Create a new setting. The value is passed in because it's used to determine what kind of setting we're creating, but the value itself might be either a default or a value, so we can't actually assign it.
See define_settings
for documentation on the legal values for the “:type” option.
# File lib/puppet/settings.rb 748 def newsetting(hash) 749 klass = nil 750 hash[:section] = hash[:section].to_sym if hash[:section] 751 752 type = hash[:type] 753 if type 754 klass = SETTING_TYPES[type] 755 unless klass 756 raise ArgumentError, _("Invalid setting type '%{type}'") % { type: type } 757 end 758 hash.delete(:type) 759 else 760 # The only implicit typing we still do for settings is to fall back to "String" type if they didn't explicitly 761 # specify a type. Personally I'd like to get rid of this too, and make the "type" option mandatory... but 762 # there was a little resistance to taking things quite that far for now. --cprice 2012-03-19 763 klass = StringSetting 764 end 765 hash[:settings] = self 766 setting = klass.new(hash) 767 768 setting 769 end
Parse the configuration file. Just provides thread safety.
# File lib/puppet/settings.rb 641 def parse_config_files(require_config = true) 642 file = which_configuration_file 643 if Puppet::FileSystem.exist?(file) 644 begin 645 text = read_file(file) 646 rescue => detail 647 message = _("Could not load %{file}: %{detail}") % { file: file, detail: detail} 648 if require_config 649 Puppet.log_and_raise(detail, message) 650 else 651 Puppet.log_exception(detail, message) 652 return 653 end 654 end 655 else 656 return 657 end 658 659 parse_config(text, file) 660 end
This method is called during application bootstrapping. It is responsible for parsing all of the command line options and initializing the settings accordingly.
It will ignore options that are not defined in the global puppet settings list, because they may be valid options for the specific application that we are about to launch… however, at this point in the bootstrapping lifecycle, we don't yet know what that application is.
# File lib/puppet/settings.rb 324 def parse_global_options(args) 325 # Create an option parser 326 option_parser = PuppetOptionParser.new 327 option_parser.ignore_invalid_options = true 328 329 # Add all global options to it. 330 self.optparse_addargs([]).each do |option| 331 option_parser.on(*option) do |arg| 332 opt, val = Puppet::Settings.clean_opt(option[0], arg) 333 handlearg(opt, val) 334 end 335 end 336 337 option_parser.on('--run_mode', 338 "The effective 'run mode' of the application: server, agent, or user.", 339 :REQUIRED) do |arg| 340 Puppet.settings.preferred_run_mode = arg 341 end 342 343 option_parser.parse(args) 344 345 # remove run_mode options from the arguments so that later parses don't think 346 # it is an unknown option. 347 while option_index = args.index('--run_mode') do #rubocop:disable Lint/AssignmentInCondition 348 args.delete_at option_index 349 args.delete_at option_index 350 end 351 args.reject! { |arg| arg.start_with? '--run_mode=' } 352 end
# File lib/puppet/settings.rb 1320 def production_environment_exists? 1321 environment_path = self[:environmentpath] 1322 paths = environment_path.split(File::PATH_SEPARATOR) 1323 1324 paths.any? do |path| 1325 # If expected_path is a symlink, assume the source path is being managed 1326 # elsewhere, so accept it also as a valid production environment path 1327 expected_path = File.join(path, 'production') 1328 Puppet::FileSystem.directory?(expected_path) || Puppet::FileSystem.symlink?(expected_path) 1329 end 1330 end
Read the file in. @api private
# File lib/puppet/settings.rb 1361 def read_file(file) 1362 return Puppet::FileSystem.read(file, :encoding => 'utf-8') 1363 end
Record that we want to issue a deprecation warning later in the application initialization cycle when we have settings bootstrapped to the point where we can read the Puppet setting.
We are only recording warnings applicable to settings set in puppet.conf itself.
# File lib/puppet/settings.rb 1263 def record_deprecations_from_puppet_conf(puppet_conf) 1264 puppet_conf.sections.values.each do |section| 1265 section.settings.each do |conf_setting| 1266 setting = self.setting(conf_setting.name) 1267 if setting 1268 @deprecated_settings_that_have_been_configured << setting if setting.deprecated? 1269 end 1270 end 1271 end 1272 end
# File lib/puppet/settings.rb 1250 def screen_non_puppet_conf_settings(puppet_conf) 1251 puppet_conf.sections.values.each do |section| 1252 forbidden = section.settings.select { |setting| Puppet::Settings::EnvironmentConf::ENVIRONMENT_CONF_ONLY_SETTINGS.include?(setting.name) } 1253 raise(SettingsError, "Cannot set #{forbidden.map { |s| s.name }.join(", ")} settings in puppet.conf") if !forbidden.empty? 1254 end 1255 end
Remove all set values, potentially skipping cli values.
# File lib/puppet/settings.rb 235 def unsafe_clear(clear_cli = true, clear_application_defaults = false) 236 if clear_application_defaults 237 @value_sets[:application_defaults] = Values.new(:application_defaults, @config) 238 @app_defaults_initialized = false 239 end 240 241 if clear_cli 242 @value_sets[:cli] = Values.new(:cli, @config) 243 244 # Only clear the 'used' values if we were explicitly asked to clear out 245 # :cli values; otherwise, it may be just a config file reparse, 246 # and we want to retain this cli values. 247 @used = [] 248 end 249 250 @value_sets[:memory] = Values.new(:memory, @config) 251 @value_sets[:overridden_defaults] = Values.new(:overridden_defaults, @config) 252 253 @deprecated_settings_that_have_been_configured.clear 254 @values.clear 255 @cache.clear 256 end
# File lib/puppet/settings.rb 290 def unsafe_flush_cache 291 clearused 292 end
# File lib/puppet/settings.rb 672 def user_config_file 673 return File.join(Puppet::Util::RunMode[:user].conf_dir, config_file_name) 674 end
Yield each search source in turn.
# File lib/puppet/settings.rb 1355 def value_sets_for(environment, mode) 1356 searchpath(environment, mode).collect { |source| searchpath_values(source) }.compact 1357 end