The class for handling configuration files.
local reference for convenience
These are the settings that every app is required to specify; there are reasonable defaults defined in application.rb.
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, line 117 def [](param) if @deprecated_setting_names.include?(param) issue_deprecation_warning(setting(param), "Accessing '#{param}' as a setting is deprecated.") end value(param) 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, line 128 def []=(param, value) if @deprecated_setting_names.include?(param) issue_deprecation_warning(setting(param), "Modifying '#{param}' as a setting is deprecated.") end @value_sets[:memory].set(param, value) unsafe_flush_cache 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, line 152 def addargs(options) # Add all of the settings as valid options. self.each { |name, setting| setting.getopt_args.each { |args| options << args } } options end
# File lib/puppet/settings.rb, line 328 def app_defaults_initialized? @app_defaults_initialized end
# File lib/puppet/settings.rb, line 672 def apply_metadata_from_section(section) section.settings.each do |setting| if setting.has_metadata? && type = @config[setting.name] type.set_meta(setting.meta) end end end
Is our setting a boolean setting?
# File lib/puppet/settings.rb, line 173 def boolean?(param) param = param.to_sym @config.include?(param) and @config[param].kind_of?(BooleanSetting) end
Remove all set values, potentially skipping cli values.
# File lib/puppet/settings.rb, line 179 def clear unsafe_clear 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, line 215 def clear_environment_settings(environment) if environment.nil? return end @cache[environment.to_sym].clear @values[environment.to_sym] = {} end
# File lib/puppet/settings.rb, line 251 def clearused @cache.clear @used = [] 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, respresented 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, line 869 def define_settings(section, defs) section = section.to_sym call = [] defs.each do |name, hash| raise ArgumentError, "setting definition for '#{name}' is not a hash!" unless hash.is_a? Hash name = name.to_sym hash[:name] = name hash[:section] = section raise ArgumentError, "Setting #{name} is already defined" if @config.include?(name) tryconfig = newsetting(hash) if short = tryconfig.short if other = @shortnames[short] raise ArgumentError, "Setting #{other.name} is already using short name '#{short}'" end @shortnames[short] = tryconfig end @config[name] = tryconfig # Collect the settings that need to have their hooks called immediately. # We have to collect them so that we can be sure we're fully initialized before # the hook is called. if tryconfig.has_hook? if tryconfig.call_hook_on_define? call << tryconfig elsif tryconfig.call_hook_on_initialize? @hooks_to_call_on_application_initialization << tryconfig end end @deprecated_setting_names << name if tryconfig.deprecated? end call.each do |setting| setting.handle(self.value(setting.name)) end end
Return a value’s description.
# File lib/puppet/settings.rb, line 366 def description(name) if obj = @config[name.to_sym] obj.desc else nil end end
Iterate over each section name.
# File lib/puppet/settings.rb, line 377 def eachsection yielded = [] @config.each do |name, object| section = object.section unless yielded.include? section yield section yielded << section end end 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, line 235 def flush_cache unsafe_flush_cache end
# File lib/puppet/settings.rb, line 473 def generate_config puts to_config true end
# File lib/puppet/settings.rb, line 478 def generate_manifest puts to_manifest true end
# File lib/puppet/settings.rb, line 256 def global_defaults_initialized?() @global_defaults_initialized end
Handle a command-line argument.
# File lib/puppet/settings.rb, line 395 def handlearg(opt, value = nil) @cache.clear if value.is_a?(FalseClass) value = "false" elsif value.is_a?(TrueClass) value = "true" end value &&= @translate[value] str = opt.sub(/^--/,'') bool = true newstr = str.sub(/^no-/, '') if newstr != str str = newstr bool = false end str = str.intern if @config[str].is_a?(Puppet::Settings::BooleanSetting) if value == "" or value.nil? value = bool end end if s = @config[str] @deprecated_settings_that_have_been_configured << s if s.completely_deprecated? end @value_sets[:cli].set(str, value) unsafe_flush_cache end
# File lib/puppet/settings.rb, line 429 def include?(name) name = name.intern if name.is_a? String @config.include?(name) end
# File lib/puppet/settings.rb, line 332 def initialize_app_defaults(app_defaults) REQUIRED_APP_SETTINGS.each do |key| raise SettingsError, "missing required app default setting '#{key}'" unless app_defaults.has_key?(key) end app_defaults.each do |key, value| if key == :run_mode self.preferred_run_mode = value else @value_sets[:application_defaults].set(key, value) unsafe_flush_cache end end apply_metadata call_hooks_deferred_to_application_initialization issue_deprecations @app_defaults_initialized = true end
# File lib/puppet/settings.rb, line 260 def initialize_global_settings(args = []) raise Puppet::DevError, "Attempting to initialize global default settings more than once!" if global_defaults_initialized? # The first two phases of the lifecycle of a puppet application are: # 1) Parse the command line options and handle any of them that are # registered, defined "global" puppet settings (mostly from defaults.rb). # 2) Parse the puppet config file(s). parse_global_options(args) parse_config_files @global_defaults_initialized = true end
Return a given object’s file metadata.
# File lib/puppet/settings.rb, line 494 def metadata(param) if obj = @config[param.to_sym] and obj.is_a?(FileSetting) { :owner => obj.owner, :group => obj.group, :mode => obj.mode }.delete_if { |key, value| value.nil? } else nil end end
Make a directory with the appropriate user, group, and mode
# File lib/puppet/settings.rb, line 507 def mkdir(default) obj = get_config_file_default(default) Puppet::Util::SUIDManager.asuser(obj.owner, obj.group) do mode = obj.mode || 0750 Dir.mkdir(obj.value, mode) end 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, line 163 def optparse_addargs(options) # Add all of the settings as valid options. self.each { |name, setting| options << setting.optparse_args } options 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, line 145 def override_default(param, value) @value_sets[:overridden_defaults].set(param, value) unsafe_flush_cache end
Return all of the settings associated with a given section.
# File lib/puppet/settings.rb, line 538 def params(section = nil) if section section = section.intern if section.is_a? String @config.find_all { |name, obj| obj.section == section }.collect { |name, obj| name } else @config.keys end end
# File lib/puppet/settings.rb, line 551 def parse_config(text, file = "text") begin data = @config_file_parser.parse_file(file, text) rescue => detail Puppet.log_exception(detail, "Could not parse #{file}: #{detail}") return end # If we get here and don't have any data, we just return and don't muck with the current state of the world. return if data.nil? # If we get here then we have some data, so we need to clear out any # previous settings that may have come from config files. unsafe_clear(false, false) record_deprecations_from_puppet_conf(data) # And now we can repopulate with the values from our last parsing of the config files. @configuration_file = data # Determine our environment, if we have one. if @config[:environment] env = self.value(:environment).to_sym else env = "none" end # Call any hooks we should be calling. value_sets = value_sets_for(env, preferred_run_mode) @config.values.select(&:has_hook?).each do |setting| value_sets.each do |source| if source.include?(setting.name) # We still have to use value to retrieve the value, since # we want the fully interpolated value, not $vardir/lib or whatever. # This results in extra work, but so few of the settings # will have associated hooks that it ends up being less work this # way overall. if setting.call_hook_on_initialize? @hooks_to_call_on_application_initialization << setting else setting.handle(ChainedValues.new( preferred_run_mode, env, value_sets, @config).interpolate(setting.name)) end break end end end call_hooks_deferred_to_application_initialization :ignore_interpolation_dependency_errors => true apply_metadata 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, line 1092 def parse_file(file) @config_file_parser.parse_file(file, read_file(file)) end
Iterate across all of the objects in a given section.
# File lib/puppet/settings.rb, line 726 def persection(section) section = section.to_sym self.each { |name, obj| if obj.section == section yield obj end } end
The currently configured run mode that is preferred for constructing the application configuration.
# File lib/puppet/settings.rb, line 517 def preferred_run_mode @preferred_run_mode_name || :user 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, line 527 def preferred_run_mode=(mode) mode = mode.to_s.downcase.intern raise ValidationError, "Invalid run mode '#{mode}'" unless [:master, :agent, :user].include?(mode) @preferred_run_mode_name = mode # Changing the run mode has far-reaching consequences. Flush any cached # settings so they will be re-generated. flush_cache mode 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, line 442 def print_config_options env = value(:environment) val = value(:configprint) if val == "all" hash = {} each do |name, obj| val = value(name,env) val = val.inspect if val == "" hash[name] = val end hash.sort { |a,b| a[0].to_s <=> b[0].to_s }.each do |name, val| puts "#{name} = #{val}" end else val.split(/\s*,\s*/).sort.each do |v| if include?(v) #if there is only one value, just print it for back compatibility if v == val puts value(val,env) break end puts "#{v} = #{value(v,env)}" else puts "invalid setting: #{v}" return false end end end true end
# File lib/puppet/settings.rb, line 483 def print_configs return print_config_options if value(:configprint) != "" return generate_config if value(:genconfig) generate_manifest if value(:genmanifest) end
# File lib/puppet/settings.rb, line 489 def print_configs? (value(:configprint) != "" || value(:genconfig) || value(:genmanifest)) && true end
Reparse our config file, if necessary.
# File lib/puppet/settings.rb, line 736 def reparse_config_files if files if filename = any_files_changed? Puppet.notice "Config file #{filename} changed; triggering re-parse of all config files." parse_config_files reuse end end end
# File lib/puppet/settings.rb, line 769 def reuse return unless defined?(@used) new = @used @used = [] self.use(*new) end
The order in which to search for values.
# File lib/puppet/settings.rb, line 777 def searchpath(environment = nil) [:memory, :cli, environment, :run_mode, :main, :application_defaults, :overridden_defaults].compact end
Get a list of objects per section
# File lib/puppet/settings.rb, line 782 def sectionlist sectionlist = [] self.each { |name, obj| section = obj.section || "puppet" sections[section] ||= [] sectionlist << section unless sectionlist.include?(section) sections[section] << obj } return sectionlist, sections end
# File lib/puppet/settings.rb, line 806 def service_group_available? return @service_group_available if defined?(@service_group_available) if self[:group] group = Puppet::Type.type(:group).new :name => self[:group], :audit => :ensure @service_group_available = group.exists? else @service_group_available = false end end
# File lib/puppet/settings.rb, line 794 def service_user_available? return @service_user_available if defined?(@service_user_available) if self[:user] user = Puppet::Type.type(:user).new :name => self[:user], :audit => :ensure @service_user_available = user.exists? else @service_user_available = false end 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
# File lib/puppet/settings.rb, line 821 def set_by_cli?(param) param = param.to_sym !@value_sets[:cli].lookup(param).nil? end
# File lib/puppet/settings.rb, line 826 def set_value(param, value, type, options = {}) Puppet.deprecation_warning("Puppet.settings.set_value is deprecated. Use Puppet[]= instead.") if @value_sets[type] @value_sets[type].set(param, value) unsafe_flush_cache end end
Deprecated; use define_settings instead
# File lib/puppet/settings.rb, line 835 def setdefaults(section, defs) Puppet.deprecation_warning("'setdefaults' is deprecated and will be removed; please call 'define_settings' instead") define_settings(section, defs) end
@param name [Symbol] The name of the setting to fetch @return [Puppet::Settings::BaseSetting] The setting object
# File lib/puppet/settings.rb, line 109 def setting(name) @config[name] end
check to see if a short name is already defined
# File lib/puppet/settings.rb, line 435 def shortinclude?(short) short = short.intern if name.is_a? String @shortnames.include?(short) end
Convert the settings we manage into a catalog full of resources that model those settings.
# File lib/puppet/settings.rb, line 908 def to_catalog(*sections) sections = nil if sections.empty? catalog = Puppet::Resource::Catalog.new("Settings", Puppet::Node::Environment::NONE) @config.keys.find_all { |key| @config[key].is_a?(FileSetting) }.each do |key| next if (key == :manifestdir && should_skip_manifestdir?()) file = @config[key] next unless (sections.nil? or sections.include?(file.section)) next unless resource = file.to_resource next if catalog.resource(resource.ref) Puppet.debug("Using settings: adding file resource '#{key}': '#{resource.inspect}'") catalog.add_resource(resource) end add_user_resources(catalog, sections) add_environment_resources(catalog, sections) catalog end
Convert our list of config settings into a configuration file.
# File lib/puppet/settings.rb, line 938 def to_config str = %Q{The configuration file for #{Puppet.run_mode.name}. Note that this file is likely to have unused settings in it; any setting that's valid anywhere in Puppet can be in any config file, even if it's not used. Every section can specify three special parameters: owner, group, and mode. These parameters affect the required permissions of any files specified after their specification. Puppet will sometimes use these parameters to check its own configured state, so they can be used to make Puppet a bit more self-managing. The file format supports octothorpe-commented lines, but not partial-line comments. Generated on #{Time.now}. }.gsub(/^/, "# ") # Add a section heading that matches our name. str += "[#{preferred_run_mode}]\n" eachsection do |section| persection(section) do |obj| str += obj.to_config + "\n" unless obj.name == :genconfig end end return str end
Convert to a parseable manifest
# File lib/puppet/settings.rb, line 966 def to_manifest catalog = to_catalog catalog.resource_refs.collect do |ref| catalog.resource(ref).to_manifest end.join("\n\n") end
# File lib/puppet/settings.rb, line 1011 def uninterpolated_value(param, environment = nil) Puppet.deprecation_warning("Puppet.settings.uninterpolated_value is deprecated. Use Puppet.settings.value instead") param = param.to_sym environment &&= environment.to_sym values(environment, self.preferred_run_mode).lookup(param) 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, line 975 def use(*sections) sections = sections.collect { |s| s.to_sym } sections = sections.reject { |s| @used.include?(s) } return if sections.empty? begin catalog = to_catalog(*sections).to_ral rescue => detail Puppet.log_and_raise(detail, "Could not create resources for managing Puppet's files and directories in sections #{sections.inspect}: #{detail}") end catalog.host_config = false catalog.apply do |transaction| if transaction.any_failed? report = transaction.report status_failures = report.resource_statuses.values.select { |r| r.failed? } status_fail_msg = status_failures. collect(&:events). flatten. select { |event| event.status == 'failure' }. collect { |event| "#{event.resource}: #{event.message}" }.join("; ") raise "Got #{status_failures.length} failure(s) while initializing: #{status_fail_msg}" end end sections.each { |s| @used << s } @used.uniq! end
# File lib/puppet/settings.rb, line 1006 def valid?(param) param = param.to_sym @config.has_key?(param) 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, line 1043 def value(param, environment = nil, bypass_interpolation = false) param = param.to_sym environment &&= environment.to_sym setting = @config[param] # Short circuit to nil for undefined settings. return nil if setting.nil? # Check the cache first. It needs to be a per-environment # cache so that we don't spread values from one env # to another. if @cache[environment||"none"].has_key?(param) return @cache[environment||"none"][param] elsif bypass_interpolation val = values(environment, self.preferred_run_mode).lookup(param) else val = values(environment, self.preferred_run_mode).interpolate(param) end @cache[environment||"none"][param] = val val 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, line 1026 def values(environment, section) @values[environment][section] ||= ChainedValues.new( section, environment, value_sets_for(environment, section), @config) 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/puppet/puppet.conf)
Otherwise, use the user puppet.conf (usually ~/.puppet/puppet.conf)
@api private @todo this code duplicates {Puppet::Util::RunMode#which_dir} as described
in {http://projects.puppetlabs.com/issues/16637 #16637}
# File lib/puppet/settings.rb, line 1080 def which_configuration_file if explicit_config_file? or Puppet.features.root? then return main_config_file else return user_config_file end end
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, line 42 def self.app_defaults_for_run_mode(run_mode) { :name => run_mode.to_s, :run_mode => run_mode.name, :confdir => run_mode.conf_dir, :vardir => run_mode.var_dir, :rundir => run_mode.run_dir, :logdir => run_mode.log_dir, } 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, line 317 def self.clean_opt(opt, val) # rewrite --[no-]option to --no-option if that's what was given if opt =~ /\[no-\]/ and !val opt = opt.gsub(/\[no-\]/,'no-') end # otherwise remove the [no-] prefix to not confuse everybody opt = opt.gsub(/\[no-\]/, '') [opt, val] end
# File lib/puppet/settings.rb, line 53 def self.default_certname() hostname = hostname_fact domain = domain_fact if domain and domain != "" fqdn = [hostname, domain].join(".") else fqdn = hostname end fqdn.to_s.gsub(/\.$/, '') end
# File lib/puppet/settings.rb, line 72 def self.default_config_file_name "puppet.conf" end
# File lib/puppet/settings.rb, line 68 def self.domain_fact() Facter["domain"].value end
# File lib/puppet/settings.rb, line 64 def self.hostname_fact() Facter["hostname"].value end
Create a new collection of config settings.
# File lib/puppet/settings.rb, line 77 def initialize @config = {} @shortnames = {} @created = [] # Keep track of set values. @value_sets = { :cli => Values.new(:cli, @config), :memory => Values.new(:memory, @config), :application_defaults => Values.new(:application_defaults, @config), :overridden_defaults => Values.new(:overridden_defaults, @config), } @configuration_file = nil # And keep a per-environment cache @cache = Hash.new { |hash, key| hash[key] = {} } @values = Hash.new { |hash, key| hash[key] = {} } # The list of sections we've used. @used = [] @hooks_to_call_on_application_initialization = [] @deprecated_setting_names = [] @deprecated_settings_that_have_been_configured = [] @translate = Puppet::Settings::ValueTranslator.new @config_file_parser = Puppet::Settings::ConfigFile.new(@translate) end