class ChefConfig::Config
Public Class Methods
Path to this file in the current install.
# File lib/chef-config/config.rb, line 1297 def self._this_file File.expand_path(__FILE__) end
@param logger [String]
# File lib/chef-config/config.rb, line 165 def self.add_event_logger(logger) event_handlers << logger end
@param name [String] @param file_path [String]
# File lib/chef-config/config.rb, line 160 def self.add_formatter(name, file_path = nil) formatters << [name, file_path] end
# File lib/chef-config/config.rb, line 169 def self.apply_extra_config_options(extra_config_options) if extra_config_options extra_parsed_options = extra_config_options.inject({}) do |memo, option| # Sanity check value. if option.empty? || !option.include?("=") raise UnparsableConfigOption, "Unparsable config option #{option.inspect}" end # Split including whitespace if someone does truly odd like # --config-option "foo = bar" key, value = option.split(/\s*=\s*/, 2) # Call to_sym because Chef::Config expects only symbol keys. Also # runs a simple parse on the string for some common types. memo[key.to_sym] = YAML.safe_load(value, permitted_classes: [Date]) memo end set_extra_config_options(extra_parsed_options) end end
On windows, C:/chef/
(should only be called in a windows-context)
@return [String] the platform-specific path
# File lib/chef-config/config.rb, line 126 def self.c_chef_dir(windows: ChefUtils.windows?) drive = windows_installation_drive || "C:" PathHelper.join(drive, ChefUtils::Dist::Infra::DIR_SUFFIX, windows: windows) end
On windows, C:/opscode
(should only be called in a windows-context)
@return [String] the platform-specific path
# File lib/chef-config/config.rb, line 137 def self.c_opscode_dir(windows: ChefUtils.windows?) drive = windows_installation_drive || "C:" PathHelper.join(drive, ChefUtils::Dist::Org::LEGACY_CONF_DIR, ChefUtils::Dist::Infra::DIR_SUFFIX, windows: windows) end
@param child_path [String]
# File lib/chef-config/config.rb, line 288 def self.derive_path_from_chef_repo_path(child_path) if chef_repo_path.is_a?(String) PathHelper.join(chef_repo_path, child_path) else chef_repo_path.uniq.map { |path| PathHelper.join(path, child_path) } end end
If installed via an omnibus installer, this gives the path to the “embedded” directory which contains all of the software packaged with omnibus. This is used to locate the cacert.pem file on windows.
# File lib/chef-config/config.rb, line 1286 def self.embedded_dir Pathname.new(_this_file).ascend do |path| if path.basename.to_s == "embedded" return path.to_s end end nil end
Set fips mode in openssl. Do any patching necessary to make sure Chef runs do not crash. @api private
# File lib/chef-config/config.rb, line 1304 def self.enable_fips_mode OpenSSL.fips_mode = true require "digest" unless defined?(Digest) require "digest/sha1" unless defined?(Digest::SHA1) require "digest/md5" unless defined?(Digest::MD5) # Remove pre-existing constants if they do exist to reduce the # amount of log spam and warnings. Digest.send(:remove_const, "SHA1") if Digest.const_defined?(:SHA1) Digest.const_set(:SHA1, OpenSSL::Digest::SHA1) OpenSSL::Digest.send(:remove_const, "MD5") if OpenSSL::Digest.const_defined?(:MD5) OpenSSL::Digest.const_set(:MD5, Digest::MD5) ChefConfig.logger.debug "FIPS mode is enabled." end
This provides a hook which rspec can stub so that we can avoid twiddling global state in tests.
# File lib/chef-config/config.rb, line 970 def self.env ENV end
On *nix, /etc/chef, on Windows C:chef
@param windows [Boolean] optional flag to force to windows or unix-style @return [String] the platform-specific path
# File lib/chef-config/config.rb, line 86 def self.etc_chef_dir(windows: ChefUtils.windows?) @etc_chef_dir ||= {} @etc_chef_dir[windows] ||= begin path = windows ? c_chef_dir : PathHelper.join("/etc", ChefUtils::Dist::Infra::DIR_SUFFIX, windows: windows) PathHelper.cleanpath(path, windows: windows) end end
# File lib/chef-config/config.rb, line 236 def self.expand_relative_paths(path) unless path.nil? if path.is_a?(String) File.expand_path(path) else Array(path).map { |path| File.expand_path(path) } end end end
@api private
# File lib/chef-config/config.rb, line 1189 def self.export_no_proxy(value) ENV["no_proxy"] = value unless ENV["no_proxy"] ENV["NO_PROXY"] = value unless ENV["NO_PROXY"] end
Public method that users should call to export proxies to the appropriate environment variables. This method should be called after the config file is parsed and loaded. TODO add some post-file-parsing logic that automatically calls this so users don’t have to
# File lib/chef-config/config.rb, line 1145 def self.export_proxies export_proxy("http", http_proxy, http_proxy_user, http_proxy_pass) if key?(:http_proxy) && http_proxy export_proxy("https", https_proxy, https_proxy_user, https_proxy_pass) if key?(:https_proxy) && https_proxy export_proxy("ftp", ftp_proxy, ftp_proxy_user, ftp_proxy_pass) if key?(:ftp_proxy) && ftp_proxy export_no_proxy(no_proxy) if key?(:no_proxy) && no_proxy end
Builds a proxy uri and exports it to the appropriate environment variables. Examples:
http://username:password@hostname:port https://username@hostname:port ftp://hostname:port
when
scheme = "http", "https", or "ftp" hostport = hostname:port or scheme://hostname:port user = username pass = password
@api private
# File lib/chef-config/config.rb, line 1162 def self.export_proxy(scheme, path, user, pass) # Character classes for Addressable # See https://www.ietf.org/rfc/rfc3986.txt 3.2.1 # The user part may not have a : in it user_class = Addressable::URI::CharacterClasses::UNRESERVED + Addressable::URI::CharacterClasses::SUB_DELIMS # The password part may have any valid USERINFO characters password_class = user_class + "\\:" path = "#{scheme}://#{path}" unless path.include?("://") # URI.split returns the following parts: # [scheme, userinfo, host, port, registry, path, opaque, query, fragment] uri = Addressable::URI.encode(path, Addressable::URI) if user && !user.empty? userinfo = Addressable::URI.encode_component(user, user_class) if pass userinfo << ":#{Addressable::URI.encode_component(pass, password_class)}" end uri.userinfo = userinfo end path = uri.to_s ENV["#{scheme}_proxy".downcase] = path unless ENV["#{scheme}_proxy".downcase] ENV["#{scheme}_proxy".upcase] = path unless ENV["#{scheme}_proxy".upcase] end
# File lib/chef-config/config.rb, line 271 def self.find_chef_repo_path(cwd) # In local mode, we auto-discover the repo root by looking for a path with "cookbooks" under it. # This allows us to run config-free. path = cwd until File.directory?(PathHelper.join(path, "cookbooks")) || File.directory?(PathHelper.join(path, "cookbook_artifacts")) new_path = File.expand_path("..", path) if new_path == path ChefConfig.logger.warn("No cookbooks directory found at or above current directory. Assuming #{cwd}.") return cwd end path = new_path end ChefConfig.logger.info("Auto-discovered #{ChefUtils::Dist::Infra::SHORT} repository at #{path}") path end
Evaluates the given string as config.
filename
is used for context in stacktraces, but doesn’t need to be the name of an actual file.
# File lib/chef-config/config.rb, line 53 def self.from_string(string, filename) instance_eval(string, filename, 1) end
Chef requires an English-language UTF-8 locale to function properly. We attempt to use the ‘locale -a’ command and search through a list of preferences until we find one that we can use. On Ubuntu systems we should find ‘C.UTF-8’ and be able to use that even if there is no English locale on the server, but Mac, Solaris, AIX, etc do not have that locale. We then try to find an English locale and fall back to ‘C’ if we do not. The choice of fallback is pick-your-poison. If we try to do the work to return a non-US UTF-8 locale then we fail inside of providers when things like ‘svn info’ return Japanese and we can’t parse them. OTOH, if we pick ‘C’ then we will blow up on UTF-8 characters. Between the warn we throw and the Encoding exception that ruby will throw it is more obvious what is broken if we drop UTF-8 by default rather than drop English.
If there is no ‘locale -a’ then we return ‘en_US.UTF-8’ since that is the most commonly available English UTF-8 locale. However, all modern POSIXen should support ‘locale -a’.
# File lib/chef-config/config.rb, line 1228 def self.guess_internal_locale # https://github.com/chef/chef/issues/2181 # Some systems have the `locale -a` command, but the result has # invalid characters for the default encoding. # # For example, on CentOS 6 with ENV['LANG'] = "en_US.UTF-8", # `locale -a`.split fails with ArgumentError invalid UTF-8 encoding. cmd = Mixlib::ShellOut.new("locale -a").run_command cmd.error! locales = cmd.stdout.split case when locales.include?("C.UTF-8") "C.UTF-8" when locales.include?("en_US.UTF-8"), locales.include?("en_US.utf8") "en_US.UTF-8" when locales.include?("en.UTF-8") "en.UTF-8" else # Will match en_ZZ.UTF-8, en_ZZ.utf-8, en_ZZ.UTF8, en_ZZ.utf8 guesses = locales.grep(/^en_.*UTF-?8$/i) unless guesses.empty? guessed_locale = guesses.first # Transform into the form en_ZZ.UTF-8 guessed_locale.gsub(/UTF-?8$/i, "UTF-8") else ChefConfig.logger.warn "Please install an English UTF-8 locale for #{ChefUtils::Dist::Infra::PRODUCT} to use, falling back to C locale and disabling UTF-8 support." "C" end end rescue if ChefUtils.windows? ChefConfig.logger.trace "Defaulting to locale en_US.UTF-8 on Windows, until it matters that we do something else." else ChefConfig.logger.trace "No usable locale -a command found, assuming you have en_US.UTF-8 installed." end "en_US.UTF-8" end
Initialize openssl
# File lib/chef-config/config.rb, line 748 def self.init_openssl if fips enable_fips_mode end end
# File lib/chef-config/config.rb, line 57 def self.inspect configuration.inspect end
@param uri [String] the URI to validate
@return [Boolean] is the URL valid
# File lib/chef-config/config.rb, line 213 def self.is_valid_url?(uri) url = uri.to_s.strip %r{^http://} =~ url || %r{^https://} =~ url || /^chefzero:/ =~ url end
Returns true only if the path exists and is readable and writeable for the user.
@param path [String]
# File lib/chef-config/config.rb, line 394 def self.path_accessible?(path) File.exist?(path) && File.readable?(path) && File.writable?(path) end
given a *nix style config path return the platform specific path to that same config file @example client.pem path on Windows
platform_specific_path("/etc/chef/client.pem") #=> "C:\\chef\\client.pem"
@param path [String] The unix path to convert to a platform specific path @return [String] a platform specific path
# File lib/chef-config/config.rb, line 67 def self.platform_specific_path(path) path = PathHelper.cleanpath(path) if ChefUtils.windows? # turns \etc\chef\client.rb and \var\chef\client.rb into C:/chef/client.rb # Some installations will be on different drives so use the drive that # the expanded path to __FILE__ is found. drive = windows_installation_drive if drive && path[0] == "\\" && path.split("\\")[2] == "chef" path = PathHelper.join(drive, path.split("\\", 3)[2]) end end path end
Given a scheme, host, and port, return the correct proxy URI based on the set environment variables, unless excluded by no_proxy, in which case nil is returned
# File lib/chef-config/config.rb, line 1197 def self.proxy_uri(scheme, host, port) proxy_env_var = ENV["#{scheme}_proxy"].to_s.strip # Check if the proxy string contains a scheme. If not, add the url's scheme to the # proxy before parsing. The regex /^.*:\/\// matches, for example, http://. Reusing proxy # here since we are really just trying to get the string built correctly. proxy = unless proxy_env_var.empty? if %r{^.*://}.match?(proxy_env_var) URI.parse(proxy_env_var) else URI.parse("#{scheme}://#{proxy_env_var}") end end return proxy unless fuzzy_hostname_match_any?(host, ENV["no_proxy"]) end
# File lib/chef-config/config.rb, line 948 def self.set_defaults_for_nix # Those lists of regular expressions define what chef considers a # valid user and group name # # user/group cannot start with '-', '+' or '~' # user/group cannot contain ':', ',' or non-space-whitespace or null byte # everything else is allowed (UTF-8, spaces, etc) and we delegate to your O/S useradd program to barf or not # copies: http://anonscm.debian.org/viewvc/pkg-shadow/debian/trunk/debian/patches/506_relaxed_usernames?view=markup default :user_valid_regex, [ /^[^-+~:,\t\r\n\f\0]+[^:,\t\r\n\f\0]*$/ ] default :group_valid_regex, [ /^[^-+~:,\t\r\n\f\0]+[^:,\t\r\n\f\0]*$/ ] end
# File lib/chef-config/config.rb, line 937 def self.set_defaults_for_windows # Those lists of regular expressions define what chef considers a # valid user and group name # From http://technet.microsoft.com/en-us/library/cc776019(WS.10).aspx principal_valid_regex_part = '[^"\/\\\\\[\]\:;|=,+*?<>]+' default :user_valid_regex, [ /^(#{principal_valid_regex_part}\\)?#{principal_valid_regex_part}$/ ] default :group_valid_regex, [ /^(#{principal_valid_regex_part}\\)?#{principal_valid_regex_part}$/ ] default :fatal_windows_admin_check, false end
We use :[]= assignment here to not bypass any coercions that happen via mixlib-config writes_value callbacks
# File lib/chef-config/config.rb, line 191 def self.set_extra_config_options(extra_parsed_options) extra_parsed_options.each do |key, value| self[key.to_sym] = value end end
# File lib/chef-config/config.rb, line 559 def self.target_mode? target_mode.enabled end
On *nix, /var/chef, on Windows C:chef
@param windows [Boolean] optional flag to force to windows or unix-style @return [String] the platform-specific path
# File lib/chef-config/config.rb, line 99 def self.var_chef_dir(windows: ChefUtils.windows?) @var_chef_dir ||= {} @var_chef_dir[windows] ||= begin path = windows ? c_chef_dir : PathHelper.join("/var", ChefUtils::Dist::Infra::DIR_SUFFIX, windows: windows) PathHelper.cleanpath(path, windows: windows) end end
On *nix, /var, on Windows C:\
@param windows [Boolean] optional flag to force to windows or unix-style @return [String] the platform-specific path
# File lib/chef-config/config.rb, line 112 def self.var_root_dir(windows: ChefUtils.windows?) @var_root_dir ||= {} @var_root_dir[windows] ||= begin path = windows ? "C:\\" : "/var" PathHelper.cleanpath(path, windows: windows) end end
# File lib/chef-config/config.rb, line 974 def self.windows_home_path ChefConfig.logger.deprecation("Chef::Config.windows_home_path is now deprecated. Consider using Chef::Util::PathHelper.home instead.") PathHelper.home end
the drive where Chef is installed on a windows host. This is determined either by the drive containing the current file or by the SYSTEMDRIVE ENV variable
(should only be called in a windows-context)
@return [String] the drive letter
# File lib/chef-config/config.rb, line 150 def self.windows_installation_drive if ChefUtils.windows? drive = File.expand_path(__FILE__).split("/", 2)[0] drive = ENV["SYSTEMDRIVE"] if drive.to_s == "" drive end end