diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/chef/audit/runner.rb | 12 | ||||
-rw-r--r-- | lib/chef/client.rb | 3 | ||||
-rw-r--r-- | lib/chef/config.rb | 8 | ||||
-rw-r--r-- | lib/chef/knife/bootstrap.rb | 3 | ||||
-rw-r--r-- | lib/chef/knife/core/subcommand_loader.rb | 18 | ||||
-rw-r--r-- | lib/chef/knife/exec.rb | 3 | ||||
-rw-r--r-- | lib/chef/knife/ssh.rb | 7 | ||||
-rw-r--r-- | lib/chef/provider/group.rb | 10 | ||||
-rw-r--r-- | lib/chef/provider/package/openbsd.rb | 67 | ||||
-rw-r--r-- | lib/chef/provider/service/macosx.rb | 3 | ||||
-rw-r--r-- | lib/chef/shell.rb | 12 | ||||
-rw-r--r-- | lib/chef/util/path_helper.rb | 76 | ||||
-rw-r--r-- | lib/chef/workstation_config_loader.rb | 7 |
13 files changed, 181 insertions, 48 deletions
diff --git a/lib/chef/audit/runner.rb b/lib/chef/audit/runner.rb index 13ba95428c..13c2823dca 100644 --- a/lib/chef/audit/runner.rb +++ b/lib/chef/audit/runner.rb @@ -79,11 +79,15 @@ class Chef require 'rspec' require 'rspec/its' require 'specinfra' + require 'specinfra/helper' + require 'specinfra/helper/set' require 'serverspec/helper' require 'serverspec/matcher' require 'serverspec/subject' require 'chef/audit/audit_event_proxy' require 'chef/audit/rspec_formatter' + + Specinfra::Backend::Cmd.send(:include, Specinfra::Helper::Set) end # Configure RSpec just the way we like it: @@ -136,9 +140,13 @@ class Chef end end - # Set up the backend for Specinfra/Serverspec. :exec is the local system. + # Set up the backend for Specinfra/Serverspec. :exec is the local system; on Windows, it is :cmd def configure_specinfra - Specinfra.configuration.backend = :exec + if Chef::Platform.windows? + Specinfra.configuration.backend = :cmd + else + Specinfra.configuration.backend = :exec + end end # Iterates through the control groups registered to this run_context, builds an diff --git a/lib/chef/client.rb b/lib/chef/client.rb index 7fd7bd9e3f..f5cde4bfb3 100644 --- a/lib/chef/client.rb +++ b/lib/chef/client.rb @@ -331,8 +331,8 @@ class Chef runner.converge @events.converge_complete rescue Exception => e - Chef::Log.error("Converge failed with error message #{e.message}") @events.converge_failed(e) + raise e if Chef::Config[:audit_mode] == :disabled converge_exception = e end end @@ -347,6 +347,7 @@ class Chef begin save_updated_node rescue Exception => e + raise e if Chef::Config[:audit_mode] == :disabled converge_exception = e end end diff --git a/lib/chef/config.rb b/lib/chef/config.rb index 4e60ad652b..a9fa9f1552 100644 --- a/lib/chef/config.rb +++ b/lib/chef/config.rb @@ -497,7 +497,8 @@ class Chef default(:syntax_check_cache_path) { cache_options[:path] } # Deprecated: - default(:cache_options) { { :path => PathHelper.join(file_cache_path, "checksums") } } + # Move this to the default value of syntax_cache_path when this is removed. + default(:cache_options) { { :path => PathHelper.join(config_dir, "syntaxcache") } } # Whether errors should be raised for deprecation warnings. When set to # `false` (the default setting), a warning is emitted but code using @@ -570,11 +571,12 @@ class Chef end def self.windows_home_path - env['SYSTEMDRIVE'] + env['HOMEPATH'] if env['SYSTEMDRIVE'] && env['HOMEPATH'] + Chef::Log.deprecation("Chef::Config.windows_home_path is now deprecated. Consider using Chef::Util::PathHelper.home instead.") + PathHelper.home end # returns a platform specific path to the user home dir if set, otherwise default to current directory. - default( :user_home ) { env['HOME'] || windows_home_path || env['USERPROFILE'] || Dir.pwd } + default( :user_home ) { PathHelper.home || Dir.pwd } # Enable file permission fixup for selinux. Fixup will be done # only if selinux is enabled in the system. diff --git a/lib/chef/knife/bootstrap.rb b/lib/chef/knife/bootstrap.rb index e168a6bd9b..64d1d0c378 100644 --- a/lib/chef/knife/bootstrap.rb +++ b/lib/chef/knife/bootstrap.rb @@ -21,6 +21,7 @@ require 'chef/knife/data_bag_secret_options' require 'erubis' require 'chef/knife/bootstrap/chef_vault_handler' require 'chef/knife/bootstrap/client_builder' +require 'chef/util/path_helper' class Chef class Knife @@ -268,7 +269,7 @@ class Chef bootstrap_files = [] bootstrap_files << File.join(File.dirname(__FILE__), 'bootstrap/templates', "#{template}.erb") bootstrap_files << File.join(Knife.chef_config_dir, "bootstrap", "#{template}.erb") if Chef::Knife.chef_config_dir - bootstrap_files << File.join(ENV['HOME'], '.chef', 'bootstrap', "#{template}.erb") if ENV['HOME'] + Chef::Util::PathHelper.home('.chef', 'bootstrap', "#{template}.erb") {|p| bootstrap_files << p} bootstrap_files << Gem.find_files(File.join("chef","knife","bootstrap","#{template}.erb")) bootstrap_files.flatten! diff --git a/lib/chef/knife/core/subcommand_loader.rb b/lib/chef/knife/core/subcommand_loader.rb index f9b8f5008e..1f59515f44 100644 --- a/lib/chef/knife/core/subcommand_loader.rb +++ b/lib/chef/knife/core/subcommand_loader.rb @@ -28,9 +28,15 @@ class Chef attr_reader :chef_config_dir attr_reader :env - def initialize(chef_config_dir, env=ENV) - @chef_config_dir, @env = chef_config_dir, env + def initialize(chef_config_dir, env=nil) + @chef_config_dir = chef_config_dir @forced_activate = {} + + # Deprecated and un-used instance variable. + @env = env + unless env.nil? + Chef::Log.deprecation("The env argument to Chef::Knife::SubcommandLoader is deprecated. If you are using env to inject/mock HOME, consider mocking Chef::Util::PathHelper.home instead.") + end end # Load all the sub-commands @@ -49,7 +55,9 @@ class Chef end # finally search ~/.chef/plugins/knife/*.rb - user_specific_files.concat Dir.glob(File.join(Chef::Util::PathHelper.escape_glob(env['HOME'], '.chef', 'plugins', 'knife'), '*.rb')) if env['HOME'] + Chef::Util::PathHelper.home('.chef', 'plugins', 'knife') do |p| + user_specific_files.concat Dir.glob(File.join(Chef::Util::PathHelper.escape_glob(p), '*.rb')) + end user_specific_files end @@ -140,7 +148,7 @@ class Chef end def have_plugin_manifest? - ENV["HOME"] && File.exist?(plugin_manifest_path) + plugin_manifest_path && File.exist?(plugin_manifest_path) end def plugin_manifest @@ -148,7 +156,7 @@ class Chef end def plugin_manifest_path - File.join(ENV['HOME'], '.chef', 'plugin_manifest.json') + Chef::Util::PathHelper.home('.chef', 'plugin_manifest.json') end private diff --git a/lib/chef/knife/exec.rb b/lib/chef/knife/exec.rb index 3e8196c616..ace4ee2300 100644 --- a/lib/chef/knife/exec.rb +++ b/lib/chef/knife/exec.rb @@ -17,6 +17,7 @@ # require 'chef/knife' +require 'chef/util/path_helper' class Chef::Knife::Exec < Chef::Knife @@ -42,7 +43,7 @@ class Chef::Knife::Exec < Chef::Knife # Default script paths are chef-repo/.chef/scripts and ~/.chef/scripts config[:script_path] << File.join(Chef::Knife.chef_config_dir, 'scripts') if Chef::Knife.chef_config_dir - config[:script_path] << File.join(ENV['HOME'], '.chef', 'scripts') if ENV['HOME'] + Chef::Util::PathHelper.home('.chef', 'scripts') { |p| config[:script_path] << p } scripts = Array(name_args) context = Object.new diff --git a/lib/chef/knife/ssh.rb b/lib/chef/knife/ssh.rb index db0fb7dd41..50fedd0e49 100644 --- a/lib/chef/knife/ssh.rb +++ b/lib/chef/knife/ssh.rb @@ -31,6 +31,7 @@ class Chef require 'chef/search/query' require 'chef/mixin/shell_out' require 'chef/mixin/command' + require 'chef/util/path_helper' require 'mixlib/shellout' end @@ -342,8 +343,10 @@ class Chef def screen tf = Tempfile.new("knife-ssh-screen") - if File.exist? "#{ENV["HOME"]}/.screenrc" - tf.puts("source #{ENV["HOME"]}/.screenrc") + Chef::Util::PathHelper.home('.screenrc') do |screenrc_path| + if File.exist? screenrc_path + tf.puts("source #{screenrc_path}") + end end tf.puts("caption always '%-Lw%{= BW}%50>%n%f* %t%{-}%+Lw%<'") tf.puts("hardstatus alwayslastline 'knife ssh #{@name_args[0]}'") diff --git a/lib/chef/provider/group.rb b/lib/chef/provider/group.rb index 29738cc046..a802758dce 100644 --- a/lib/chef/provider/group.rb +++ b/lib/chef/provider/group.rb @@ -125,13 +125,13 @@ class Chef def action_create case @group_exists when false - converge_by("create #{@new_resource}") do + converge_by("create #{@new_resource.group_name}") do create_group Chef::Log.info("#{@new_resource} created") end else if compare_group - converge_by(["alter group #{@new_resource}"] + change_desc) do + converge_by(["alter group #{@new_resource.group_name}"] + change_desc) do manage_group Chef::Log.info("#{@new_resource} altered") end @@ -141,7 +141,7 @@ class Chef def action_remove if @group_exists - converge_by("remove group #{@new_resource}") do + converge_by("remove group #{@new_resource.group_name}") do remove_group Chef::Log.info("#{@new_resource} removed") end @@ -150,7 +150,7 @@ class Chef def action_manage if @group_exists && compare_group - converge_by(["manage group #{@new_resource}"] + change_desc) do + converge_by(["manage group #{@new_resource.group_name}"] + change_desc) do manage_group Chef::Log.info("#{@new_resource} managed") end @@ -159,7 +159,7 @@ class Chef def action_modify if compare_group - converge_by(["modify group #{@new_resource}"] + change_desc) do + converge_by(["modify group #{@new_resource.group_name}"] + change_desc) do manage_group Chef::Log.info("#{@new_resource} modified") end diff --git a/lib/chef/provider/package/openbsd.rb b/lib/chef/provider/package/openbsd.rb index f0931d7555..82048c3bd4 100644 --- a/lib/chef/provider/package/openbsd.rb +++ b/lib/chef/provider/package/openbsd.rb @@ -24,6 +24,7 @@ require 'chef/resource/package' require 'chef/provider/package' require 'chef/mixin/shell_out' require 'chef/mixin/get_source_from_package' +require 'chef/exceptions' class Chef class Provider @@ -37,25 +38,42 @@ class Chef def initialize(*args) super - @current_resource = Chef::Resource::Package.new(@new_resource.name) - @new_resource.source(pkg_path) if !@new_resource.source + @current_resource = Chef::Resource::Package.new(new_resource.name) end def load_current_resource - @current_resource.package_name(@new_resource.package_name) + @current_resource.package_name(new_resource.package_name) @current_resource.version(installed_version) @current_resource end + def define_resource_requirements + super + + # Below are incomplete/missing features for this package provider + requirements.assert(:all_actions) do |a| + a.assertion { !new_resource.source } + a.failure_message(Chef::Exceptions::Package, 'The openbsd package provider does not support the source attribute') + end + requirements.assert(:all_actions) do |a| + a.assertion do + if new_resource.package_name =~ /^(.+?)--(.+)/ + !new_resource.version + else + true + end + end + a.failure_message(Chef::Exceptions::Package, 'The openbsd package provider does not support providing a version and flavor') + end + end + def install_package(name, version) unless @current_resource.version - version_string = '' - version_string += "-#{version}" if version if parts = name.match(/^(.+?)--(.+)/) # use double-dash for stems with flavors, see man page for pkg_add name = parts[1] end - shell_out!("pkg_add -r #{name}#{version_string}", :env => {"PKG_PATH" => @new_resource.source}).status - Chef::Log.debug("#{@new_resource} installed from: #{@new_resource.source}") + shell_out!("pkg_add -r #{name}#{version_string}", :env => {"PKG_PATH" => pkg_path}).status + Chef::Log.debug("#{new_resource.package_name} installed") end end @@ -71,32 +89,45 @@ class Chef private def installed_version - if parts = @new_resource.package_name.match(/^(.+?)--(.+)/) + if parts = new_resource.package_name.match(/^(.+?)--(.+)/) name = parts[1] else - name = @new_resource.package_name + name = new_resource.package_name end pkg_info = shell_out!("pkg_info -e \"#{name}->0\"", :env => nil, :returns => [0,1]) result = pkg_info.stdout[/^inst:#{Regexp.escape(name)}-(.+?)\s/, 1] - Chef::Log.debug("installed_version of '#{@new_resource.package_name}' is '#{result}'") + Chef::Log.debug("installed_version of '#{new_resource.package_name}' is '#{result}'") result end def candidate_version @candidate_version ||= begin - version_string = '' - version_string += "-#{version}" if @new_resource.version - pkg_info = shell_out!("pkg_info -I \"#{@new_resource.package_name}#{version_string}\"", :env => nil, :returns => [0,1]) - if parts = @new_resource.package_name.match(/^(.+?)--(.+)/) - result = pkg_info.stdout[/^#{Regexp.escape(parts[1])}-(.+?)\s/, 1] + results = [] + shell_out!("pkg_info -I \"#{new_resource.package_name}#{version_string}\"", :env => nil, :returns => [0,1]).stdout.each_line do |line| + if parts = new_resource.package_name.match(/^(.+?)--(.+)/) + results << line[/^#{Regexp.escape(parts[1])}-(.+?)\s/, 1] + else + results << line[/^#{Regexp.escape(new_resource.package_name)}-(.+?)\s/, 1] + end + end + results = results.reject(&:nil?) + Chef::Log.debug("candidate versions of '#{new_resource.package_name}' are '#{results}'") + case results.length + when 0 + [] + when 1 + results[0] else - result = pkg_info.stdout[/^#{Regexp.escape(@new_resource.package_name)}-(.+?)\s/, 1] + raise Chef::Exceptions::Package, "#{new_resource.name} has multiple matching candidates. Please use a more specific name" if results.length > 1 end - Chef::Log.debug("candidate_version of '#{@new_resource.package_name}' is '#{result}'") - result end end + def version_string + ver = '' + ver += "-#{new_resource.version}" if new_resource.version + end + def pkg_path ENV['PKG_PATH'] || "http://ftp.OpenBSD.org/pub/#{node.kernel.name}/#{node.kernel.release}/packages/#{node.kernel.machine}/" end diff --git a/lib/chef/provider/service/macosx.rb b/lib/chef/provider/service/macosx.rb index 10ad1aa29d..df5be54fda 100644 --- a/lib/chef/provider/service/macosx.rb +++ b/lib/chef/provider/service/macosx.rb @@ -33,8 +33,7 @@ class Chef /Library/LaunchDaemons /System/Library/LaunchAgents /System/Library/LaunchDaemons } - - locations << "#{ENV['HOME']}/Library/LaunchAgents" if ENV['HOME'] + Chef::Util::PathHelper.home('Library', 'LaunchAgents') { |p| locations << p } locations end diff --git a/lib/chef/shell.rb b/lib/chef/shell.rb index fed32b3795..ee4fe78808 100644 --- a/lib/chef/shell.rb +++ b/lib/chef/shell.rb @@ -29,6 +29,7 @@ require 'chef/config_fetcher' require 'chef/shell/shell_session' require 'chef/shell/ext' require 'chef/json_compat' +require 'chef/util/path_helper' # = Shell # Shell is Chef in an IRB session. Shell can interact with a Chef server via the @@ -101,7 +102,7 @@ module Shell end def self.configure_irb - irb_conf[:HISTORY_FILE] = "~/.chef/chef_shell_history" + irb_conf[:HISTORY_FILE] = Chef::Util::PathHelper.home(".chef", "chef_shell_history") irb_conf[:SAVE_HISTORY] = 1000 irb_conf[:IRB_RC] = lambda do |conf| @@ -295,18 +296,19 @@ FOOTER private def config_file_for_shell_mode(environment) + dot_chef_dir = Chef::Util::PathHelper.home('.chef') if config[:config_file] config[:config_file] - elsif environment && ENV['HOME'] + elsif environment Shell.env = environment - config_file_to_try = ::File.join(ENV['HOME'], '.chef', environment, 'chef_shell.rb') + config_file_to_try = ::File.join(dot_chef_dir, environment, 'chef_shell.rb') unless ::File.exist?(config_file_to_try) puts "could not find chef-shell config for environment #{environment} at #{config_file_to_try}" exit 1 end config_file_to_try - elsif ENV['HOME'] && ::File.exist?(File.join(ENV['HOME'], '.chef', 'chef_shell.rb')) - File.join(ENV['HOME'], '.chef', 'chef_shell.rb') + elsif dot_chef_dir && ::File.exist?(File.join(dot_chef_dir, 'chef_shell.rb')) + File.join(dot_chef_dir, 'chef_shell.rb') elsif config[:solo] Chef::Config.platform_specific_path("/etc/chef/solo.rb") elsif config[:client] diff --git a/lib/chef/util/path_helper.rb b/lib/chef/util/path_helper.rb index 1ae489598d..17c7175331 100644 --- a/lib/chef/util/path_helper.rb +++ b/lib/chef/util/path_helper.rb @@ -142,6 +142,82 @@ class Chef def self.relative_path_from(from, to) pathname = Pathname.new(Chef::Util::PathHelper.cleanpath(to)).relative_path_from(Pathname.new(Chef::Util::PathHelper.cleanpath(from))) end + + # Retrieves the "home directory" of the current user while trying to ascertain the existence + # of said directory. The path returned uses / for all separators (the ruby standard format). + # If the home directory doesn't exist or an error is otherwise encountered, nil is returned. + # + # If a set of path elements is provided, they are appended as-is to the home path if the + # homepath exists. + # + # If an optional block is provided, the joined path is passed to that block if the home path is + # valid and the result of the block is returned instead. + # + # Home-path discovery is performed once. If a path is discovered, that value is memoized so + # that subsequent calls to home_dir don't bounce around. + # + # See self.all_homes. + def self.home(*args) + @@home_dir ||= self.all_homes { |p| break p } + if @@home_dir + path = File.join(@@home_dir, *args) + block_given? ? (yield path) : path + end + end + + # See self.home. This method performs a similar operation except that it yields all the different + # possible values of 'HOME' that one could have on this platform. Hence, on windows, if + # HOMEDRIVE\HOMEPATH and USERPROFILE are different, the provided block will be called twice. + # This method goes out and checks the existence of each location at the time of the call. + # + # The return is a list of all the returned values from each block invocation or a list of paths + # if no block is provided. + def self.all_homes(*args) + paths = [] + if Chef::Platform.windows? + # By default, Ruby uses the the following environment variables to determine Dir.home: + # HOME + # HOMEDRIVE HOMEPATH + # USERPROFILE + # Ruby only checks to see if the variable is specified - not if the directory actually exists. + # On Windows, HOMEDRIVE HOMEPATH can point to a different location (such as an unavailable network mounted drive) + # while USERPROFILE points to the location where the user application settings and profile are stored. HOME + # is not defined as an environment variable (usually). If the home path actually uses UNC, then the prefix is + # HOMESHARE instead of HOMEDRIVE. + # + # We instead walk down the following and only include paths that actually exist. + # HOME + # HOMEDRIVE HOMEPATH + # HOMESHARE HOMEPATH + # USERPROFILE + + paths << ENV['HOME'] + paths << ENV['HOMEDRIVE'] + ENV['HOMEPATH'] if ENV['HOMEDRIVE'] && ENV['HOMEPATH'] + paths << ENV['HOMESHARE'] + ENV['HOMEPATH'] if ENV['HOMESHARE'] && ENV['HOMEPATH'] + paths << ENV['USERPROFILE'] + end + paths << Dir.home + + # Depending on what environment variables we're using, the slashes can go in any which way. + # Just change them all to / to keep things consistent. + # Note: Maybe this is a bad idea on some unixy systems where \ might be a valid character depending on + # the particular brand of kool-aid you consume. This code assumes that \ and / are both + # path separators on any system being used. + paths = paths.map { |home_path| home_path.gsub(path_separator, ::File::SEPARATOR) if home_path } + + # Filter out duplicate paths and paths that don't exist. + valid_paths = paths.select { |home_path| home_path && Dir.exists?(home_path) } + valid_paths = valid_paths.uniq + + # Join all optional path elements at the end. + # If a block is provided, invoke it - otherwise just return what we've got. + joined_paths = valid_paths.map { |home_path| File.join(home_path, *args) } + if block_given? + joined_paths.each { |p| yield p } + else + joined_paths + end + end end end end diff --git a/lib/chef/workstation_config_loader.rb b/lib/chef/workstation_config_loader.rb index dd02ad9a66..2454c9cccf 100644 --- a/lib/chef/workstation_config_loader.rb +++ b/lib/chef/workstation_config_loader.rb @@ -19,6 +19,7 @@ require 'chef/config_fetcher' require 'chef/config' require 'chef/null_logger' +require 'chef/util/path_helper' class Chef @@ -112,9 +113,9 @@ class Chef candidate_configs << File.join(chef_config_dir, 'knife.rb') end # Look for $HOME/.chef/knife.rb - if env['HOME'] - candidate_configs << File.join(env['HOME'], '.chef', 'config.rb') - candidate_configs << File.join(env['HOME'], '.chef', 'knife.rb') + Chef::Util::PathHelper.home('.chef') do |dot_chef_dir| + candidate_configs << File.join(dot_chef_dir, 'config.rb') + candidate_configs << File.join(dot_chef_dir, 'knife.rb') end candidate_configs.find do | candidate_config | |