diff options
Diffstat (limited to 'lib')
39 files changed, 545 insertions, 189 deletions
diff --git a/lib/chef/application.rb b/lib/chef/application.rb index 5b1d53d741..0430d4acfa 100644 --- a/lib/chef/application.rb +++ b/lib/chef/application.rb @@ -46,6 +46,7 @@ class Chef::Application configure_chef configure_logging configure_proxy_environment_variables + configure_encoding end # Get this party started @@ -175,6 +176,11 @@ class Chef::Application configure_no_proxy end + # Sets the default external encoding to UTF-8 (users can change this, but they shouldn't) + def configure_encoding + Encoding.default_external = Chef::Config[:ruby_encoding] + end + # Called prior to starting the application, by the run method def setup_application raise Chef::Exceptions::Application, "#{self.to_s}: you must override setup_application" diff --git a/lib/chef/application/apply.rb b/lib/chef/application/apply.rb index ab35b35389..ea9154c6f2 100644 --- a/lib/chef/application/apply.rb +++ b/lib/chef/application/apply.rb @@ -134,6 +134,10 @@ class Chef::Application::Apply < Chef::Application @recipe_text = STDIN.read temp_recipe_file else + if !ARGV[0] + puts opt_parser + Chef::Application.exit! "No recipe file provided", 1 + end @recipe_filename = ARGV[0] @recipe_text,@recipe_fh = read_recipe_file @recipe_filename end diff --git a/lib/chef/chef_fs/chef_fs_data_store.rb b/lib/chef/chef_fs/chef_fs_data_store.rb index 09a66a9ab2..484ab07390 100644 --- a/lib/chef/chef_fs/chef_fs_data_store.rb +++ b/lib/chef/chef_fs/chef_fs_data_store.rb @@ -27,7 +27,61 @@ require 'fileutils' class Chef module ChefFS + # + # Translation layer between chef-zero's DataStore (a place where it expects + # files to be stored) and ChefFS (the user's repository directory layout). + # + # chef-zero expects the data store to store files *its* way--for example, it + # expects get("nodes/blah") to return the JSON text for the blah node, and + # it expects get("cookbooks/blah/1.0.0") to return the JSON definition of + # the blah cookbook version 1.0.0. + # + # The repository is defined the way the *user* wants their layout. These + # two things are very similar in layout (for example, nodes are stored under + # the nodes/ directory and their filename is the name of the node). + # + # However, there are a few differences that make this more than just a raw + # file store: + # + # 1. Cookbooks are stored much differently. + # - chef-zero places JSON text with the checksums for the cookbook at + # /cookbooks/NAME/VERSION, and expects the JSON to contain URLs to the + # actual files, which are stored elsewhere. + # - The repository contains an actual directory with just the cookbook + # files and a metadata.rb containing a version #. There is no JSON to + # be found. + # - Further, if versioned_cookbooks is false, that directory is named + # /cookbooks/NAME and only one version exists. If versioned_cookbooks + # is true, the directory is named /cookbooks/NAME-VERSION. + # - Therefore, ChefFSDataStore calculates the cookbook JSON by looking at + # the files in the cookbook and checksumming them, and reading metadata.rb + # for the version and dependency information. + # - ChefFSDataStore also modifies the cookbook file URLs so that they point + # to /file_store/repo/<filename> (the path to the actual file under the + # repository root). For example, /file_store/repo/apache2/metadata.rb or + # /file_store/repo/cookbooks/apache2/recipes/default.rb). + # + # 2. Sandboxes don't exist in the repository. + # - ChefFSDataStore lets cookbooks be uploaded into a temporary memory + # storage, and when the cookbook is committed, copies the files onto the + # disk in the correct place (/cookbooks/apache2/recipes/default.rb). + # 3. Data bags: + # - The Chef server expects data bags in /data/BAG/ITEM + # - The repository stores data bags in /data_bags/BAG/ITEM + # + # 4. JSON filenames are generally NAME.json in the repository (e.g. /nodes/foo.json). + # class ChefFSDataStore + # + # Create a new ChefFSDataStore + # + # ==== Arguments + # + # [chef_fs] + # A +ChefFS::FileSystem+ object representing the repository root. + # Generally will be a +ChefFS::FileSystem::ChefRepositoryFileSystemRoot+ + # object, created from +ChefFS::Config.local_fs+. + # def initialize(chef_fs) @chef_fs = chef_fs @memory_store = ChefZero::DataStore::MemoryStore.new diff --git a/lib/chef/chef_fs/config.rb b/lib/chef/chef_fs/config.rb index ca273b2cca..fcad6c919f 100644 --- a/lib/chef/chef_fs/config.rb +++ b/lib/chef/chef_fs/config.rb @@ -22,9 +22,74 @@ require 'chef/chef_fs/path_utils' class Chef module ChefFS # - # Helpers to take Chef::Config and create chef_fs and local_fs from it + # Helpers to take Chef::Config and create chef_fs and local_fs (ChefFS + # objects representing the server and local repository, respectively). # class Config + # + # Create a new Config object which can produce a chef_fs and local_fs. + # + # ==== Arguments + # + # [chef_config] + # A hash that looks suspiciously like +Chef::Config+. These hash keys + # include: + # + # :chef_repo_path:: + # The root where all local chef object data is stored. Mirrors + # +Chef::Config.chef_repo_path+ + # :cookbook_path, node_path, ...:: + # Paths to cookbooks/, nodes/, data_bags/, etc. Mirrors + # +Chef::Config.cookbook_path+, etc. Defaults to + # +<chef_repo_path>/cookbooks+, etc. + # :repo_mode:: + # The directory format on disk. 'everything', 'hosted_everything' and + # 'static'. Default: autodetected based on whether the URL has + # "/organizations/NAME." + # :versioned_cookbooks:: + # If true, the repository contains cookbooks with versions in their + # name (apache2-1.0.0). If false, the repository just has one version + # of each cookbook and the directory has the cookbook name (apache2). + # Default: +false+ + # :chef_server_url:: + # The URL to the Chef server, e.g. https://api.opscode.com/organizations/foo. + # Used as the server for the remote chef_fs, and to "guess" repo_mode + # if not specified. + # :node_name:: The username to authenticate to the Chef server with. + # :client_key:: The private key for the user for authentication + # :environment:: The environment in which you are presently working + # :repo_mode:: + # The repository mode, :hosted_everything, :everything or :static. + # This determines the set of subdirectories the Chef server will offer + # up. + # :versioned_cookbooks:: Whether or not to include versions in cookbook names + # + # [cwd] + # The current working directory to base relative Chef paths from. + # Defaults to +Dir.pwd+. + # + # [options] + # A hash of other, not-suspiciously-like-chef-config options: + # :cookbook_version:: + # When downloading cookbooks, download this cookbook version instead + # of the latest. + # + # [ui] + # The object to print output to, with "output", "warn" and "error" + # (looks a little like a Chef::Knife::UI object, obtainable from + # Chef::Knife.ui). + # + # ==== Example + # + # require 'chef/chef_fs/config' + # config = Chef::ChefFS::Config.new + # config.chef_fs.child('cookbooks').children.each do |cookbook| + # puts "Cookbook on server: #{cookbook.name}" + # end + # config.local_fs.child('cookbooks').children.each do |cookbook| + # puts "Local cookbook: #{cookbook.name}" + # end + # def initialize(chef_config = Chef::Config, cwd = Dir.pwd, options = {}, ui = nil) @chef_config = chef_config @cwd = cwd diff --git a/lib/chef/chef_fs/file_system/chef_repository_file_system_root_dir.rb b/lib/chef/chef_fs/file_system/chef_repository_file_system_root_dir.rb index 050da60389..ac272d4c1a 100644 --- a/lib/chef/chef_fs/file_system/chef_repository_file_system_root_dir.rb +++ b/lib/chef/chef_fs/file_system/chef_repository_file_system_root_dir.rb @@ -42,15 +42,17 @@ class Chef # Create a new Chef Repository File System root. # # == Parameters - # - child_paths - a hash of child paths, e.g.: - # "nodes" => [ '/var/nodes', '/home/jkeiser/nodes' ], - # "roles" => [ '/var/roles' ], - # ... - # - root_paths - an array of paths representing the top level, where - # org.json, members.json, and invites.json will be stored. - # - chef_config - a hash of options that looks suspiciously like the ones + # [child_paths] + # A hash of child paths, e.g.: + # "nodes" => [ '/var/nodes', '/home/jkeiser/nodes' ], + # "roles" => [ '/var/roles' ], + # ... + # [root_paths] + # An array of paths representing the top level, where + # +org.json+, +members.json+, and +invites.json+ will be stored. + # [chef_config] - a hash of options that looks suspiciously like the ones # stored in Chef::Config, containing at least these keys: - # - :versioned_cookbooks - whether to include versions in cookbook names + # :versioned_cookbooks:: whether to include versions in cookbook names def initialize(child_paths, root_paths=[], chef_config=Chef::Config) super("", nil) @child_paths = child_paths diff --git a/lib/chef/chef_fs/file_system/chef_server_root_dir.rb b/lib/chef/chef_fs/file_system/chef_server_root_dir.rb index 61a224c307..370308ee0a 100644 --- a/lib/chef/chef_fs/file_system/chef_server_root_dir.rb +++ b/lib/chef/chef_fs/file_system/chef_server_root_dir.rb @@ -46,19 +46,24 @@ class Chef # # == Parameters # - # - root_name - a friendly name for the root, for printing--like "remote" or "chef_central". - # - chef_config - a hash with options that look suspiciously like Chef::Config, including the - # following keys: - # - :chef_server_url - the URL to the Chef server or top of the organization - # - :node_name - the username to authenticate to the Chef server with - # - :client_key - the private key for the user for authentication - # - :environment - the environment in which you are presently working - # - :repo_mode - the repository mode, :hosted_everything, :everything or :static. - # This determines the set of subdirectories the Chef server - # will offer up. - # - :versioned_cookbooks - whether or not to include versions in cookbook names - # - options - other options: - # - :cookbook_version - when cookbooks are retrieved, grab this version for them. + # [root_name] + # A friendly name for the root, for printing--like "remote" or "chef_central". + # [chef_config] + # A hash with options that look suspiciously like Chef::Config, including the + # following keys: + # :chef_server_url:: The URL to the Chef server or top of the organization + # :node_name:: The username to authenticate to the Chef server with + # :client_key:: The private key for the user for authentication + # :environment:: The environment in which you are presently working + # :repo_mode:: + # The repository mode, :hosted_everything, :everything or :static. + # This determines the set of subdirectories the Chef server will + # offer up. + # :versioned_cookbooks:: whether or not to include versions in cookbook names + # [options] + # Other options: + # :cookbook_version:: when cookbooks are retrieved, grab this version for them. + # :freeze:: freeze cookbooks on upload # def initialize(root_name, chef_config, options = {}) super("", nil) diff --git a/lib/chef/client.rb b/lib/chef/client.rb index 2de3ca3e64..161ecddb0f 100644 --- a/lib/chef/client.rb +++ b/lib/chef/client.rb @@ -44,6 +44,7 @@ require 'chef/resource_reporter' require 'chef/run_lock' require 'chef/policy_builder' require 'chef/request_id' +require 'chef/platform/rebooter' require 'ohai' require 'rbconfig' @@ -427,7 +428,9 @@ class Chef run_context = setup_run_context - converge(run_context) + catch (:end_client_run_early) do + converge(run_context) + end save_updated_node @@ -435,6 +438,10 @@ class Chef Chef::Log.info("Chef Run complete in #{run_status.elapsed_time} seconds") run_completed_successfully @events.run_completed(node) + + # rebooting has to be the last thing we do, no exceptions. + Chef::Platform::Rebooter.reboot_if_needed!(node) + true rescue Exception => e # CHEF-3336: Send the error first in case something goes wrong below and we don't know why diff --git a/lib/chef/config.rb b/lib/chef/config.rb index 4e71645dcc..1963a95aab 100644 --- a/lib/chef/config.rb +++ b/lib/chef/config.rb @@ -587,6 +587,51 @@ class Chef default :normal_attribute_whitelist, nil default :override_attribute_whitelist, nil + # 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'. + default :internal_locale do + begin + locales = `locale -a`.split + case + when locales.include?('C.UTF-8') + 'C.UTF-8' + when locales.include?('en_US.UTF-8') + 'en_US.UTF-8' + when locales.include?('en.UTF-8') + 'en.UTF-8' + when guesses = locales.select { |l| l =~ /^en_.*UTF-8$'/ } + guesses.first + else + Chef::Log.warn "Please install an English UTF-8 locale for Chef to use, falling back to C locale and disabling UTF-8 support." + 'C' + end + rescue + Chef::Log.warn "No usable locale -a command found, assuming you have en_US.UTF-8 installed." + 'en_US.UTF-8' + end + end + + # Force UTF-8 Encoding, for when we fire up in the 'C' locale or other strange locales (e.g. + # japanese windows encodings). If we do not do this, then knife upload will fail when a cookbook's + # README.md has UTF-8 characters that do not encode in whatever surrounding encoding we have been + # passed. Effectively, the Chef Ecosystem is globally UTF-8 by default. Anyone who wants to be + # able to upload Shift_JIS or ISO-8859-1 files needs to mark *those* files explicitly with + # magic tags to make ruby correctly identify the encoding being used. Changing this default will + # break Chef community cookbooks and is very highly discouraged. + default :ruby_encoding, Encoding::UTF_8 + # 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. diff --git a/lib/chef/dsl/reboot_pending.rb b/lib/chef/dsl/reboot_pending.rb index 9f80d38c61..a81debce99 100644 --- a/lib/chef/dsl/reboot_pending.rb +++ b/lib/chef/dsl/reboot_pending.rb @@ -27,10 +27,13 @@ class Chef include Chef::DSL::PlatformIntrospection # Returns true if the system needs a reboot or is expected to reboot - # Raises UnsupportedPlatform if this functionality isn't provided yet + # Note that we will silently miss any other platform-specific reboot notices besides Windows+Ubuntu. def reboot_pending? - if platform?("windows") + # don't break when used as a mixin in contexts without #node (e.g. specs). + if self.respond_to?(:node, true) && node.run_context.reboot_requested? + true + elsif platform?("windows") # PendingFileRenameOperations contains pairs (REG_MULTI_SZ) of filenames that cannot be updated # due to a file being in use (usually a temporary file and a system file) # \??\c:\temp\test.sys!\??\c:\winnt\system32\test.sys @@ -53,7 +56,7 @@ class Chef # This should work for Debian as well if update-notifier-common happens to be installed. We need an API for that. File.exists?('/var/run/reboot-required') else - raise Chef::Exceptions::UnsupportedPlatform.new(node[:platform]) + false end end end diff --git a/lib/chef/knife/core/bootstrap_context.rb b/lib/chef/knife/core/bootstrap_context.rb index 6bc48636c5..87c25ca160 100644 --- a/lib/chef/knife/core/bootstrap_context.rb +++ b/lib/chef/knife/core/bootstrap_context.rb @@ -44,8 +44,10 @@ class Chef def encrypted_data_bag_secret knife_config[:secret] || begin - if knife_config[:secret_file] && File.exist?(knife_config[:secret_file]) - IO.read(File.expand_path(knife_config[:secret_file])) + secret_file_path = knife_config[:secret_file] + expanded_secret_file_path = File.expand_path(secret_file_path.to_s) + if secret_file_path && File.exist?(expanded_secret_file_path) + IO.read(expanded_secret_file_path) else nil end diff --git a/lib/chef/mixin/shell_out.rb b/lib/chef/mixin/shell_out.rb index 881c94b862..82772b584a 100644 --- a/lib/chef/mixin/shell_out.rb +++ b/lib/chef/mixin/shell_out.rb @@ -30,32 +30,39 @@ class Chef # Generally speaking, 'extend Chef::Mixin::ShellOut' in your recipes and include 'Chef::Mixin::ShellOut' in your LWRPs # You can also call Mixlib::Shellout.new directly, but you lose all of the above functionality + # we use 'en_US.UTF-8' by default because we parse localized strings in English as an API and + # generally must support UTF-8 unicode. def shell_out(*command_args) - cmd = Mixlib::ShellOut.new(*run_command_compatible_options(command_args)) - cmd.live_stream ||= io_for_live_stream - cmd.run_command - cmd + args = command_args.dup + if args.last.is_a?(Hash) + options = args.pop.dup + env_key = options.has_key?(:env) ? :env : :environment + options[env_key] ||= {} + options[env_key] = options[env_key].dup + options[env_key]['LC_ALL'] ||= Chef::Config[:internal_locale] unless options[env_key].has_key?('LC_ALL') + args << options + else + args << { :environment => { 'LC_ALL' => Chef::Config[:internal_locale] } } + end + + shell_out_command(*args) end + # call shell_out (using en_US.UTF-8) and raise errors def shell_out!(*command_args) - cmd= shell_out(*command_args) + cmd = shell_out(*command_args) cmd.error! cmd end - # environment['LC_ALL'] should be nil or what the user specified def shell_out_with_systems_locale(*command_args) - args = command_args.dup - if args.last.is_a?(Hash) - options = args.last - env_key = options.has_key?(:env) ? :env : :environment - options[env_key] ||= {} - options[env_key]['LC_ALL'] ||= nil - else - args << { :environment => { 'LC_ALL' => nil } } - end + shell_out_command(*command_args) + end - shell_out(*args) + def shell_out_with_systems_locale!(*command_args) + cmd = shell_out_with_systems_locale(*command_args) + cmd.error! + cmd end DEPRECATED_OPTIONS = @@ -82,6 +89,13 @@ class Chef private + def shell_out_command(*command_args) + cmd = Mixlib::ShellOut.new(*run_command_compatible_options(command_args)) + cmd.live_stream ||= io_for_live_stream + cmd.run_command + cmd + end + def deprecate_option(old_option, new_option) Chef::Log.logger.warn "DEPRECATION: Chef::Mixin::ShellOut option :#{old_option} is deprecated. Use :#{new_option}" end diff --git a/lib/chef/platform/rebooter.rb b/lib/chef/platform/rebooter.rb new file mode 100644 index 0000000000..b46f0e394c --- /dev/null +++ b/lib/chef/platform/rebooter.rb @@ -0,0 +1,54 @@ +# +# Author:: Chris Doherty <cdoherty@getchef.com>) +# Copyright:: Copyright (c) 2014 Chef, Inc. +# License:: Apache License, Version 2.0 +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +require 'chef/dsl/reboot_pending' +require 'chef/log' +require 'chef/platform' + +class Chef + class Platform + module Rebooter + extend Chef::Mixin::ShellOut + + class << self + + def reboot!(node) + reboot_info = node.run_context.reboot_info + + cmd = if Chef::Platform.windows? + # should this do /f as well? do we then need a minimum delay to let apps quit? + "shutdown /r /t #{reboot_info[:delay_mins]} /c \"#{reboot_info[:reason]}\"" + else + # probably Linux-only. + "shutdown -r +#{reboot_info[:delay_mins]} \"#{reboot_info[:reason]}\"" + end + + Chef::Log.warn "Rebooting server at a recipe's request. Details: #{reboot_info.inspect}" + shell_out!(cmd) + end + + # this is a wrapper function so Chef::Client only needs a single line of code. + def reboot_if_needed!(node) + if node.run_context.reboot_requested? + reboot!(node) + end + end + end + end + end +end diff --git a/lib/chef/provider/ifconfig.rb b/lib/chef/provider/ifconfig.rb index 31f88e5406..ac52100b56 100644 --- a/lib/chef/provider/ifconfig.rb +++ b/lib/chef/provider/ifconfig.rb @@ -19,6 +19,7 @@ require 'chef/log' require 'chef/mixin/command' require 'chef/provider' +require 'chef/resource/file' require 'chef/exceptions' require 'erb' @@ -109,11 +110,11 @@ class Chef :command => command ) Chef::Log.info("#{@new_resource} added") - # Write out the config files - generate_config end end end + # Write out the config files + generate_config end def action_enable @@ -140,12 +141,12 @@ class Chef run_command( :command => command ) - delete_config Chef::Log.info("#{@new_resource} deleted") end else Chef::Log.debug("#{@new_resource} does not exist - nothing to do") end + delete_config end def action_disable @@ -168,27 +169,25 @@ class Chef ! @config_template.nil? and ! @config_path.nil? end + def resource_for_config(path) + Chef::Resource::File.new(path, run_context) + end + def generate_config return unless can_generate_config? b = binding template = ::ERB.new(@config_template) - converge_by ("generate configuration file : #{@config_path}") do - network_file = ::File.new(@config_path, "w") - network_file.puts(template.result(b)) - network_file.close - end - Chef::Log.info("#{@new_resource} created configuration file") + config = resource_for_config(@config_path) + config.content(template.result(b)) + config.run_action(:create) + @new_resource.updated_by_last_action(true) if config.updated? end def delete_config return unless can_generate_config? - require 'fileutils' - if ::File.exist?(@config_path) - converge_by ("delete the #{@config_path}") do - FileUtils.rm_f(@config_path, :verbose => false) - end - end - Chef::Log.info("#{@new_resource} deleted configuration file") + config = resource_for_config(@config_path) + config.run_action(:delete) + @new_resource.updated_by_last_action(true) if config.updated? end private diff --git a/lib/chef/provider/link.rb b/lib/chef/provider/link.rb index d6602c2e03..af2fe4a84f 100644 --- a/lib/chef/provider/link.rb +++ b/lib/chef/provider/link.rb @@ -83,7 +83,7 @@ class Chef end def canonicalize(path) - Chef::Platform.windows? ? path.gsub('/', '\\') : path + Chef::Util::PathHelper.canonical_path(path) end def action_create diff --git a/lib/chef/provider/package/aix.rb b/lib/chef/provider/package/aix.rb index 9fb87d6ea0..da3e6d1684 100644 --- a/lib/chef/provider/package/aix.rb +++ b/lib/chef/provider/package/aix.rb @@ -112,14 +112,10 @@ class Chef def install_package(name, version) Chef::Log.debug("#{@new_resource} package install options: #{@new_resource.options}") if @new_resource.options.nil? - run_command_with_systems_locale( - :command => "installp -aYF -d #{@new_resource.source} #{@new_resource.package_name}" - ) + shell_out!( "installp -aYF -d #{@new_resource.source} #{@new_resource.package_name}" ) Chef::Log.debug("#{@new_resource} installed version #{@new_resource.version} from: #{@new_resource.source}") else - run_command_with_systems_locale( - :command => "installp -aYF #{expand_options(@new_resource.options)} -d #{@new_resource.source} #{@new_resource.package_name}" - ) + shell_out!( "installp -aYF #{expand_options(@new_resource.options)} -d #{@new_resource.source} #{@new_resource.package_name}" ) Chef::Log.debug("#{@new_resource} installed version #{@new_resource.version} from: #{@new_resource.source}") end end @@ -128,14 +124,10 @@ class Chef def remove_package(name, version) if @new_resource.options.nil? - run_command_with_systems_locale( - :command => "installp -u #{name}" - ) + shell_out!( "installp -u #{name}" ) Chef::Log.debug("#{@new_resource} removed version #{@new_resource.version}") else - run_command_with_systems_locale( - :command => "installp -u #{expand_options(@new_resource.options)} #{name}" - ) + shell_out!( "installp -u #{expand_options(@new_resource.options)} #{name}" ) Chef::Log.debug("#{@new_resource} removed version #{@new_resource.version}") end end diff --git a/lib/chef/provider/package/ips.rb b/lib/chef/provider/package/ips.rb index 92b41b3627..4090507303 100644 --- a/lib/chef/provider/package/ips.rb +++ b/lib/chef/provider/package/ips.rb @@ -65,15 +65,13 @@ class Chef def install_package(name, version) package_name = "#{name}@#{version}" normal_command = "pkg#{expand_options(@new_resource.options)} install -q #{package_name}" - if @new_resource.respond_to?(:accept_license) and @new_resource.accept_license - command = normal_command.gsub('-q', '-q --accept') - else - command = normal_command - end - begin - run_command_with_systems_locale(:command => command) - rescue - end + command = + if @new_resource.respond_to?(:accept_license) and @new_resource.accept_license + normal_command.gsub('-q', '-q --accept') + else + normal_command + end + shell_out(command) end def upgrade_package(name, version) @@ -82,9 +80,7 @@ class Chef def remove_package(name, version) package_name = "#{name}@#{version}" - run_command_with_systems_locale( - :command => "pkg#{expand_options(@new_resource.options)} uninstall -q #{package_name}" - ) + shell_out!( "pkg#{expand_options(@new_resource.options)} uninstall -q #{package_name}" ) end end end diff --git a/lib/chef/provider/package/macports.rb b/lib/chef/provider/package/macports.rb index 6ef303ee4f..05247e6d31 100644 --- a/lib/chef/provider/package/macports.rb +++ b/lib/chef/provider/package/macports.rb @@ -45,27 +45,21 @@ class Chef unless @current_resource.version == version command = "port#{expand_options(@new_resource.options)} install #{name}" command << " @#{version}" if version and !version.empty? - run_command_with_systems_locale( - :command => command - ) + shell_out!(command) end end def purge_package(name, version) command = "port#{expand_options(@new_resource.options)} uninstall #{name}" command << " @#{version}" if version and !version.empty? - run_command_with_systems_locale( - :command => command - ) + shell_out!(command) end def remove_package(name, version) command = "port#{expand_options(@new_resource.options)} deactivate #{name}" command << " @#{version}" if version and !version.empty? - run_command_with_systems_locale( - :command => command - ) + shell_out!(command) end def upgrade_package(name, version) @@ -78,9 +72,7 @@ class Chef # that hasn't been installed. install_package(name, version) elsif current_version != version - run_command_with_systems_locale( - :command => "port#{expand_options(@new_resource.options)} upgrade #{name} @#{version}" - ) + shell_out!( "port#{expand_options(@new_resource.options)} upgrade #{name} @#{version}" ) end end diff --git a/lib/chef/provider/package/pacman.rb b/lib/chef/provider/package/pacman.rb index 2e8bb7850b..1014ebcaa5 100644 --- a/lib/chef/provider/package/pacman.rb +++ b/lib/chef/provider/package/pacman.rb @@ -86,9 +86,7 @@ class Chef end def install_package(name, version) - run_command_with_systems_locale( - :command => "pacman --sync --noconfirm --noprogressbar#{expand_options(@new_resource.options)} #{name}" - ) + shell_out!( "pacman --sync --noconfirm --noprogressbar#{expand_options(@new_resource.options)} #{name}" ) end def upgrade_package(name, version) @@ -96,9 +94,7 @@ class Chef end def remove_package(name, version) - run_command_with_systems_locale( - :command => "pacman --remove --noconfirm --noprogressbar#{expand_options(@new_resource.options)} #{name}" - ) + shell_out!( "pacman --remove --noconfirm --noprogressbar#{expand_options(@new_resource.options)} #{name}" ) end def purge_package(name, version) diff --git a/lib/chef/provider/package/portage.rb b/lib/chef/provider/package/portage.rb index 6a3587558a..7e0eebd0d9 100644 --- a/lib/chef/provider/package/portage.rb +++ b/lib/chef/provider/package/portage.rb @@ -110,9 +110,7 @@ class Chef pkg = "~#{name}-#{$1}" end - run_command_with_systems_locale( - :command => "emerge -g --color n --nospinner --quiet#{expand_options(@new_resource.options)} #{pkg}" - ) + shell_out!( "emerge -g --color n --nospinner --quiet#{expand_options(@new_resource.options)} #{pkg}" ) end def upgrade_package(name, version) @@ -126,9 +124,7 @@ class Chef pkg = "#{@new_resource.package_name}" end - run_command_with_systems_locale( - :command => "emerge --unmerge --color n --nospinner --quiet#{expand_options(@new_resource.options)} #{pkg}" - ) + shell_out!( "emerge --unmerge --color n --nospinner --quiet#{expand_options(@new_resource.options)} #{pkg}" ) end def purge_package(name, version) diff --git a/lib/chef/provider/package/rpm.rb b/lib/chef/provider/package/rpm.rb index bbb561bd15..c0a6444252 100644 --- a/lib/chef/provider/package/rpm.rb +++ b/lib/chef/provider/package/rpm.rb @@ -90,13 +90,9 @@ class Chef def install_package(name, version) unless @current_resource.version - run_command_with_systems_locale( - :command => "rpm #{@new_resource.options} -i #{@new_resource.source}" - ) + shell_out!( "rpm #{@new_resource.options} -i #{@new_resource.source}" ) else - run_command_with_systems_locale( - :command => "rpm #{@new_resource.options} -U #{@new_resource.source}" - ) + shell_out!( "rpm #{@new_resource.options} -U #{@new_resource.source}" ) end end @@ -104,13 +100,9 @@ class Chef def remove_package(name, version) if version - run_command_with_systems_locale( - :command => "rpm #{@new_resource.options} -e #{name}-#{version}" - ) + shell_out!( "rpm #{@new_resource.options} -e #{name}-#{version}" ) else - run_command_with_systems_locale( - :command => "rpm #{@new_resource.options} -e #{name}" - ) + shell_out!( "rpm #{@new_resource.options} -e #{name}" ) end end diff --git a/lib/chef/provider/package/solaris.rb b/lib/chef/provider/package/solaris.rb index 0f45b61e18..19f844b66a 100644 --- a/lib/chef/provider/package/solaris.rb +++ b/lib/chef/provider/package/solaris.rb @@ -112,9 +112,7 @@ class Chef else command = "pkgadd -n -d #{@new_resource.source} all" end - run_command_with_systems_locale( - :command => command - ) + shell_out!(command) Chef::Log.debug("#{@new_resource} installed version #{@new_resource.version} from: #{@new_resource.source}") else if ::File.directory?(@new_resource.source) # CHEF-4469 @@ -122,23 +120,17 @@ class Chef else command = "pkgadd -n#{expand_options(@new_resource.options)} -d #{@new_resource.source} all" end - run_command_with_systems_locale( - :command => command - ) + shell_out!(command) Chef::Log.debug("#{@new_resource} installed version #{@new_resource.version} from: #{@new_resource.source}") end end def remove_package(name, version) if @new_resource.options.nil? - run_command_with_systems_locale( - :command => "pkgrm -n #{name}" - ) + shell_out!( "pkgrm -n #{name}" ) Chef::Log.debug("#{@new_resource} removed version #{@new_resource.version}") else - run_command_with_systems_locale( - :command => "pkgrm -n#{expand_options(@new_resource.options)} #{name}" - ) + shell_out!( "pkgrm -n#{expand_options(@new_resource.options)} #{name}" ) Chef::Log.debug("#{@new_resource} removed version #{@new_resource.version}") end end diff --git a/lib/chef/provider/reboot.rb b/lib/chef/provider/reboot.rb new file mode 100644 index 0000000000..8dde4653ec --- /dev/null +++ b/lib/chef/provider/reboot.rb @@ -0,0 +1,69 @@ +# +# Author:: Chris Doherty <cdoherty@getchef.com>) +# Copyright:: Copyright (c) 2014 Chef, Inc. +# License:: Apache License, Version 2.0 +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +require 'chef/log' +require 'chef/provider' + +class Chef + class Provider + class Reboot < Chef::Provider + + def whyrun_supported? + true + end + + def load_current_resource + @current_resource ||= Chef::Resource::Reboot.new(@new_resource.name) + @current_resource.reason(@new_resource.reason) + @current_resource.delay_mins(@new_resource.delay_mins) + @current_resource + end + + def request_reboot + node.run_context.request_reboot( + :delay_mins => @new_resource.delay_mins, + :reason => @new_resource.reason, + :timestamp => Time.now, + :requested_by => @new_resource.name + ) + end + + def action_request_reboot + converge_by("request a system reboot to occur if the run succeeds") do + Chef::Log.warn "Reboot requested:'#{@new_resource.name}'" + request_reboot + end + end + + def action_reboot_now + converge_by("rebooting the system immediately") do + Chef::Log.warn "Rebooting system immediately, requested by '#{@new_resource.name}'" + request_reboot + throw :end_client_run_early + end + end + + def action_cancel + converge_by("cancel any existing end-of-run reboot request") do + Chef::Log.warn "Reboot canceled: '#{@new_resource.name}'" + node.run_context.cancel_reboot + end + end + end + end +end diff --git a/lib/chef/provider/service/debian.rb b/lib/chef/provider/service/debian.rb index 06fe7fc480..1ebef90349 100644 --- a/lib/chef/provider/service/debian.rb +++ b/lib/chef/provider/service/debian.rb @@ -130,15 +130,15 @@ class Chef def enable_service if @new_resource.priority.is_a? Integer - run_command(:command => "/usr/sbin/update-rc.d -f #{@new_resource.service_name} remove") - run_command(:command => "/usr/sbin/update-rc.d #{@new_resource.service_name} defaults #{@new_resource.priority} #{100 - @new_resource.priority}") + shell_out!("/usr/sbin/update-rc.d -f #{@new_resource.service_name} remove") + shell_out!("/usr/sbin/update-rc.d #{@new_resource.service_name} defaults #{@new_resource.priority} #{100 - @new_resource.priority}") elsif @new_resource.priority.is_a? Hash # we call the same command regardless of we're enabling or disabling # users passing a Hash are responsible for setting their own start priorities set_priority else # No priority, go with update-rc.d defaults - run_command(:command => "/usr/sbin/update-rc.d -f #{@new_resource.service_name} remove") - run_command(:command => "/usr/sbin/update-rc.d #{@new_resource.service_name} defaults") + shell_out!("/usr/sbin/update-rc.d -f #{@new_resource.service_name} remove") + shell_out!("/usr/sbin/update-rc.d #{@new_resource.service_name} defaults") end end @@ -146,16 +146,16 @@ class Chef def disable_service if @new_resource.priority.is_a? Integer # Stop processes in reverse order of start using '100 - start_priority' - run_command(:command => "/usr/sbin/update-rc.d -f #{@new_resource.service_name} remove") - run_command(:command => "/usr/sbin/update-rc.d -f #{@new_resource.service_name} stop #{100 - @new_resource.priority} 2 3 4 5 .") + shell_out!("/usr/sbin/update-rc.d -f #{@new_resource.service_name} remove") + shell_out!("/usr/sbin/update-rc.d -f #{@new_resource.service_name} stop #{100 - @new_resource.priority} 2 3 4 5 .") elsif @new_resource.priority.is_a? Hash # we call the same command regardless of we're enabling or disabling # users passing a Hash are responsible for setting their own stop priorities set_priority else # no priority, using '100 - 20 (update-rc.d default)' to stop in reverse order of start - run_command(:command => "/usr/sbin/update-rc.d -f #{@new_resource.service_name} remove") - run_command(:command => "/usr/sbin/update-rc.d -f #{@new_resource.service_name} stop 80 2 3 4 5 .") + shell_out!("/usr/sbin/update-rc.d -f #{@new_resource.service_name} remove") + shell_out!("/usr/sbin/update-rc.d -f #{@new_resource.service_name} stop 80 2 3 4 5 .") end end @@ -166,8 +166,8 @@ class Chef priority = o[1] args += "#{action} #{priority} #{level} . " end - run_command(:command => "/usr/sbin/update-rc.d -f #{@new_resource.service_name} remove") - run_command(:command => "/usr/sbin/update-rc.d #{@new_resource.service_name} #{args}") + shell_out!("/usr/sbin/update-rc.d -f #{@new_resource.service_name} remove") + shell_out!("/usr/sbin/update-rc.d #{@new_resource.service_name} #{args}") end end end diff --git a/lib/chef/provider/service/freebsd.rb b/lib/chef/provider/service/freebsd.rb index 7b69957cc6..08d58232e1 100644 --- a/lib/chef/provider/service/freebsd.rb +++ b/lib/chef/provider/service/freebsd.rb @@ -78,7 +78,7 @@ class Chef if new_resource.start_command super else - shell_out!("#{init_command} faststart") + shell_out_with_systems_locale!("#{init_command} faststart") end end @@ -86,7 +86,7 @@ class Chef if new_resource.stop_command super else - shell_out!("#{init_command} faststop") + shell_out_with_systems_locale!("#{init_command} faststop") end end @@ -94,7 +94,7 @@ class Chef if new_resource.restart_command super elsif new_resource.supports[:restart] - shell_out!("#{init_command} fastrestart") + shell_out_with_systems_locale!("#{init_command} fastrestart") else stop_service sleep 1 diff --git a/lib/chef/provider/service/gentoo.rb b/lib/chef/provider/service/gentoo.rb index 1559c7893f..a68abfebc9 100644 --- a/lib/chef/provider/service/gentoo.rb +++ b/lib/chef/provider/service/gentoo.rb @@ -58,10 +58,10 @@ class Chef::Provider::Service::Gentoo < Chef::Provider::Service::Init end def enable_service() - run_command(:command => "/sbin/rc-update add #{@new_resource.service_name} default") + shell_out!("/sbin/rc-update add #{@new_resource.service_name} default") end def disable_service() - run_command(:command => "/sbin/rc-update del #{@new_resource.service_name} default") + shell_out!("/sbin/rc-update del #{@new_resource.service_name} default") end end diff --git a/lib/chef/provider/service/init.rb b/lib/chef/provider/service/init.rb index 23d9dde80a..5d8bb5bb38 100644 --- a/lib/chef/provider/service/init.rb +++ b/lib/chef/provider/service/init.rb @@ -50,7 +50,7 @@ class Chef if @new_resource.start_command super else - shell_out!("#{default_init_command} start") + shell_out_with_systems_locale!("#{default_init_command} start") end end @@ -58,7 +58,7 @@ class Chef if @new_resource.stop_command super else - shell_out!("#{default_init_command} stop") + shell_out_with_systems_locale!("#{default_init_command} stop") end end @@ -66,7 +66,7 @@ class Chef if @new_resource.restart_command super elsif @new_resource.supports[:restart] - shell_out!("#{default_init_command} restart") + shell_out_with_systems_locale!("#{default_init_command} restart") else stop_service sleep 1 @@ -78,7 +78,7 @@ class Chef if @new_resource.reload_command super elsif @new_resource.supports[:reload] - shell_out!("#{default_init_command} reload") + shell_out_with_systems_locale!("#{default_init_command} reload") end end end diff --git a/lib/chef/provider/service/insserv.rb b/lib/chef/provider/service/insserv.rb index 35767ee7b9..f4c85dd9d3 100644 --- a/lib/chef/provider/service/insserv.rb +++ b/lib/chef/provider/service/insserv.rb @@ -37,12 +37,12 @@ class Chef end def enable_service() - run_command(:command => "/sbin/insserv -r -f #{@new_resource.service_name}") - run_command(:command => "/sbin/insserv -d -f #{@new_resource.service_name}") + shell_out!("/sbin/insserv -r -f #{@new_resource.service_name}") + shell_out!("/sbin/insserv -d -f #{@new_resource.service_name}") end def disable_service() - run_command(:command => "/sbin/insserv -r -f #{@new_resource.service_name}") + shell_out!("/sbin/insserv -r -f #{@new_resource.service_name}") end end end diff --git a/lib/chef/provider/service/macosx.rb b/lib/chef/provider/service/macosx.rb index 36930ee4ac..cf5e554559 100644 --- a/lib/chef/provider/service/macosx.rb +++ b/lib/chef/provider/service/macosx.rb @@ -83,7 +83,7 @@ class Chef if @new_resource.start_command super else - shell_out!("launchctl load -w '#{@plist}'", :user => @owner_uid, :group => @owner_gid) + shell_out_with_systems_locale!("launchctl load -w '#{@plist}'", :user => @owner_uid, :group => @owner_gid) end end end @@ -95,7 +95,7 @@ class Chef if @new_resource.stop_command super else - shell_out!("launchctl unload '#{@plist}'", :user => @owner_uid, :group => @owner_gid) + shell_out_with_systems_locale!("launchctl unload '#{@plist}'", :user => @owner_uid, :group => @owner_gid) end end end diff --git a/lib/chef/provider/service/simple.rb b/lib/chef/provider/service/simple.rb index 0eb983a0bf..bd51d15f84 100644 --- a/lib/chef/provider/service/simple.rb +++ b/lib/chef/provider/service/simple.rb @@ -85,16 +85,16 @@ class Chef end def start_service - shell_out!(@new_resource.start_command) + shell_out_with_systems_locale!(@new_resource.start_command) end def stop_service - shell_out!(@new_resource.stop_command) + shell_out_with_systems_locale!(@new_resource.stop_command) end def restart_service if @new_resource.restart_command - shell_out!(@new_resource.restart_command) + shell_out_with_systems_locale!(@new_resource.restart_command) else stop_service sleep 1 @@ -103,7 +103,7 @@ class Chef end def reload_service - shell_out!(@new_resource.reload_command) + shell_out_with_systems_locale!(@new_resource.reload_command) end protected diff --git a/lib/chef/provider/service/solaris.rb b/lib/chef/provider/service/solaris.rb index 0c47a3462b..f0584dcf6d 100644 --- a/lib/chef/provider/service/solaris.rb +++ b/lib/chef/provider/service/solaris.rb @@ -56,7 +56,7 @@ class Chef alias_method :start_service, :enable_service def reload_service - shell_out!("#{default_init_command} refresh #{@new_resource.service_name}") + shell_out_with_systems_locale!("#{default_init_command} refresh #{@new_resource.service_name}") end def restart_service diff --git a/lib/chef/provider/service/systemd.rb b/lib/chef/provider/service/systemd.rb index 6231603d03..31feee65d4 100644 --- a/lib/chef/provider/service/systemd.rb +++ b/lib/chef/provider/service/systemd.rb @@ -28,7 +28,7 @@ class Chef::Provider::Service::Systemd < Chef::Provider::Service::Simple if @new_resource.status_command Chef::Log.debug("#{@new_resource} you have specified a status command, running..") - unless shell_out_with_systems_locale(@new_resource.status_command).error? + unless shell_out(@new_resource.status_command).error? @current_resource.running(true) else @status_check_success = false @@ -61,7 +61,7 @@ class Chef::Provider::Service::Systemd < Chef::Provider::Service::Simple if @new_resource.start_command super else - shell_out_with_systems_locale("/bin/systemctl start #{@new_resource.service_name}") + shell_out_with_systems_locale!("/bin/systemctl start #{@new_resource.service_name}") end end end @@ -73,7 +73,7 @@ class Chef::Provider::Service::Systemd < Chef::Provider::Service::Simple if @new_resource.stop_command super else - shell_out_with_systems_locale("/bin/systemctl stop #{@new_resource.service_name}") + shell_out_with_systems_locale!("/bin/systemctl stop #{@new_resource.service_name}") end end end @@ -82,7 +82,7 @@ class Chef::Provider::Service::Systemd < Chef::Provider::Service::Simple if @new_resource.restart_command super else - shell_out_with_systems_locale("/bin/systemctl restart #{@new_resource.service_name}") + shell_out_with_systems_locale!("/bin/systemctl restart #{@new_resource.service_name}") end end @@ -91,7 +91,7 @@ class Chef::Provider::Service::Systemd < Chef::Provider::Service::Simple super else if @current_resource.running - shell_out_with_systems_locale("/bin/systemctl reload #{@new_resource.service_name}") + shell_out_with_systems_locale!("/bin/systemctl reload #{@new_resource.service_name}") else start_service end @@ -99,18 +99,18 @@ class Chef::Provider::Service::Systemd < Chef::Provider::Service::Simple end def enable_service - shell_out_with_systems_locale("/bin/systemctl enable #{@new_resource.service_name}") + shell_out!("/bin/systemctl enable #{@new_resource.service_name}") end def disable_service - shell_out_with_systems_locale("/bin/systemctl disable #{@new_resource.service_name}") + shell_out!("/bin/systemctl disable #{@new_resource.service_name}") end def is_active? - shell_out_with_systems_locale("/bin/systemctl is-active #{@new_resource.service_name} --quiet").exitstatus == 0 + shell_out("/bin/systemctl is-active #{@new_resource.service_name} --quiet").exitstatus == 0 end def is_enabled? - shell_out_with_systems_locale("/bin/systemctl is-enabled #{@new_resource.service_name} --quiet").exitstatus == 0 + shell_out("/bin/systemctl is-enabled #{@new_resource.service_name} --quiet").exitstatus == 0 end end diff --git a/lib/chef/provider/service/upstart.rb b/lib/chef/provider/service/upstart.rb index c81a8a50dc..670bf9e5f8 100644 --- a/lib/chef/provider/service/upstart.rb +++ b/lib/chef/provider/service/upstart.rb @@ -97,10 +97,10 @@ class Chef Chef::Log.debug("#{@new_resource} you have specified a status command, running..") begin - if run_command_with_systems_locale(:command => @new_resource.status_command) == 0 + if shell_out!(@new_resource.status_command) == 0 @current_resource.running true end - rescue Chef::Exceptions::Exec + rescue @command_success = false @current_resource.running false nil @@ -153,7 +153,7 @@ class Chef if @new_resource.start_command super else - run_command_with_systems_locale(:command => "/sbin/start #{@job}") + shell_out_with_systems_locale!("/sbin/start #{@job}") end end end @@ -167,7 +167,7 @@ class Chef if @new_resource.stop_command super else - run_command_with_systems_locale(:command => "/sbin/stop #{@job}") + shell_out_with_systems_locale!("/sbin/stop #{@job}") end end end @@ -179,7 +179,7 @@ class Chef # Older versions of upstart would fail on restart if the service was currently stopped, check for that. LP:430883 else if @current_resource.running - run_command_with_systems_locale(:command => "/sbin/restart #{@job}") + shell_out_with_systems_locale!("/sbin/restart #{@job}") else start_service end @@ -191,7 +191,7 @@ class Chef super else # upstart >= 0.6.3-4 supports reload (HUP) - run_command_with_systems_locale(:command => "/sbin/reload #{@job}") + shell_out_with_systems_locale!("/sbin/reload #{@job}") end end diff --git a/lib/chef/provider/subversion.rb b/lib/chef/provider/subversion.rb index 81ed639c53..6cf31c8ec8 100644 --- a/lib/chef/provider/subversion.rb +++ b/lib/chef/provider/subversion.rb @@ -60,7 +60,7 @@ class Chef def action_checkout if target_dir_non_existent_or_empty? converge_by("perform checkout of #{@new_resource.repository} into #{@new_resource.destination}") do - run_command(run_options(:command => checkout_command)) + shell_out!(run_options(command: checkout_command)) end else Chef::Log.debug "#{@new_resource} checkout destination #{@new_resource.destination} already exists or is a non-empty directory - nothing to do" @@ -77,7 +77,7 @@ class Chef def action_force_export converge_by("export #{@new_resource.repository} into #{@new_resource.destination}") do - run_command(run_options(:command => export_command)) + shell_out!(run_options(command: export_command)) end end @@ -88,7 +88,7 @@ class Chef Chef::Log.debug "#{@new_resource} current revision: #{current_rev} target revision: #{revision_int}" unless current_revision_matches_target_revision? converge_by("sync #{@new_resource.destination} from #{@new_resource.repository}") do - run_command(run_options(:command => sync_command)) + shell_out!(run_options(command: sync_command)) Chef::Log.info "#{@new_resource} updated to revision: #{revision_int}" end end @@ -100,14 +100,14 @@ class Chef def sync_command c = scm :update, @new_resource.svn_arguments, verbose, authentication, "-r#{revision_int}", @new_resource.destination Chef::Log.debug "#{@new_resource} updated working copy #{@new_resource.destination} to revision #{@new_resource.revision}" - c + c end def checkout_command c = scm :checkout, @new_resource.svn_arguments, verbose, authentication, "-r#{revision_int}", @new_resource.repository, @new_resource.destination Chef::Log.info "#{@new_resource} checked out #{@new_resource.repository} at revision #{@new_resource.revision} to #{@new_resource.destination}" - c + c end def export_command @@ -116,7 +116,7 @@ class Chef "-r#{revision_int}" << @new_resource.repository << @new_resource.destination c = scm :export, *args Chef::Log.info "#{@new_resource} exported #{@new_resource.repository} at revision #{@new_resource.revision} to #{@new_resource.destination}" - c + c end # If the specified revision isn't an integer ("HEAD" for example), look diff --git a/lib/chef/provider/whyrun_safe_ruby_block.rb b/lib/chef/provider/whyrun_safe_ruby_block.rb index 4b491a4f60..e5f35debd7 100644 --- a/lib/chef/provider/whyrun_safe_ruby_block.rb +++ b/lib/chef/provider/whyrun_safe_ruby_block.rb @@ -19,7 +19,7 @@ class Chef class Provider class WhyrunSafeRubyBlock < Chef::Provider::RubyBlock - def action_create + def action_run @new_resource.block.call @new_resource.updated_by_last_action(true) @run_context.events.resource_update_applied(@new_resource, :create, "execute the whyrun_safe_ruby_block #{@new_resource.name}") diff --git a/lib/chef/providers.rb b/lib/chef/providers.rb index 3c9e94e6f7..1b0ff3ffff 100644 --- a/lib/chef/providers.rb +++ b/lib/chef/providers.rb @@ -39,6 +39,7 @@ require 'chef/provider/mdadm' require 'chef/provider/mount' require 'chef/provider/package' require 'chef/provider/powershell_script' +require 'chef/provider/reboot' require 'chef/provider/remote_directory' require 'chef/provider/remote_file' require 'chef/provider/route' diff --git a/lib/chef/resource/reboot.rb b/lib/chef/resource/reboot.rb new file mode 100644 index 0000000000..d6caafdea8 --- /dev/null +++ b/lib/chef/resource/reboot.rb @@ -0,0 +1,48 @@ +# +# Author:: Chris Doherty <cdoherty@getchef.com>) +# Copyright:: Copyright (c) 2014 Chef, Inc. +# License:: Apache License, Version 2.0 +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +require 'chef/resource' + +# In using this resource via notifications, it's important to *only* use +# immediate notifications. Delayed notifications produce unintuitive and +# probably undesired results. +class Chef + class Resource + class Reboot < Chef::Resource + def initialize(name, run_context=nil) + super + @resource_name = :reboot + @provider = Chef::Provider::Reboot + @allowed_actions = [:request_reboot, :reboot_now, :cancel] + + @reason = "Reboot by Chef" + @delay_mins = 0 + + # no default action. + end + + def reason(arg=nil) + set_or_return(:reason, arg, :kind_of => String) + end + + def delay_mins(arg=nil) + set_or_return(:delay_mins, arg, :kind_of => Fixnum) + end + end + end +end diff --git a/lib/chef/resources.rb b/lib/chef/resources.rb index 93ff682288..8c2f71bd30 100644 --- a/lib/chef/resources.rb +++ b/lib/chef/resources.rb @@ -53,6 +53,7 @@ require 'chef/resource/perl' require 'chef/resource/portage_package' require 'chef/resource/powershell_script' require 'chef/resource/python' +require 'chef/resource/reboot' require 'chef/resource/registry_key' require 'chef/resource/remote_directory' require 'chef/resource/remote_file' diff --git a/lib/chef/run_context.rb b/lib/chef/run_context.rb index 3dd53f0f8f..bbe2f9eba0 100644 --- a/lib/chef/run_context.rb +++ b/lib/chef/run_context.rb @@ -61,6 +61,9 @@ class Chef # Event dispatcher for this run. attr_reader :events + # Hash of factoids for a reboot request. + attr_reader :reboot_info + # Creates a new Chef::RunContext object and populates its fields. This object gets # used by the Chef Server to generate a fully compiled recipe list for a node. # @@ -76,6 +79,7 @@ class Chef @loaded_recipes = {} @loaded_attributes = {} @events = events + @reboot_info = {} @node.run_context = self @@ -271,6 +275,27 @@ ERROR_MESSAGE end end + # there are options for how to handle multiple calls to these functions: + # 1. first call always wins (never change @reboot_info once set). + # 2. last call always wins (happily change @reboot_info whenever). + # 3. raise an exception on the first conflict. + # 4. disable reboot after this run if anyone ever calls :cancel. + # 5. raise an exception on any second call. + # 6. ? + def request_reboot(reboot_info) + Chef::Log::info "Changing reboot status from #{@reboot_info.inspect} to #{reboot_info.inspect}" + @reboot_info = reboot_info + end + + def cancel_reboot + Chef::Log::info "Changing reboot status from #{@reboot_info.inspect} to {}" + @reboot_info = {} + end + + def reboot_requested? + @reboot_info.size > 0 + end + private def loaded_recipe(cookbook, recipe) diff --git a/lib/chef/win32/api/file.rb b/lib/chef/win32/api/file.rb index 7a8dafd8b5..da9713e119 100644 --- a/lib/chef/win32/api/file.rb +++ b/lib/chef/win32/api/file.rb @@ -459,11 +459,7 @@ BOOL WINAPI DeviceIoControl( # to be passed to the *W vesion of WinAPI File # functions def encode_path(path) - (path_prepender << path.gsub(::File::SEPARATOR, ::File::ALT_SEPARATOR)).to_wstring - end - - def path_prepender - "\\\\?\\" + Chef::Util::PathHelper.canonical_path(path).to_wstring end # retrieves a file search handle and passes it |