summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorAbhishekKr <abhikumar163@gmail.com>2016-09-10 02:28:30 +0530
committerAbhishekKr <abhikumar163@gmail.com>2016-09-10 02:28:30 +0530
commit5c01c0f74941d4f788e254ae4d040c0e4a2a477d (patch)
tree8cf25328d577db77d191d88bdc85277629553f3e /lib
parentc3c6cfc156d0a0bfe7c7dd4f273a2c2bdc4b0281 (diff)
parent3731bff0641d0cb12780bc52376e50d9a0a71644 (diff)
downloadchef-5c01c0f74941d4f788e254ae4d040c0e4a2a477d.tar.gz
Merge branch 'master' of https://github.com/chef/chef
Diffstat (limited to 'lib')
-rw-r--r--lib/chef/application.rb27
-rw-r--r--lib/chef/application/client.rb16
-rw-r--r--lib/chef/application/knife.rb8
-rw-r--r--lib/chef/application/solo.rb12
-rw-r--r--lib/chef/audit/audit_reporter.rb6
-rw-r--r--lib/chef/chef_fs/chef_fs_data_store.rb1
-rw-r--r--lib/chef/chef_fs/command_line.rb70
-rw-r--r--lib/chef/chef_fs/data_handler/data_handler_base.rb4
-rw-r--r--lib/chef/chef_fs/file_pattern.rb2
-rw-r--r--lib/chef/chef_fs/file_system.rb276
-rw-r--r--lib/chef/chef_fs/file_system/repository/acls_dir.rb6
-rw-r--r--lib/chef/chef_fs/file_system/repository/base_file.rb3
-rw-r--r--lib/chef/chef_fs/file_system/repository/chef_repository_file_system_cookbook_entry.rb1
-rw-r--r--lib/chef/chef_fs/file_system/repository/directory.rb7
-rw-r--r--lib/chef/chef_fs/file_system_cache.rb18
-rw-r--r--lib/chef/chef_fs/parallelizer/parallel_enumerable.rb8
-rw-r--r--lib/chef/cookbook/cookbook_version_loader.rb49
-rw-r--r--lib/chef/cookbook/metadata.rb2
-rw-r--r--lib/chef/cookbook/synchronizer.rb6
-rw-r--r--lib/chef/cookbook_site_streaming_uploader.rb6
-rw-r--r--lib/chef/cookbook_uploader.rb2
-rw-r--r--lib/chef/cookbook_version.rb12
-rw-r--r--lib/chef/dsl/powershell.rb2
-rw-r--r--lib/chef/event_dispatch/base.rb4
-rw-r--r--lib/chef/exceptions.rb2
-rw-r--r--lib/chef/file_access_control/windows.rb6
-rw-r--r--lib/chef/file_cache.rb2
-rw-r--r--lib/chef/formatters/base.rb4
-rw-r--r--lib/chef/formatters/doc.rb4
-rw-r--r--lib/chef/http.rb66
-rw-r--r--lib/chef/http/auth_credentials.rb2
-rw-r--r--lib/chef/http/basic_client.rb13
-rw-r--r--lib/chef/http/socketless_chef_zero_client.rb4
-rw-r--r--lib/chef/key.rb111
-rw-r--r--lib/chef/knife.rb131
-rw-r--r--lib/chef/knife/bootstrap.rb8
-rw-r--r--lib/chef/knife/client_delete.rb4
-rw-r--r--lib/chef/knife/cookbook_bulk_delete.rb2
-rw-r--r--lib/chef/knife/cookbook_show.rb2
-rw-r--r--lib/chef/knife/core/bootstrap_context.rb10
-rw-r--r--lib/chef/knife/core/gem_glob_loader.rb6
-rw-r--r--lib/chef/knife/search.rb4
-rw-r--r--lib/chef/knife/ssh.rb40
-rw-r--r--lib/chef/knife/status.rb4
-rw-r--r--lib/chef/mixin/command/unix.rb4
-rw-r--r--lib/chef/mixin/powershell_type_coercions.rb2
-rw-r--r--lib/chef/mixin/properties.rb3
-rw-r--r--lib/chef/mixin/securable.rb4
-rw-r--r--lib/chef/mixin/shell_out.rb30
-rw-r--r--lib/chef/mixin/uris.rb3
-rw-r--r--lib/chef/mixin/windows_architecture_helper.rb7
-rw-r--r--lib/chef/monkey_patches/webrick-utils.rb4
-rw-r--r--lib/chef/monologger.rb2
-rw-r--r--lib/chef/node.rb4
-rw-r--r--lib/chef/node/attribute.rb6
-rw-r--r--lib/chef/platform/provider_mapping.rb7
-rw-r--r--lib/chef/property.rb17
-rw-r--r--lib/chef/provider/apt_repository.rb12
-rw-r--r--lib/chef/provider/apt_update.rb13
-rw-r--r--lib/chef/provider/cron.rb5
-rw-r--r--lib/chef/provider/dsc_script.rb8
-rw-r--r--lib/chef/provider/file.rb8
-rw-r--r--lib/chef/provider/group/usermod.rb2
-rw-r--r--lib/chef/provider/link.rb13
-rw-r--r--lib/chef/provider/osx_profile.rb20
-rw-r--r--lib/chef/provider/package.rb14
-rw-r--r--lib/chef/provider/package/rubygems.rb33
-rw-r--r--lib/chef/provider/package/windows.rb2
-rw-r--r--lib/chef/provider/package/windows/exe.rb2
-rw-r--r--lib/chef/provider/package/windows/registry_uninstall_entry.rb2
-rw-r--r--lib/chef/provider/package/yum/rpm_utils.rb16
-rw-r--r--lib/chef/provider/package/yum/yum_cache.rb2
-rw-r--r--lib/chef/provider/remote_file/ftp.rb4
-rw-r--r--lib/chef/provider/remote_file/sftp.rb4
-rw-r--r--lib/chef/provider/service/debian.rb4
-rw-r--r--lib/chef/provider/service/simple.rb7
-rw-r--r--lib/chef/provider/service/solaris.rb2
-rw-r--r--lib/chef/provider/service/systemd.rb4
-rw-r--r--lib/chef/provider/service/upstart.rb13
-rw-r--r--lib/chef/provider/support/yum_repo.erb125
-rw-r--r--lib/chef/provider/systemd_unit.rb13
-rw-r--r--lib/chef/provider/template_finder.rb2
-rw-r--r--lib/chef/provider/user.rb36
-rw-r--r--lib/chef/provider/user/aix.rb7
-rw-r--r--lib/chef/provider/user/dscl.rb1
-rw-r--r--lib/chef/provider/user/linux.rb128
-rw-r--r--lib/chef/provider/user/pw.rb3
-rw-r--r--lib/chef/provider/user/solaris.rb5
-rw-r--r--lib/chef/provider/user/useradd.rb9
-rw-r--r--lib/chef/provider/user/windows.rb2
-rw-r--r--lib/chef/provider/windows_script.rb7
-rw-r--r--lib/chef/provider/yum_repository.rb121
-rw-r--r--lib/chef/providers.rb6
-rw-r--r--lib/chef/recipe.rb9
-rw-r--r--lib/chef/resource.rb16
-rw-r--r--lib/chef/resource/conditional.rb10
-rw-r--r--lib/chef/resource/freebsd_package.rb2
-rw-r--r--lib/chef/resource/launchd.rb2
-rw-r--r--lib/chef/resource/user.rb6
-rw-r--r--lib/chef/resource/user/aix_user.rb31
-rw-r--r--lib/chef/resource/user/dscl_user.rb31
-rw-r--r--lib/chef/resource/user/linux_user.rb51
-rw-r--r--lib/chef/resource/user/pw_user.rb31
-rw-r--r--lib/chef/resource/user/solaris_user.rb31
-rw-r--r--lib/chef/resource/user/windows_user.rb31
-rw-r--r--lib/chef/resource/yum_package.rb25
-rw-r--r--lib/chef/resource/yum_repository.rb76
-rw-r--r--lib/chef/resource_builder.rb2
-rw-r--r--lib/chef/resource_collection/stepable_iterator.rb4
-rw-r--r--lib/chef/resource_reporter.rb10
-rw-r--r--lib/chef/resources.rb7
-rw-r--r--lib/chef/run_context.rb8
-rw-r--r--lib/chef/run_context/cookbook_compiler.rb5
-rw-r--r--lib/chef/run_list.rb4
-rw-r--r--lib/chef/search/query.rb19
-rw-r--r--lib/chef/shell/ext.rb4
-rw-r--r--lib/chef/shell/shell_session.rb2
-rw-r--r--lib/chef/util/dsc/configuration_generator.rb2
-rw-r--r--lib/chef/util/powershell/cmdlet.rb7
-rw-r--r--lib/chef/util/selinux.rb2
-rw-r--r--lib/chef/version.rb2
-rw-r--r--lib/chef/version_class.rb11
-rw-r--r--lib/chef/version_constraint.rb4
-rw-r--r--lib/chef/win32/api/error.rb4
-rw-r--r--lib/chef/win32/api/net.rb2
-rw-r--r--lib/chef/win32/eventlog.rb2
-rw-r--r--lib/chef/win32/file.rb8
-rw-r--r--lib/chef/win32/net.rb2
-rw-r--r--lib/chef/win32/security/sid.rb2
129 files changed, 1537 insertions, 649 deletions
diff --git a/lib/chef/application.rb b/lib/chef/application.rb
index 6c2fc8b11b..f9735a3769 100644
--- a/lib/chef/application.rb
+++ b/lib/chef/application.rb
@@ -28,10 +28,7 @@ require "mixlib/cli"
require "tmpdir"
require "rbconfig"
require "chef/application/exit_code"
-require "resolv"
-# on linux, we replace the glibc resolver with the ruby resolv library, which
-# supports reloading.
-require "resolv-replace" if RbConfig::CONFIG["host_os"] =~ /linux/
+require "yaml"
class Chef
class Application
@@ -112,7 +109,22 @@ class Chef
config_content = config_fetcher.read_config
apply_config(config_content, config[:config_file])
end
+ extra_config_options = config.delete(:config_option)
Chef::Config.merge!(config)
+ if extra_config_options
+ extra_parsed_options = extra_config_options.inject({}) do |memo, option|
+ # Sanity check value.
+ Chef::Application.fatal!("Unparsable config option #{option.inspect}") if option.empty? || !option.include?("=")
+ # 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)
+ memo
+ end
+ Chef::Config.merge!(extra_parsed_options)
+ end
end
def set_specific_recipes
@@ -336,6 +348,13 @@ class Chef
class << self
def debug_stacktrace(e)
message = "#{e.class}: #{e}\n#{e.backtrace.join("\n")}"
+
+ cause = e.cause if e.respond_to?(:cause)
+ while cause != nil
+ message << "\n\n>>>> Caused by #{cause.class}: #{cause}\n#{cause.backtrace.join("\n")}"
+ cause = cause.respond_to?(:cause) ? cause.cause : nil
+ end
+
chef_stacktrace_out = "Generated at #{Time.now}\n"
chef_stacktrace_out += message
diff --git a/lib/chef/application/client.rb b/lib/chef/application/client.rb
index 2a2f70c3a1..cbaa494b71 100644
--- a/lib/chef/application/client.rb
+++ b/lib/chef/application/client.rb
@@ -41,6 +41,14 @@ class Chef::Application::Client < Chef::Application
:long => "--config CONFIG",
:description => "The configuration file to use"
+ option :config_option,
+ :long => "--config-option OPTION=VALUE",
+ :description => "Override a single configuration option",
+ :proc => lambda { |option, existing|
+ (existing ||= []) << option
+ existing
+ }
+
option :formatter,
:short => "-F FORMATTER",
:long => "--format FORMATTER",
@@ -196,9 +204,9 @@ class Chef::Application::Client < Chef::Application
:description => "Replace current run list with specified items for a single run",
:proc => lambda {|items|
items = items.split(",")
- items.compact.map {|item|
+ items.compact.map do |item|
Chef::RunList::RunListItem.new(item)
- }
+ end
}
option :runlist,
@@ -207,9 +215,9 @@ class Chef::Application::Client < Chef::Application
:description => "Permanently replace current run list with specified items",
:proc => lambda {|items|
items = items.split(",")
- items.compact.map {|item|
+ items.compact.map do |item|
Chef::RunList::RunListItem.new(item)
- }
+ end
}
option :why_run,
:short => "-W",
diff --git a/lib/chef/application/knife.rb b/lib/chef/application/knife.rb
index 34598574dd..c80d0245f1 100644
--- a/lib/chef/application/knife.rb
+++ b/lib/chef/application/knife.rb
@@ -33,6 +33,14 @@ class Chef::Application::Knife < Chef::Application
:description => "The configuration file to use",
:proc => lambda { |path| File.expand_path(path, Dir.pwd) }
+ option :config_option,
+ :long => "--config-option OPTION=VALUE",
+ :description => "Override a single configuration option",
+ :proc => lambda { |option, existing|
+ (existing ||= []) << option
+ existing
+ }
+
verbosity_level = 0
option :verbosity,
:short => "-V",
diff --git a/lib/chef/application/solo.rb b/lib/chef/application/solo.rb
index a7c4038f4c..446a0f007d 100644
--- a/lib/chef/application/solo.rb
+++ b/lib/chef/application/solo.rb
@@ -41,6 +41,14 @@ class Chef::Application::Solo < Chef::Application
:default => Chef::Config.platform_specific_path("/etc/chef/solo.rb"),
:description => "The configuration file to use"
+ option :config_option,
+ :long => "--config-option OPTION=VALUE",
+ :description => "Override a single configuration option",
+ :proc => lambda { |option, existing|
+ (existing ||= []) << option
+ existing
+ }
+
option :formatter,
:short => "-F FORMATTER",
:long => "--format FORMATTER",
@@ -160,9 +168,9 @@ class Chef::Application::Solo < Chef::Application
:description => "Replace current run list with specified items",
:proc => lambda {|items|
items = items.split(",")
- items.compact.map {|item|
+ items.compact.map do |item|
Chef::RunList::RunListItem.new(item)
- }
+ end
}
option :client_fork,
diff --git a/lib/chef/audit/audit_reporter.rb b/lib/chef/audit/audit_reporter.rb
index a40cae93dd..8546a21bb4 100644
--- a/lib/chef/audit/audit_reporter.rb
+++ b/lib/chef/audit/audit_reporter.rb
@@ -140,7 +140,11 @@ class Chef
# Save the audit report to local disk
error_file = "failed-audit-data.json"
Chef::FileCache.store(error_file, Chef::JSONCompat.to_json_pretty(run_data), 0640)
- Chef::Log.error("Failed to post audit report to server. Saving report to #{Chef::FileCache.load(error_file, false)}")
+ if Chef::Config.chef_zero.enabled
+ Chef::Log.debug("Saving audit report to #{Chef::FileCache.load(error_file, false)}")
+ else
+ Chef::Log.error("Failed to post audit report to server. Saving report to #{Chef::FileCache.load(error_file, false)}")
+ end
end
else
Chef::Log.error("Failed to post audit report to server (#{e})")
diff --git a/lib/chef/chef_fs/chef_fs_data_store.rb b/lib/chef/chef_fs/chef_fs_data_store.rb
index aa5a6d5a69..6b3e830f8d 100644
--- a/lib/chef/chef_fs/chef_fs_data_store.rb
+++ b/lib/chef/chef_fs/chef_fs_data_store.rb
@@ -458,6 +458,7 @@ class Chef
# We want to delete just the ones that == POLICY
next unless policy.name.rpartition("-")[0] == path[1]
policy.delete(false)
+ FileSystemCache.instance.delete!(policy.file_path)
found_policy = true
end
raise ChefZero::DataStore::DataNotFoundError.new(path) if !found_policy
diff --git a/lib/chef/chef_fs/command_line.rb b/lib/chef/chef_fs/command_line.rb
index c824bc90df..2d887f4780 100644
--- a/lib/chef/chef_fs/command_line.rb
+++ b/lib/chef/chef_fs/command_line.rb
@@ -242,48 +242,50 @@ class Chef
return [ [ :error, old_entry, new_entry, nil, nil, e ] ]
end
- private
+ class << self
+ private
- def self.sort_keys(json_object)
- if json_object.is_a?(Array)
- json_object.map { |o| sort_keys(o) }
- elsif json_object.is_a?(Hash)
- new_hash = {}
- json_object.keys.sort.each { |key| new_hash[key] = sort_keys(json_object[key]) }
- new_hash
- else
- json_object
+ def sort_keys(json_object)
+ if json_object.is_a?(Array)
+ json_object.map { |o| sort_keys(o) }
+ elsif json_object.is_a?(Hash)
+ new_hash = {}
+ json_object.keys.sort.each { |key| new_hash[key] = sort_keys(json_object[key]) }
+ new_hash
+ else
+ json_object
+ end
end
- end
- def self.canonicalize_json(json_text)
- parsed_json = Chef::JSONCompat.parse(json_text)
- sorted_json = sort_keys(parsed_json)
- Chef::JSONCompat.to_json_pretty(sorted_json)
- end
-
- def self.diff_text(old_path, new_path, old_value, new_value)
- # Copy to tempfiles before diffing
- # TODO don't copy things that are already in files! Or find an in-memory diff algorithm
- begin
- new_tempfile = Tempfile.new("new")
- new_tempfile.write(new_value)
- new_tempfile.close
+ def canonicalize_json(json_text)
+ parsed_json = Chef::JSONCompat.parse(json_text)
+ sorted_json = sort_keys(parsed_json)
+ Chef::JSONCompat.to_json_pretty(sorted_json)
+ end
+ def diff_text(old_path, new_path, old_value, new_value)
+ # Copy to tempfiles before diffing
+ # TODO don't copy things that are already in files! Or find an in-memory diff algorithm
begin
- old_tempfile = Tempfile.new("old")
- old_tempfile.write(old_value)
- old_tempfile.close
+ new_tempfile = Tempfile.new("new")
+ new_tempfile.write(new_value)
+ new_tempfile.close
- result = Chef::Util::Diff.new.udiff(old_tempfile.path, new_tempfile.path)
- result = result.gsub(/^--- #{old_tempfile.path}/, "--- #{old_path}")
- result = result.gsub(/^\+\+\+ #{new_tempfile.path}/, "+++ #{new_path}")
- result
+ begin
+ old_tempfile = Tempfile.new("old")
+ old_tempfile.write(old_value)
+ old_tempfile.close
+
+ result = Chef::Util::Diff.new.udiff(old_tempfile.path, new_tempfile.path)
+ result = result.gsub(/^--- #{old_tempfile.path}/, "--- #{old_path}")
+ result = result.gsub(/^\+\+\+ #{new_tempfile.path}/, "+++ #{new_path}")
+ result
+ ensure
+ old_tempfile.close!
+ end
ensure
- old_tempfile.close!
+ new_tempfile.close!
end
- ensure
- new_tempfile.close!
end
end
end
diff --git a/lib/chef/chef_fs/data_handler/data_handler_base.rb b/lib/chef/chef_fs/data_handler/data_handler_base.rb
index b34aff4b98..3668f77dd5 100644
--- a/lib/chef/chef_fs/data_handler/data_handler_base.rb
+++ b/lib/chef/chef_fs/data_handler/data_handler_base.rb
@@ -93,7 +93,7 @@ class Chef
# name to recipe[name]. Then calls uniq on the result.
#
def normalize_run_list(run_list)
- run_list.map {|item|
+ run_list.map do |item|
case item.to_s
when /^recipe\[.*\]$/
item # explicit recipe
@@ -102,7 +102,7 @@ class Chef
else
"recipe[#{item}]"
end
- }.uniq
+ end.uniq
end
#
diff --git a/lib/chef/chef_fs/file_pattern.rb b/lib/chef/chef_fs/file_pattern.rb
index a308a0fe2c..9c12bd4b96 100644
--- a/lib/chef/chef_fs/file_pattern.rb
+++ b/lib/chef/chef_fs/file_pattern.rb
@@ -160,7 +160,7 @@ class Chef
pattern
end
- private
+ private
def regexp
calculate
diff --git a/lib/chef/chef_fs/file_system.rb b/lib/chef/chef_fs/file_system.rb
index 69dce54f00..1a8da2fd6b 100644
--- a/lib/chef/chef_fs/file_system.rb
+++ b/lib/chef/chef_fs/file_system.rb
@@ -68,7 +68,7 @@ class Chef
list_from(exact_child, &block)
end
- # Otherwise, go through all children and find any matches
+ # Otherwise, go through all children and find any matches
elsif entry.dir?
results = Parallelizer.parallelize(entry.children) { |child| Chef::ChefFS::FileSystem.list(child, pattern) }
results.flatten(1).each(&block)
@@ -257,172 +257,174 @@ class Chef
[ are_same, a_value, b_value ]
end
- private
-
- # Copy two entries (could be files or dirs)
- def self.copy_entries(src_entry, dest_entry, new_dest_parent, recurse_depth, options, ui, format_path)
- # A NOTE about this algorithm:
- # There are cases where this algorithm does too many network requests.
- # knife upload with a specific filename will first check if the file
- # exists (a "dir" in the parent) before deciding whether to POST or
- # PUT it. If we just tried PUT (or POST) and then tried the other if
- # the conflict failed, we wouldn't need to check existence.
- # On the other hand, we may already have DONE the request, in which
- # case we shouldn't waste time trying PUT if we know the file doesn't
- # exist.
- # Will need to decide how that works with checksums, though.
- error = false
- begin
- dest_path = format_path.call(dest_entry) if ui
- src_path = format_path.call(src_entry) if ui
- if !src_entry.exists?
- if options[:purge]
- # If we would not have uploaded it, we will not purge it.
- if src_entry.parent.can_have_child?(dest_entry.name, dest_entry.dir?)
- if options[:dry_run]
- ui.output "Would delete #{dest_path}" if ui
- else
- begin
- dest_entry.delete(true)
- ui.output "Deleted extra entry #{dest_path} (purge is on)" if ui
- rescue Chef::ChefFS::FileSystem::NotFoundError
- ui.output "Entry #{dest_path} does not exist. Nothing to do. (purge is on)" if ui
+ class << self
+ private
+
+ # Copy two entries (could be files or dirs)
+ def copy_entries(src_entry, dest_entry, new_dest_parent, recurse_depth, options, ui, format_path)
+ # A NOTE about this algorithm:
+ # There are cases where this algorithm does too many network requests.
+ # knife upload with a specific filename will first check if the file
+ # exists (a "dir" in the parent) before deciding whether to POST or
+ # PUT it. If we just tried PUT (or POST) and then tried the other if
+ # the conflict failed, we wouldn't need to check existence.
+ # On the other hand, we may already have DONE the request, in which
+ # case we shouldn't waste time trying PUT if we know the file doesn't
+ # exist.
+ # Will need to decide how that works with checksums, though.
+ error = false
+ begin
+ dest_path = format_path.call(dest_entry) if ui
+ src_path = format_path.call(src_entry) if ui
+ if !src_entry.exists?
+ if options[:purge]
+ # If we would not have uploaded it, we will not purge it.
+ if src_entry.parent.can_have_child?(dest_entry.name, dest_entry.dir?)
+ if options[:dry_run]
+ ui.output "Would delete #{dest_path}" if ui
+ else
+ begin
+ dest_entry.delete(true)
+ ui.output "Deleted extra entry #{dest_path} (purge is on)" if ui
+ rescue Chef::ChefFS::FileSystem::NotFoundError
+ ui.output "Entry #{dest_path} does not exist. Nothing to do. (purge is on)" if ui
+ end
end
- end
- else
- ui.output ("Not deleting extra entry #{dest_path} (purge is off)") if ui
- end
- end
-
- elsif !dest_entry.exists?
- if new_dest_parent.can_have_child?(src_entry.name, src_entry.dir?)
- # If the entry can do a copy directly from filesystem, do that.
- if new_dest_parent.respond_to?(:create_child_from)
- if options[:dry_run]
- ui.output "Would create #{dest_path}" if ui
else
- new_dest_parent.create_child_from(src_entry)
- ui.output "Created #{dest_path}" if ui
+ ui.output ("Not deleting extra entry #{dest_path} (purge is off)") if ui
end
- return
end
- if src_entry.dir?
- if options[:dry_run]
- ui.output "Would create #{dest_path}" if ui
- new_dest_dir = new_dest_parent.child(src_entry.name)
- else
- new_dest_dir = new_dest_parent.create_child(src_entry.name, nil)
- ui.output "Created #{dest_path}" if ui
- end
- # Directory creation is recursive.
- if recurse_depth != 0
- parallel_do(src_entry.children) do |src_child|
- new_dest_child = new_dest_dir.child(src_child.name)
- child_error = copy_entries(src_child, new_dest_child, new_dest_dir, recurse_depth ? recurse_depth - 1 : recurse_depth, options, ui, format_path)
- error ||= child_error
+ elsif !dest_entry.exists?
+ if new_dest_parent.can_have_child?(src_entry.name, src_entry.dir?)
+ # If the entry can do a copy directly from filesystem, do that.
+ if new_dest_parent.respond_to?(:create_child_from)
+ if options[:dry_run]
+ ui.output "Would create #{dest_path}" if ui
+ else
+ new_dest_parent.create_child_from(src_entry)
+ ui.output "Created #{dest_path}" if ui
end
+ return
end
- else
- if options[:dry_run]
- ui.output "Would create #{dest_path}" if ui
- else
- child = new_dest_parent.create_child(src_entry.name, src_entry.read)
- ui.output "Created #{format_path.call(child)}" if ui
- end
- end
- end
-
- else
- # Both exist.
- # If the entry can do a copy directly, do that.
- if dest_entry.respond_to?(:copy_from)
- if options[:force] || compare(src_entry, dest_entry)[0] == false
- if options[:dry_run]
- ui.output "Would update #{dest_path}" if ui
+ if src_entry.dir?
+ if options[:dry_run]
+ ui.output "Would create #{dest_path}" if ui
+ new_dest_dir = new_dest_parent.child(src_entry.name)
+ else
+ new_dest_dir = new_dest_parent.create_child(src_entry.name, nil)
+ ui.output "Created #{dest_path}" if ui
+ end
+ # Directory creation is recursive.
+ if recurse_depth != 0
+ parallel_do(src_entry.children) do |src_child|
+ new_dest_child = new_dest_dir.child(src_child.name)
+ child_error = copy_entries(src_child, new_dest_child, new_dest_dir, recurse_depth ? recurse_depth - 1 : recurse_depth, options, ui, format_path)
+ error ||= child_error
+ end
+ end
else
- dest_entry.copy_from(src_entry, options)
- ui.output "Updated #{dest_path}" if ui
+ if options[:dry_run]
+ ui.output "Would create #{dest_path}" if ui
+ else
+ child = new_dest_parent.create_child(src_entry.name, src_entry.read)
+ ui.output "Created #{format_path.call(child)}" if ui
+ end
end
end
- return
- end
- # If they are different types, log an error.
- if src_entry.dir?
- if dest_entry.dir?
- # If both are directories, recurse into their children
- if recurse_depth != 0
- parallel_do(child_pairs(src_entry, dest_entry)) do |src_child, dest_child|
- child_error = copy_entries(src_child, dest_child, dest_entry, recurse_depth ? recurse_depth - 1 : recurse_depth, options, ui, format_path)
- error ||= child_error
+ else
+ # Both exist.
+
+ # If the entry can do a copy directly, do that.
+ if dest_entry.respond_to?(:copy_from)
+ if options[:force] || compare(src_entry, dest_entry)[0] == false
+ if options[:dry_run]
+ ui.output "Would update #{dest_path}" if ui
+ else
+ dest_entry.copy_from(src_entry, options)
+ ui.output "Updated #{dest_path}" if ui
end
end
- else
- # If they are different types.
- ui.error("File #{src_path} is a directory while file #{dest_path} is a regular file\n") if ui
return
end
- else
- if dest_entry.dir?
- ui.error("File #{src_path} is a regular file while file #{dest_path} is a directory\n") if ui
- return
- else
- # Both are files! Copy them unless we're sure they are the same.'
- if options[:diff] == false
- should_copy = false
- elsif options[:force]
- should_copy = true
- src_value = nil
+ # If they are different types, log an error.
+ if src_entry.dir?
+ if dest_entry.dir?
+ # If both are directories, recurse into their children
+ if recurse_depth != 0
+ parallel_do(child_pairs(src_entry, dest_entry)) do |src_child, dest_child|
+ child_error = copy_entries(src_child, dest_child, dest_entry, recurse_depth ? recurse_depth - 1 : recurse_depth, options, ui, format_path)
+ error ||= child_error
+ end
+ end
else
- are_same, src_value, _dest_value = compare(src_entry, dest_entry)
- should_copy = !are_same
+ # If they are different types.
+ ui.error("File #{src_path} is a directory while file #{dest_path} is a regular file\n") if ui
+ return
end
- if should_copy
- if options[:dry_run]
- ui.output "Would update #{dest_path}" if ui
+ else
+ if dest_entry.dir?
+ ui.error("File #{src_path} is a regular file while file #{dest_path} is a directory\n") if ui
+ return
+ else
+
+ # Both are files! Copy them unless we're sure they are the same.'
+ if options[:diff] == false
+ should_copy = false
+ elsif options[:force]
+ should_copy = true
+ src_value = nil
else
- src_value = src_entry.read if src_value.nil?
- dest_entry.write(src_value)
- ui.output "Updated #{dest_path}" if ui
+ are_same, src_value, _dest_value = compare(src_entry, dest_entry)
+ should_copy = !are_same
+ end
+ if should_copy
+ if options[:dry_run]
+ ui.output "Would update #{dest_path}" if ui
+ else
+ src_value = src_entry.read if src_value.nil?
+ dest_entry.write(src_value)
+ ui.output "Updated #{dest_path}" if ui
+ end
end
end
end
end
+ rescue RubyFileError => e
+ ui.warn "#{format_path.call(e.entry)} #{e.reason}." if ui
+ rescue DefaultEnvironmentCannotBeModifiedError => e
+ ui.warn "#{format_path.call(e.entry)} #{e.reason}." if ui
+ rescue OperationFailedError => e
+ ui.error "#{format_path.call(e.entry)} failed to #{e.operation}: #{e.message}" if ui
+ error = true
+ rescue OperationNotAllowedError => e
+ ui.error "#{format_path.call(e.entry)} #{e.reason}." if ui
+ error = true
end
- rescue RubyFileError => e
- ui.warn "#{format_path.call(e.entry)} #{e.reason}." if ui
- rescue DefaultEnvironmentCannotBeModifiedError => e
- ui.warn "#{format_path.call(e.entry)} #{e.reason}." if ui
- rescue OperationFailedError => e
- ui.error "#{format_path.call(e.entry)} failed to #{e.operation}: #{e.message}" if ui
- error = true
- rescue OperationNotAllowedError => e
- ui.error "#{format_path.call(e.entry)} #{e.reason}." if ui
- error = true
+ error
end
- error
- end
- def self.get_or_create_parent(entry, options, ui, format_path)
- parent = entry.parent
- if parent && !parent.exists?
- parent_path = format_path.call(parent) if ui
- parent_parent = get_or_create_parent(parent, options, ui, format_path)
- if options[:dry_run]
- ui.output "Would create #{parent_path}" if ui
- else
- parent = parent_parent.create_child(parent.name, nil)
- ui.output "Created #{parent_path}" if ui
+ def get_or_create_parent(entry, options, ui, format_path)
+ parent = entry.parent
+ if parent && !parent.exists?
+ parent_path = format_path.call(parent) if ui
+ parent_parent = get_or_create_parent(parent, options, ui, format_path)
+ if options[:dry_run]
+ ui.output "Would create #{parent_path}" if ui
+ else
+ parent = parent_parent.create_child(parent.name, nil)
+ ui.output "Created #{parent_path}" if ui
+ end
end
+ return parent
end
- return parent
- end
- def self.parallel_do(enum, options = {}, &block)
- Chef::ChefFS::Parallelizer.parallel_do(enum, options, &block)
+ def parallel_do(enum, options = {}, &block)
+ Chef::ChefFS::Parallelizer.parallel_do(enum, options, &block)
+ end
end
end
end
diff --git a/lib/chef/chef_fs/file_system/repository/acls_dir.rb b/lib/chef/chef_fs/file_system/repository/acls_dir.rb
index 619031aa70..110befdf22 100644
--- a/lib/chef/chef_fs/file_system/repository/acls_dir.rb
+++ b/lib/chef/chef_fs/file_system/repository/acls_dir.rb
@@ -28,14 +28,16 @@ class Chef
module Repository
class AclsDir < Repository::Directory
+ BARE_FILES = %w{ organization.json root }
+
def can_have_child?(name, is_dir)
- is_dir ? Chef::ChefFS::FileSystem::ChefServer::AclsDir::ENTITY_TYPES.include?(name) : name == "organization.json"
+ is_dir ? Chef::ChefFS::FileSystem::ChefServer::AclsDir::ENTITY_TYPES.include?(name) : BARE_FILES.include?(name)
end
protected
def make_child_entry(child_name)
- if child_name == "organization.json"
+ if BARE_FILES.include? child_name
Acl.new(child_name, self)
else
AclsSubDir.new(child_name, self)
diff --git a/lib/chef/chef_fs/file_system/repository/base_file.rb b/lib/chef/chef_fs/file_system/repository/base_file.rb
index a768bcf971..3e1edc8d62 100644
--- a/lib/chef/chef_fs/file_system/repository/base_file.rb
+++ b/lib/chef/chef_fs/file_system/repository/base_file.rb
@@ -16,6 +16,8 @@
# limitations under the License.
#
+require "chef/chef_fs/file_system_cache"
+
class Chef
module ChefFS
module FileSystem
@@ -99,6 +101,7 @@ class Chef
end
def delete(_)
+ FileSystemCache.instance.delete!(file_path)
File.delete(file_path)
rescue Errno::ENOENT
raise Chef::ChefFS::FileSystem::NotFoundError.new(self, $!)
diff --git a/lib/chef/chef_fs/file_system/repository/chef_repository_file_system_cookbook_entry.rb b/lib/chef/chef_fs/file_system/repository/chef_repository_file_system_cookbook_entry.rb
index 9d1538e46e..4019c6985b 100644
--- a/lib/chef/chef_fs/file_system/repository/chef_repository_file_system_cookbook_entry.rb
+++ b/lib/chef/chef_fs/file_system/repository/chef_repository_file_system_cookbook_entry.rb
@@ -120,6 +120,7 @@ class Chef
end
def delete(recurse)
+ FileSystemCache.instance.delete!(file_path)
begin
if dir?
if !recurse
diff --git a/lib/chef/chef_fs/file_system/repository/directory.rb b/lib/chef/chef_fs/file_system/repository/directory.rb
index 43f5719822..328cf92b03 100644
--- a/lib/chef/chef_fs/file_system/repository/directory.rb
+++ b/lib/chef/chef_fs/file_system/repository/directory.rb
@@ -84,6 +84,7 @@ class Chef
if child.exists?
raise Chef::ChefFS::FileSystem::AlreadyExistsError.new(:create_child, child)
end
+ FileSystemCache.instance.delete!(child.file_path)
if file_contents
child.write(file_contents)
else
@@ -122,6 +123,7 @@ class Chef
raise Chef::ChefFS::FileSystem::AlreadyExistsError.new(:create_child, self)
end
begin
+ FileSystemCache.instance.delete!(file_path)
Dir.mkdir(file_path)
rescue Errno::EEXIST
raise Chef::ChefFS::FileSystem::AlreadyExistsError.new(:create_child, self)
@@ -138,6 +140,7 @@ class Chef
raise MustDeleteRecursivelyError.new(self, $!)
end
FileUtils.rm_r(file_path)
+ FileSystemCache.instance.delete!(file_path)
else
raise Chef::ChefFS::FileSystem::NotFoundError.new(self, $!)
end
@@ -149,6 +152,10 @@ class Chef
protected
+ def write(data)
+ raise FileSystemError.new(self, nil, "attempted to write to a directory entry")
+ end
+
def make_child_entry(child_name)
raise "Not Implemented"
end
diff --git a/lib/chef/chef_fs/file_system_cache.rb b/lib/chef/chef_fs/file_system_cache.rb
index 38b4fda7ad..a9d8d8bfe4 100644
--- a/lib/chef/chef_fs/file_system_cache.rb
+++ b/lib/chef/chef_fs/file_system_cache.rb
@@ -49,6 +49,17 @@ class Chef
val
end
+ def delete!(path)
+ parent = _get_parent(path)
+ Chef::Log.debug("Deleting parent #{parent} and #{path} from FileSystemCache")
+ if @cache.key?(path)
+ @cache.delete(path)
+ end
+ if !parent.nil? && @cache.key?(parent)
+ @cache.delete(parent)
+ end
+ end
+
def fetch(path)
if @cache.key?(path)
@cache[path]
@@ -57,6 +68,13 @@ class Chef
end
end
+ private
+
+ def _get_parent(path)
+ parts = ChefFS::PathUtils.split(path)
+ return nil if parts.nil? || parts.length < 2
+ ChefFS::PathUtils.join(*parts[0..-2])
+ end
end
end
end
diff --git a/lib/chef/chef_fs/parallelizer/parallel_enumerable.rb b/lib/chef/chef_fs/parallelizer/parallel_enumerable.rb
index 9d02bbab78..ab578bdb7f 100644
--- a/lib/chef/chef_fs/parallelizer/parallel_enumerable.rb
+++ b/lib/chef/chef_fs/parallelizer/parallel_enumerable.rb
@@ -184,9 +184,7 @@ class Chef
sleep(0.01)
end
- until @unconsumed_output.empty?
- yield @unconsumed_output.pop
- end
+ yield @unconsumed_output.pop until @unconsumed_output.empty?
# If no one is working on our tasks and we're allowed to
# work on them in the main thread, process an input to
@@ -227,9 +225,7 @@ class Chef
def stop
@unconsumed_input.clear
- while @in_process.size > 0
- sleep(0.05)
- end
+ sleep(0.05) while @in_process.size > 0
@unconsumed_output.clear
end
diff --git a/lib/chef/cookbook/cookbook_version_loader.rb b/lib/chef/cookbook/cookbook_version_loader.rb
index d9b027f322..af8b2e043e 100644
--- a/lib/chef/cookbook/cookbook_version_loader.rb
+++ b/lib/chef/cookbook/cookbook_version_loader.rb
@@ -3,6 +3,7 @@ require "chef/cookbook_version"
require "chef/cookbook/chefignore"
require "chef/cookbook/metadata"
require "chef/util/path_helper"
+require "find"
class Chef
class Cookbook
@@ -168,7 +169,7 @@ class Chef
when /\.json$/
apply_json_metadata(metadata_file)
else
- raise RuntimeError, "Invalid metadata file: #{metadata_file} for cookbook: #{cookbook_version}"
+ raise "Invalid metadata file: #{metadata_file} for cookbook: #{cookbook_version}"
end
end
@@ -223,27 +224,31 @@ class Chef
# however if the file is named ".uploaded-cookbook-version.json" it is
# assumed to be managed by chef-zero and not part of the cookbook.
def load_all_files
- Dir.glob(File.join(Chef::Util::PathHelper.escape_glob_dir(cookbook_path), "*"), File::FNM_DOTMATCH).each do |fs_entry|
- if File.directory?(fs_entry)
- dir_relpath = Chef::Util::PathHelper.relative_path_from(@cookbook_path, fs_entry)
-
- next if dir_relpath.to_s.start_with?(".")
-
- Dir.glob(File.join(fs_entry, "**/*"), File::FNM_DOTMATCH).each do |file|
- next if File.directory?(file)
- file = Pathname.new(file).cleanpath.to_s
- name = Chef::Util::PathHelper.relative_path_from(@cookbook_path, file)
- cookbook_settings[:all_files][name] = file
- end
- elsif File.file?(fs_entry)
- file = Pathname.new(fs_entry).cleanpath.to_s
-
- next if File.basename(file) == UPLOADED_COOKBOOK_VERSION_FILE
-
- name = Chef::Util::PathHelper.relative_path_from(@cookbook_path, file)
- cookbook_settings[:all_files][name] = file
- else # pipes, devices, other weirdness
- next
+ return unless File.exist?(cookbook_path)
+
+ # If cookbook_path is a symlink, Find on Windows Ruby 2.3 will not traverse it.
+ # Dir.entries will do so on all platforms, so we iterate the top level using
+ # Dir.entries. Since we have different behavior at the top anyway (hidden
+ # directories at the top level are not included for backcompat), this
+ # actually keeps things a bit cleaner.
+ Dir.entries(cookbook_path).each do |top_filename|
+ # Skip top-level directories starting with "."
+ top_path = File.join(cookbook_path, top_filename)
+ next if File.directory?(top_path) && top_filename.start_with?(".")
+
+ # Use Find.find because it:
+ # (a) returns any children, recursively
+ # (b) includes top_path as well
+ # (c) skips symlinks, which is backcompat (no judgement on whether it was *right*)
+ Find.find(top_path) do |path|
+ # Only add files, not directories
+ next unless File.file?(path)
+ # Don't add .uploaded-cookbook-version.json
+ next if File.basename(path) == UPLOADED_COOKBOOK_VERSION_FILE
+
+ relative_path = Chef::Util::PathHelper.relative_path_from(cookbook_path, path)
+ path = Pathname.new(path).cleanpath.to_s
+ cookbook_settings[:all_files][relative_path] = path
end
end
end
diff --git a/lib/chef/cookbook/metadata.rb b/lib/chef/cookbook/metadata.rb
index 603f80748c..ab83da9e55 100644
--- a/lib/chef/cookbook/metadata.rb
+++ b/lib/chef/cookbook/metadata.rb
@@ -722,7 +722,7 @@ class Chef
end
end
- private
+ private
# Helper to match a gem style version (ohai_version/chef_version) against a set of
# Gem::Dependency version constraints. If none are present, it always matches. if
diff --git a/lib/chef/cookbook/synchronizer.rb b/lib/chef/cookbook/synchronizer.rb
index 1ee30bacc7..bb44bc3d5c 100644
--- a/lib/chef/cookbook/synchronizer.rb
+++ b/lib/chef/cookbook/synchronizer.rb
@@ -152,11 +152,11 @@ class Chef
queue << lambda do |lock|
full_file_path = sync_file(file)
- lock.synchronize {
+ lock.synchronize do
# Save the full_path of the downloaded file to be restored in the manifest later
save_full_file_path(file, full_file_path)
mark_file_synced(file)
- }
+ end
end
end
@@ -291,7 +291,7 @@ class Chef
end
def server_api
- Chef::ServerAPI.new(Chef::Config[:chef_server_url])
+ Thread.current[:server_api] ||= Chef::ServerAPI.new(Chef::Config[:chef_server_url], keepalives: true)
end
end
diff --git a/lib/chef/cookbook_site_streaming_uploader.rb b/lib/chef/cookbook_site_streaming_uploader.rb
index 9fb8d0d4bc..c0e85ff984 100644
--- a/lib/chef/cookbook_site_streaming_uploader.rb
+++ b/lib/chef/cookbook_site_streaming_uploader.rb
@@ -31,7 +31,7 @@ class Chef
# inspired by http://stanislavvitvitskiy.blogspot.com/2008/12/multipart-post-in-ruby.html
class CookbookSiteStreamingUploader
- DefaultHeaders = { "accept" => "application/json", "x-chef-version" => ::Chef::VERSION }
+ DefaultHeaders = { "accept" => "application/json", "x-chef-version" => ::Chef::VERSION } # rubocop:disable Style/ConstantName
class << self
@@ -149,11 +149,11 @@ class Chef
alias :to_s :body
# BUGBUG this makes the response compatible with what respsonse_steps expects to test headers (response.headers[] -> response[])
- def headers
+ def headers # rubocop:disable Lint/NestedMethodDefinition
self
end
- def status
+ def status # rubocop:disable Lint/NestedMethodDefinition
code.to_i
end
end
diff --git a/lib/chef/cookbook_uploader.rb b/lib/chef/cookbook_uploader.rb
index 95c27799ec..bb75234563 100644
--- a/lib/chef/cookbook_uploader.rb
+++ b/lib/chef/cookbook_uploader.rb
@@ -55,7 +55,7 @@ class Chef
checksum_files.merge!(cb.checksums)
end
- checksums = checksum_files.inject({}) { |memo, elt| memo[elt.first] = nil ; memo }
+ checksums = checksum_files.inject({}) { |memo, elt| memo[elt.first] = nil; memo }
new_sandbox = rest.post("sandboxes", { :checksums => checksums })
Chef::Log.info("Uploading files")
diff --git a/lib/chef/cookbook_version.rb b/lib/chef/cookbook_version.rb
index 1e903608b5..8de9cb26dd 100644
--- a/lib/chef/cookbook_version.rb
+++ b/lib/chef/cookbook_version.rb
@@ -316,13 +316,13 @@ class Chef
error_message << error_locations.join("\n")
existing_files = segment_filenames(segment)
# Strip the root_dir prefix off all files for readability
- pretty_existing_files = existing_files.map { |path|
+ pretty_existing_files = existing_files.map do |path|
if root_dir
path[root_dir.length + 1..-1]
else
path
end
- }
+ end
# Show the files that the cookbook does have. If the user made a typo,
# hopefully they'll see it here.
unless pretty_existing_files.empty?
@@ -599,12 +599,12 @@ class Chef
end
end
- def <=>(o)
- raise Chef::Exceptions::CookbookVersionNameMismatch if self.name != o.name
+ def <=>(other)
+ raise Chef::Exceptions::CookbookVersionNameMismatch if self.name != other.name
# FIXME: can we change the interface to the Metadata class such
# that metadata.version returns a Chef::Version instance instead
# of a string?
- Chef::Version.new(self.version) <=> Chef::Version.new(o.version)
+ Chef::Version.new(self.version) <=> Chef::Version.new(other.version)
end
private
@@ -623,7 +623,7 @@ class Chef
# For each filename, produce a mapping of base filename (i.e. recipe name
# or attribute file) to on disk location
def filenames_by_name(filenames)
- filenames.select { |filename| filename =~ /\.rb$/ }.inject({}) { |memo, filename| memo[File.basename(filename, ".rb")] = filename ; memo }
+ filenames.select { |filename| filename =~ /\.rb$/ }.inject({}) { |memo, filename| memo[File.basename(filename, ".rb")] = filename; memo }
end
def file_vendor
diff --git a/lib/chef/dsl/powershell.rb b/lib/chef/dsl/powershell.rb
index 1a900af6f6..7dc7a9a0f6 100644
--- a/lib/chef/dsl/powershell.rb
+++ b/lib/chef/dsl/powershell.rb
@@ -21,7 +21,7 @@ require "chef/util/powershell/ps_credential"
class Chef
module DSL
module Powershell
- def ps_credential(username = "placeholder", password)
+ def ps_credential(username = "placeholder", password) # rubocop:disable Style/OptionalArguments
Chef::Util::Powershell::PSCredential.new(username, password)
end
end
diff --git a/lib/chef/event_dispatch/base.rb b/lib/chef/event_dispatch/base.rb
index 6c6b2fa3bb..04c960c7af 100644
--- a/lib/chef/event_dispatch/base.rb
+++ b/lib/chef/event_dispatch/base.rb
@@ -232,11 +232,11 @@ class Chef
end
# Called after the recipe has been loaded
- def recipe_file_loaded(path)
+ def recipe_file_loaded(path, recipe)
end
# Called after a recipe file fails to load
- def recipe_file_load_failed(path, exception)
+ def recipe_file_load_failed(path, exception, recipe)
end
# Called when a recipe cannot be resolved
diff --git a/lib/chef/exceptions.rb b/lib/chef/exceptions.rb
index 43759568a7..a4d5ff60e2 100644
--- a/lib/chef/exceptions.rb
+++ b/lib/chef/exceptions.rb
@@ -184,7 +184,7 @@ class Chef
# A different version of a cookbook was added to a
# VersionedRecipeList than the one already there.
- class CookbookVersionConflict < ArgumentError ; end
+ class CookbookVersionConflict < ArgumentError; end
# does not follow X.Y.Z format. ArgumentError?
class InvalidPlatformVersion < ArgumentError; end
diff --git a/lib/chef/file_access_control/windows.rb b/lib/chef/file_access_control/windows.rb
index 6b7184bbd3..6f1ac5f581 100644
--- a/lib/chef/file_access_control/windows.rb
+++ b/lib/chef/file_access_control/windows.rb
@@ -128,7 +128,7 @@ class Chef
end
def should_update_dacl?
- return true unless ::File.exists?(file)
+ return true unless ::File.exists?(file) || ::File.symlink?(file)
dacl = target_dacl
existing_dacl = existing_descriptor.dacl
inherits = target_inherits
@@ -161,7 +161,7 @@ class Chef
end
def should_update_group?
- return true unless ::File.exists?(file)
+ return true unless ::File.exists?(file) || ::File.symlink?(file)
(group = target_group) && (group != existing_descriptor.group)
end
@@ -180,7 +180,7 @@ class Chef
end
def should_update_owner?
- return true unless ::File.exists?(file)
+ return true unless ::File.exists?(file) || ::File.symlink?(file)
(owner = target_owner) && (owner != existing_descriptor.owner)
end
diff --git a/lib/chef/file_cache.rb b/lib/chef/file_cache.rb
index cefc9da1eb..8e9bb1e3e4 100644
--- a/lib/chef/file_cache.rb
+++ b/lib/chef/file_cache.rb
@@ -85,7 +85,7 @@ class Chef
File.join(create_cache_path(File.join(file_path_array), true), file_name)
)
else
- raise RuntimeError, "Cannot move #{file} to #{path}!"
+ raise "Cannot move #{file} to #{path}!"
end
end
diff --git a/lib/chef/formatters/base.rb b/lib/chef/formatters/base.rb
index 3641e619e9..536bf72e02 100644
--- a/lib/chef/formatters/base.rb
+++ b/lib/chef/formatters/base.rb
@@ -203,12 +203,12 @@ class Chef
end
# Delegates to #file_loaded
- def recipe_file_loaded(path)
+ def recipe_file_loaded(path, recipe)
file_loaded(path)
end
# Delegates to #file_load_failed
- def recipe_file_load_failed(path, exception)
+ def recipe_file_load_failed(path, exception, recipe)
file_load_failed(path, exception)
end
diff --git a/lib/chef/formatters/doc.rb b/lib/chef/formatters/doc.rb
index d43f1993b2..7dbbf1d948 100644
--- a/lib/chef/formatters/doc.rb
+++ b/lib/chef/formatters/doc.rb
@@ -32,9 +32,9 @@ class Chef
def pretty_elapsed_time
time = elapsed_time
- if time < 60 then
+ if time < 60
message = Time.at(time).utc.strftime("%S seconds")
- elsif time < 3600 then
+ elsif time < 3600
message = Time.at(time).utc.strftime("%M minutes %S seconds")
else
message = Time.at(time).utc.strftime("%H hours %M minutes %S seconds")
diff --git a/lib/chef/http.rb b/lib/chef/http.rb
index 3e69f58383..924081bc6b 100644
--- a/lib/chef/http.rb
+++ b/lib/chef/http.rb
@@ -77,6 +77,9 @@ class Chef
attr_reader :middlewares
+ # [Boolean] if we're doing keepalives or not
+ attr_reader :keepalives
+
# Create a HTTP client object. The supplied +url+ is used as the base for
# all subsequent requests. For example, when initialized with a base url
# http://localhost:4000, a call to +get+ with 'nodes' will make an
@@ -87,6 +90,7 @@ class Chef
@sign_on_redirect = true
@redirects_followed = 0
@redirect_limit = 10
+ @keepalives = options[:keepalives] || false
@options = options
@middlewares = []
@@ -228,6 +232,33 @@ class Chef
def http_client(base_url = nil)
base_url ||= url
+ if keepalives && !base_url.nil?
+ # only reuse the http_client if we want keepalives and have a base_url
+ @http_client ||= {}
+ # the per-host per-port cache here gets peristent connections correct when
+ # redirecting to different servers
+ if base_url.is_a?(String) # sigh, this kind of abuse can't happen with strongly typed languages
+ @http_client[base_url] ||= build_http_client(base_url)
+ else
+ @http_client[base_url.host] ||= {}
+ @http_client[base_url.host][base_url.port] ||= build_http_client(base_url)
+ end
+ else
+ build_http_client(base_url)
+ end
+ end
+
+ # DEPRECATED: This is only kept around to provide access to cache control data in
+ # lib/chef/provider/remote_file/http.rb
+ # FIXME: Find a better API.
+ def last_response
+ @last_response
+ end
+
+ private
+
+ # @api private
+ def build_http_client(base_url)
if chef_zero_uri?(base_url)
# PERFORMANCE CRITICAL: *MUST* lazy require here otherwise we load up webrick
# via chef-zero and that hits DNS (at *require* time) which may timeout,
@@ -239,12 +270,11 @@ class Chef
SocketlessChefZeroClient.new(base_url)
else
- BasicClient.new(base_url, :ssl_policy => Chef::HTTP::APISSLPolicy)
+ BasicClient.new(base_url, ssl_policy: Chef::HTTP::APISSLPolicy, keepalives: keepalives)
end
end
- protected
-
+ # @api private
def create_url(path)
return path if path.is_a?(URI)
if path =~ /^(http|https|chefzero):\/\//i
@@ -259,6 +289,7 @@ class Chef
end
end
+ # @api private
def apply_request_middleware(method, url, headers, data)
middlewares.inject([method, url, headers, data]) do |req_data, middleware|
Chef::Log.debug("Chef::HTTP calling #{middleware.class}#handle_request")
@@ -266,6 +297,7 @@ class Chef
end
end
+ # @api private
def apply_response_middleware(response, rest_request, return_value)
middlewares.reverse.inject([response, rest_request, return_value]) do |res_data, middleware|
Chef::Log.debug("Chef::HTTP calling #{middleware.class}#handle_response")
@@ -273,6 +305,7 @@ class Chef
end
end
+ # @api private
def apply_stream_complete_middleware(response, rest_request, return_value)
middlewares.reverse.inject([response, rest_request, return_value]) do |res_data, middleware|
Chef::Log.debug("Chef::HTTP calling #{middleware.class}#handle_stream_complete")
@@ -280,6 +313,7 @@ class Chef
end
end
+ # @api private
def log_failed_request(response, return_value)
return_value ||= {}
error_message = "HTTP Request Returned #{response.code} #{response.message}: "
@@ -287,12 +321,14 @@ class Chef
Chef::Log.info(error_message)
end
+ # @api private
def success_response?(response)
response.kind_of?(Net::HTTPSuccess) || response.kind_of?(Net::HTTPRedirection)
end
# Runs a synchronous HTTP request, with no middleware applied (use #request
# to have the middleware applied). The entire response will be loaded into memory.
+ # @api private
def send_http_request(method, url, headers, body, &response_handler)
headers = build_headers(method, url, headers, body)
@@ -328,6 +364,7 @@ class Chef
# Wraps an HTTP request with retry logic.
# === Arguments
# url:: URL of the request, used for error messages
+ # @api private
def retrying_http_errors(url)
http_attempts = 0
begin
@@ -377,18 +414,22 @@ class Chef
end
end
+ # @api private
def http_retry_delay
config[:http_retry_delay]
end
+ # @api private
def http_retry_count
config[:http_retry_count]
end
+ # @api private
def config
Chef::Config
end
+ # @api private
def follow_redirect
raise Chef::Exceptions::RedirectLimitExceeded if @redirects_followed >= redirect_limit
@redirects_followed += 1
@@ -399,13 +440,13 @@ class Chef
@redirects_followed = 0
end
- private
-
+ # @api private
def chef_zero_uri?(uri)
uri = URI.parse(uri) unless uri.respond_to?(:scheme)
uri.scheme == "chefzero"
end
+ # @api private
def redirected_to(response)
return nil unless response.kind_of?(Net::HTTPRedirection)
# Net::HTTPNotModified is undesired subclass of Net::HTTPRedirection so test for this
@@ -413,6 +454,7 @@ class Chef
response["location"]
end
+ # @api private
def build_headers(method, url, headers = {}, json_body = false)
headers = @default_headers.merge(headers)
headers["Content-Length"] = json_body.bytesize.to_s if json_body
@@ -420,6 +462,7 @@ class Chef
headers
end
+ # @api private
def stream_to_tempfile(url, response, &progress_block)
content_length = response["Content-Length"]
tf = Tempfile.open("chef-rest")
@@ -443,18 +486,5 @@ class Chef
raise
end
- public
-
- ############################################################################
- # DEPRECATED
- ############################################################################
-
- # This is only kept around to provide access to cache control data in
- # lib/chef/provider/remote_file/http.rb
- # Find a better API.
- def last_response
- @last_response
- end
-
end
end
diff --git a/lib/chef/http/auth_credentials.rb b/lib/chef/http/auth_credentials.rb
index d5dbff3758..053b2c938e 100644
--- a/lib/chef/http/auth_credentials.rb
+++ b/lib/chef/http/auth_credentials.rb
@@ -49,7 +49,7 @@ class Chef
sign_obj = Mixlib::Authentication::SignedHeaderAuth.signing_object(request_params)
signed = sign_obj.sign(key).merge({ :host => host })
- signed.inject({}) { |memo, kv| memo["#{kv[0].to_s.upcase}"] = kv[1];memo }
+ signed.inject({}) { |memo, kv| memo["#{kv[0].to_s.upcase}"] = kv[1]; memo }
end
end
diff --git a/lib/chef/http/basic_client.rb b/lib/chef/http/basic_client.rb
index 3a87fe85e4..460744ea2a 100644
--- a/lib/chef/http/basic_client.rb
+++ b/lib/chef/http/basic_client.rb
@@ -34,6 +34,7 @@ class Chef
attr_reader :url
attr_reader :http_client
attr_reader :ssl_policy
+ attr_reader :keepalives
# Instantiate a BasicClient.
# === Arguments:
@@ -43,7 +44,11 @@ class Chef
def initialize(url, opts = {})
@url = url
@ssl_policy = opts[:ssl_policy] || DefaultSSLPolicy
- @http_client = build_http_client
+ @keepalives = opts[:keepalives] || false
+ end
+
+ def http_client
+ @http_client ||= build_http_client
end
def host
@@ -114,7 +119,11 @@ class Chef
http_client.read_timeout = config[:rest_timeout]
http_client.open_timeout = config[:rest_timeout]
- http_client
+ if keepalives
+ http_client.start
+ else
+ http_client
+ end
end
def config
diff --git a/lib/chef/http/socketless_chef_zero_client.rb b/lib/chef/http/socketless_chef_zero_client.rb
index 1acac5e758..d2f1f45b1d 100644
--- a/lib/chef/http/socketless_chef_zero_client.rb
+++ b/lib/chef/http/socketless_chef_zero_client.rb
@@ -197,9 +197,9 @@ class Chef
private
def headers_extracted_from_options
- options.reject { |name, _| KNOWN_OPTIONS.include?(name) }.map { |name, value|
+ options.reject { |name, _| KNOWN_OPTIONS.include?(name) }.map do |name, value|
[name.to_s.split("_").map { |segment| segment.capitalize }.join("-"), value]
- }
+ end
end
end
diff --git a/lib/chef/key.rb b/lib/chef/key.rb
index 1c25c5daad..38822e8b26 100644
--- a/lib/chef/key.rb
+++ b/lib/chef/key.rb
@@ -201,72 +201,71 @@ class Chef
chef_rest.delete("#{api_base}/#{@actor}/keys/#{@name}")
end
- # Class methods
- def self.from_hash(key_hash)
- if key_hash.has_key?("user")
- key = Chef::Key.new(key_hash["user"], "user")
- elsif key_hash.has_key?("client")
- key = Chef::Key.new(key_hash["client"], "client")
- else
- raise Chef::Exceptions::MissingKeyAttribute, "The hash passed to from_hash does not contain the key 'user' or 'client'. Please pass a hash that defines one of those keys."
+ class << self
+ def from_hash(key_hash)
+ if key_hash.has_key?("user")
+ key = Chef::Key.new(key_hash["user"], "user")
+ elsif key_hash.has_key?("client")
+ key = Chef::Key.new(key_hash["client"], "client")
+ else
+ raise Chef::Exceptions::MissingKeyAttribute, "The hash passed to from_hash does not contain the key 'user' or 'client'. Please pass a hash that defines one of those keys."
+ end
+ key.name key_hash["name"] if key_hash.key?("name")
+ key.public_key key_hash["public_key"] if key_hash.key?("public_key")
+ key.private_key key_hash["private_key"] if key_hash.key?("private_key")
+ key.create_key key_hash["create_key"] if key_hash.key?("create_key")
+ key.expiration_date key_hash["expiration_date"] if key_hash.key?("expiration_date")
+ key
end
- key.name key_hash["name"] if key_hash.key?("name")
- key.public_key key_hash["public_key"] if key_hash.key?("public_key")
- key.private_key key_hash["private_key"] if key_hash.key?("private_key")
- key.create_key key_hash["create_key"] if key_hash.key?("create_key")
- key.expiration_date key_hash["expiration_date"] if key_hash.key?("expiration_date")
- key
- end
-
- def self.from_json(json)
- Chef::Key.from_hash(Chef::JSONCompat.from_json(json))
- end
- def self.json_create(json)
- Chef.log_deprecation("Auto inflation of JSON data is deprecated. Please use Chef::Key#from_json or one of the load_by methods.")
- Chef::Key.from_json(json)
- end
+ def from_json(json)
+ Chef::Key.from_hash(Chef::JSONCompat.from_json(json))
+ end
- def self.list_by_user(actor, inflate = false)
- keys = Chef::ServerAPI.new(Chef::Config[:chef_server_root]).get("users/#{actor}/keys")
- self.list(keys, actor, :load_by_user, inflate)
- end
+ def json_create(json)
+ Chef.log_deprecation("Auto inflation of JSON data is deprecated. Please use Chef::Key#from_json or one of the load_by methods.")
+ Chef::Key.from_json(json)
+ end
- def self.list_by_client(actor, inflate = false)
- keys = Chef::ServerAPI.new(Chef::Config[:chef_server_url]).get("clients/#{actor}/keys")
- self.list(keys, actor, :load_by_client, inflate)
- end
+ def list_by_user(actor, inflate = false)
+ keys = Chef::ServerAPI.new(Chef::Config[:chef_server_root]).get("users/#{actor}/keys")
+ self.list(keys, actor, :load_by_user, inflate)
+ end
- def self.load_by_user(actor, key_name)
- response = Chef::ServerAPI.new(Chef::Config[:chef_server_root]).get("users/#{actor}/keys/#{key_name}")
- Chef::Key.from_hash(response.merge({ "user" => actor }))
- end
+ def list_by_client(actor, inflate = false)
+ keys = Chef::ServerAPI.new(Chef::Config[:chef_server_url]).get("clients/#{actor}/keys")
+ self.list(keys, actor, :load_by_client, inflate)
+ end
- def self.load_by_client(actor, key_name)
- response = Chef::ServerAPI.new(Chef::Config[:chef_server_url]).get("clients/#{actor}/keys/#{key_name}")
- Chef::Key.from_hash(response.merge({ "client" => actor }))
- end
+ def load_by_user(actor, key_name)
+ response = Chef::ServerAPI.new(Chef::Config[:chef_server_root]).get("users/#{actor}/keys/#{key_name}")
+ Chef::Key.from_hash(response.merge({ "user" => actor }))
+ end
- def self.generate_fingerprint(public_key)
- openssl_key_object = OpenSSL::PKey::RSA.new(public_key)
- data_string = OpenSSL::ASN1::Sequence([
- OpenSSL::ASN1::Integer.new(openssl_key_object.public_key.n),
- OpenSSL::ASN1::Integer.new(openssl_key_object.public_key.e),
- ])
- OpenSSL::Digest::SHA1.hexdigest(data_string.to_der).scan(/../).join(":")
- end
+ def load_by_client(actor, key_name)
+ response = Chef::ServerAPI.new(Chef::Config[:chef_server_url]).get("clients/#{actor}/keys/#{key_name}")
+ Chef::Key.from_hash(response.merge({ "client" => actor }))
+ end
- private
+ def generate_fingerprint(public_key)
+ openssl_key_object = OpenSSL::PKey::RSA.new(public_key)
+ data_string = OpenSSL::ASN1::Sequence([
+ OpenSSL::ASN1::Integer.new(openssl_key_object.public_key.n),
+ OpenSSL::ASN1::Integer.new(openssl_key_object.public_key.e),
+ ])
+ OpenSSL::Digest::SHA1.hexdigest(data_string.to_der).scan(/../).join(":")
+ end
- def self.list(keys, actor, load_method_symbol, inflate)
- if inflate
- keys.inject({}) do |key_map, result|
- name = result["name"]
- key_map[name] = Chef::Key.send(load_method_symbol, actor, name)
- key_map
+ def list(keys, actor, load_method_symbol, inflate)
+ if inflate
+ keys.inject({}) do |key_map, result|
+ name = result["name"]
+ key_map[name] = Chef::Key.send(load_method_symbol, actor, name)
+ key_map
+ end
+ else
+ keys
end
- else
- keys
end
end
end
diff --git a/lib/chef/knife.rb b/lib/chef/knife.rb
index 356bf47fd4..c9ecfbf0cc 100644
--- a/lib/chef/knife.rb
+++ b/lib/chef/knife.rb
@@ -233,61 +233,66 @@ class Chef
end
end
- private
-
OFFICIAL_PLUGINS = %w{ec2 rackspace windows openstack terremark bluebox}
- def self.path_from_caller(caller_line)
- caller_line.split(/:\d+/).first
- end
-
- # :nodoc:
- # Error out and print usage. probably because the arguments given by the
- # user could not be resolved to a subcommand.
- def self.subcommand_not_found!(args)
- ui.fatal("Cannot find subcommand for: '#{args.join(' ')}'")
+ class << self
+ private
- # Mention rehash when the subcommands cache(plugin_manifest.json) is used
- if subcommand_loader.is_a?(Chef::Knife::SubcommandLoader::HashedCommandLoader) ||
- subcommand_loader.is_a?(Chef::Knife::SubcommandLoader::CustomManifestLoader)
- ui.info("If this is a recently installed plugin, please run 'knife rehash' to update the subcommands cache.")
+ # @api private
+ def path_from_caller(caller_line)
+ caller_line.split(/:\d+/).first
end
- if category_commands = guess_category(args)
- list_commands(category_commands)
- elsif missing_plugin = ( OFFICIAL_PLUGINS.find { |plugin| plugin == args[0] } )
- ui.info("The #{missing_plugin} commands were moved to plugins in Chef 0.10")
- ui.info("You can install the plugin with `(sudo) gem install knife-#{missing_plugin}`")
- ui.info("Use `chef gem install knife-#{missing_plugin}` instead if using ChefDK")
- else
- list_commands
- end
+ # :nodoc:
+ # Error out and print usage. probably because the arguments given by the
+ # user could not be resolved to a subcommand.
+ # @api private
+ def subcommand_not_found!(args)
+ ui.fatal("Cannot find subcommand for: '#{args.join(' ')}'")
+
+ # Mention rehash when the subcommands cache(plugin_manifest.json) is used
+ if subcommand_loader.is_a?(Chef::Knife::SubcommandLoader::HashedCommandLoader) ||
+ subcommand_loader.is_a?(Chef::Knife::SubcommandLoader::CustomManifestLoader)
+ ui.info("If this is a recently installed plugin, please run 'knife rehash' to update the subcommands cache.")
+ end
- exit 10
- end
+ if category_commands = guess_category(args)
+ list_commands(category_commands)
+ elsif missing_plugin = ( OFFICIAL_PLUGINS.find { |plugin| plugin == args[0] } )
+ ui.info("The #{missing_plugin} commands were moved to plugins in Chef 0.10")
+ ui.info("You can install the plugin with `(sudo) gem install knife-#{missing_plugin}`")
+ ui.info("Use `chef gem install knife-#{missing_plugin}` instead if using ChefDK")
+ else
+ list_commands
+ end
+
+ exit 10
+ end
- def self.list_commands(preferred_category = nil)
- category_desc = preferred_category ? preferred_category + " " : ""
- msg "Available #{category_desc}subcommands: (for details, knife SUB-COMMAND --help)\n\n"
- subcommand_loader.list_commands(preferred_category).sort.each do |category, commands|
- next if category =~ /deprecated/i
- msg "** #{category.upcase} COMMANDS **"
- commands.sort.each do |command|
- subcommand_loader.load_command(command)
- msg subcommands[command].banner if subcommands[command]
+ # @api private
+ def list_commands(preferred_category = nil)
+ category_desc = preferred_category ? preferred_category + " " : ""
+ msg "Available #{category_desc}subcommands: (for details, knife SUB-COMMAND --help)\n\n"
+ subcommand_loader.list_commands(preferred_category).sort.each do |category, commands|
+ next if category =~ /deprecated/i
+ msg "** #{category.upcase} COMMANDS **"
+ commands.sort.each do |command|
+ subcommand_loader.load_command(command)
+ msg subcommands[command].banner if subcommands[command]
+ end
+ msg
end
- msg
end
- end
- def self.reset_config_path!
- @@chef_config_dir = nil
+ # @api private
+ def reset_config_path!
+ @@chef_config_dir = nil
+ end
+
end
reset_config_path!
- public
-
# Create a new instance of the current class configured for the given
# arguments and options
def initialize(argv = [])
@@ -324,31 +329,35 @@ class Chef
exit(1)
end
- # Returns a subset of the Chef::Config[:knife] Hash that is relevant to the
- # currently executing knife command. This is used by #configure_chef to
- # apply settings from knife.rb to the +config+ hash.
+ # keys from mixlib-cli options
+ def cli_keys
+ self.class.options.keys
+ end
+
+ # extracts the settings from the Chef::Config[:knife] sub-hash that correspond
+ # to knife cli options -- in preparation for merging config values with cli values
+ #
+ # NOTE: due to weirdness in mixlib-config #has_key? is only true if the value has
+ # been set by the user -- the Chef::Config defaults return #has_key?() of false and
+ # this code DEPENDS on that functionality since applying the default values in
+ # Chef::Config[:knife] would break the defaults in the cli that we would otherwise
+ # overwrite.
def config_file_settings
- config_file_settings = {}
- self.class.options.keys.each do |key|
- config_file_settings[key] = Chef::Config[:knife][key] if Chef::Config[:knife].has_key?(key)
+ cli_keys.each_with_object({}) do |key, memo|
+ memo[key] = Chef::Config[:knife][key] if Chef::Config[:knife].has_key?(key)
end
- config_file_settings
end
- # Apply Config in this order:
- # defaults from mixlib-cli
- # settings from config file, via Chef::Config[:knife]
- # config from command line
+ # config is merged in this order (inverse of precedence)
+ # default_config - mixlib-cli defaults (accessor from the mixin)
+ # config_file_settings - Chef::Config[:knife] sub-hash
+ # config - mixlib-cli settings (accessor from the mixin)
def merge_configs
- # Apply config file settings on top of mixlib-cli defaults
- combined_config = default_config.merge(config_file_settings)
- # Apply user-supplied options on top of the above combination
- combined_config = combined_config.merge(config)
- # replace the config hash from mixlib-cli with our own.
- # Need to use the mutate-in-place #replace method instead of assigning to
- # the instance variable because other code may have a reference to the
- # original config hash object.
- config.replace(combined_config)
+ # other code may have a handle to the config object, so use Hash#replace to deliberately
+ # update-in-place.
+ config.replace(
+ default_config.merge(config_file_settings).merge(config)
+ )
end
# Catch-all method that does any massaging needed for various config
diff --git a/lib/chef/knife/bootstrap.rb b/lib/chef/knife/bootstrap.rb
index 18914f6be2..ee4d9ce7af 100644
--- a/lib/chef/knife/bootstrap.rb
+++ b/lib/chef/knife/bootstrap.rb
@@ -101,6 +101,14 @@ class Chef
:description => "The proxy server for the node being bootstrapped",
:proc => Proc.new { |p| Chef::Config[:knife][:bootstrap_proxy] = p }
+ option :bootstrap_proxy_user,
+ :long => "--bootstrap-proxy-user PROXY_USER",
+ :description => "The proxy authentication username for the node being bootstrapped"
+
+ option :bootstrap_proxy_pass,
+ :long => "--bootstrap-proxy-pass PROXY_PASS",
+ :description => "The proxy authentication password for the node being bootstrapped"
+
option :bootstrap_no_proxy,
:long => "--bootstrap-no-proxy [NO_PROXY_URL|NO_PROXY_IP]",
:description => "Do not proxy locations for the node being bootstrapped; this option is used internally by Opscode",
diff --git a/lib/chef/knife/client_delete.rb b/lib/chef/knife/client_delete.rb
index e1b2365361..08cdf6c7dd 100644
--- a/lib/chef/knife/client_delete.rb
+++ b/lib/chef/knife/client_delete.rb
@@ -43,7 +43,7 @@ class Chef
exit 1
end
- delete_object(Chef::ApiClientV1, @client_name, "client") {
+ delete_object(Chef::ApiClientV1, @client_name, "client") do
object = Chef::ApiClientV1.load(@client_name)
if object.validator
unless config[:delete_validators]
@@ -52,7 +52,7 @@ class Chef
end
end
object.destroy
- }
+ end
end
end
diff --git a/lib/chef/knife/cookbook_bulk_delete.rb b/lib/chef/knife/cookbook_bulk_delete.rb
index bd1c8a22cc..cdd1584e36 100644
--- a/lib/chef/knife/cookbook_bulk_delete.rb
+++ b/lib/chef/knife/cookbook_bulk_delete.rb
@@ -42,7 +42,7 @@ class Chef
all_cookbooks = Chef::CookbookVersion.list
cookbooks_names = all_cookbooks.keys.grep(regex)
- cookbooks_to_delete = cookbooks_names.inject({}) { |hash, name| hash[name] = all_cookbooks[name];hash }
+ cookbooks_to_delete = cookbooks_names.inject({}) { |hash, name| hash[name] = all_cookbooks[name]; hash }
ui.msg "All versions of the following cookbooks will be deleted:"
ui.msg ""
ui.msg ui.list(cookbooks_to_delete.keys.sort, :columns_down)
diff --git a/lib/chef/knife/cookbook_show.rb b/lib/chef/knife/cookbook_show.rb
index a20e62ffc2..d0c930de0a 100644
--- a/lib/chef/knife/cookbook_show.rb
+++ b/lib/chef/knife/cookbook_show.rb
@@ -63,7 +63,7 @@ class Chef
node[:platform_version] = config[:platform_version] if config.has_key?(:platform_version)
class << node
- def attribute?(name)
+ def attribute?(name) # rubocop:disable Lint/NestedMethodDefinition
has_key?(name)
end
end
diff --git a/lib/chef/knife/core/bootstrap_context.rb b/lib/chef/knife/core/bootstrap_context.rb
index 6db1a83c73..b2670f196b 100644
--- a/lib/chef/knife/core/bootstrap_context.rb
+++ b/lib/chef/knife/core/bootstrap_context.rb
@@ -114,6 +114,16 @@ validation_client_name "#{@chef_config[:validation_client_name]}"
client_rb << %Q{https_proxy "#{knife_config[:bootstrap_proxy]}"\n}
end
+ if knife_config[:bootstrap_proxy_user]
+ client_rb << %Q{http_proxy_user "#{knife_config[:bootstrap_proxy_user]}"\n}
+ client_rb << %Q{https_proxy_user "#{knife_config[:bootstrap_proxy_user]}"\n}
+ end
+
+ if knife_config[:bootstrap_proxy_pass]
+ client_rb << %Q{http_proxy_pass "#{knife_config[:bootstrap_proxy_pass]}"\n}
+ client_rb << %Q{https_proxy_pass "#{knife_config[:bootstrap_proxy_pass]}"\n}
+ end
+
if knife_config[:bootstrap_no_proxy]
client_rb << %Q{no_proxy "#{knife_config[:bootstrap_no_proxy]}"\n}
end
diff --git a/lib/chef/knife/core/gem_glob_loader.rb b/lib/chef/knife/core/gem_glob_loader.rb
index f5eff26903..34c5c53d75 100644
--- a/lib/chef/knife/core/gem_glob_loader.rb
+++ b/lib/chef/knife/core/gem_glob_loader.rb
@@ -81,9 +81,9 @@ class Chef
files = []
if check_load_path
- files = $LOAD_PATH.map { |load_path|
+ files = $LOAD_PATH.map do |load_path|
Dir["#{File.expand_path glob, Chef::Util::PathHelper.escape_glob_dir(load_path)}#{Gem.suffix_pattern}"]
- }.flatten.select { |file| File.file? file.untaint }
+ end.flatten.select { |file| File.file? file.untaint }
end
gem_files = latest_gem_specs.map do |spec|
@@ -110,7 +110,7 @@ class Chef
end
def check_spec_for_glob(spec, glob)
- dirs = if spec.require_paths.size > 1 then
+ dirs = if spec.require_paths.size > 1
"{#{spec.require_paths.join(',')}}"
else
spec.require_paths.first
diff --git a/lib/chef/knife/search.rb b/lib/chef/knife/search.rb
index 38d1ab3f42..d102c1e955 100644
--- a/lib/chef/knife/search.rb
+++ b/lib/chef/knife/search.rb
@@ -18,6 +18,7 @@
require "chef/knife"
require "chef/knife/core/node_presenter"
+require "addressable/uri"
class Chef
class Knife
@@ -85,8 +86,7 @@ class Chef
end
q = Chef::Search::Query.new
- escaped_query = URI.escape(@query,
- Regexp.new("[^#{URI::PATTERN::UNRESERVED}]"))
+ escaped_query = Addressable::URI.encode_component(@query, Addressable::URI::CharacterClasses::QUERY)
result_items = []
result_count = 0
diff --git a/lib/chef/knife/ssh.rb b/lib/chef/knife/ssh.rb
index 2bbcbfc79e..6f266b2719 100644
--- a/lib/chef/knife/ssh.rb
+++ b/lib/chef/knife/ssh.rb
@@ -164,9 +164,7 @@ class Chef
end
def configure_session
- list = config[:manual] ?
- @name_args[0].split(" ") :
- search_nodes
+ list = config[:manual] ? @name_args[0].split(" ") : search_nodes
if list.length == 0
if @action_nodes.length == 0
ui.fatal("No nodes returned from search")
@@ -548,24 +546,24 @@ class Chef
configure_session
exit_status =
- case @name_args[1]
- when "interactive"
- interactive
- when "screen"
- screen
- when "tmux"
- tmux
- when "macterm"
- macterm
- when "cssh"
- cssh
- when "csshx"
- Chef::Log.warn("knife ssh csshx will be deprecated in a future release")
- Chef::Log.warn("please use knife ssh cssh instead")
- cssh
- else
- ssh_command(@name_args[1..-1].join(" "))
- end
+ case @name_args[1]
+ when "interactive"
+ interactive
+ when "screen"
+ screen
+ when "tmux"
+ tmux
+ when "macterm"
+ macterm
+ when "cssh"
+ cssh
+ when "csshx"
+ Chef::Log.warn("knife ssh csshx will be deprecated in a future release")
+ Chef::Log.warn("please use knife ssh cssh instead")
+ cssh
+ else
+ ssh_command(@name_args[1..-1].join(" "))
+ end
session.close
if exit_status != 0
diff --git a/lib/chef/knife/status.rb b/lib/chef/knife/status.rb
index 551d5addfc..0e3cd7e7d6 100644
--- a/lib/chef/knife/status.rb
+++ b/lib/chef/knife/status.rb
@@ -96,13 +96,13 @@ class Chef
all_nodes << node
end
- output(all_nodes.sort { |n1, n2|
+ output(all_nodes.sort do |n1, n2|
if config[:sort_reverse] || Chef::Config[:knife][:sort_status_reverse]
(n2["ohai_time"] || 0) <=> (n1["ohai_time"] || 0)
else
(n1["ohai_time"] || 0) <=> (n2["ohai_time"] || 0)
end
- })
+ end)
end
end
diff --git a/lib/chef/mixin/command/unix.rb b/lib/chef/mixin/command/unix.rb
index bfd507979f..aa541c3637 100644
--- a/lib/chef/mixin/command/unix.rb
+++ b/lib/chef/mixin/command/unix.rb
@@ -64,7 +64,7 @@ class Chef
$VERBOSE = nil
ps.last.fcntl(Fcntl::F_SETFD, Fcntl::FD_CLOEXEC)
- cid = fork {
+ cid = fork do
pw.last.close
STDIN.reopen pw.first
pw.first.close
@@ -111,7 +111,7 @@ class Chef
end
ps.last.close unless ps.last.closed?
exit!
- }
+ end
ensure
$VERBOSE = verbose
end
diff --git a/lib/chef/mixin/powershell_type_coercions.rb b/lib/chef/mixin/powershell_type_coercions.rb
index 381cbed637..6159c87948 100644
--- a/lib/chef/mixin/powershell_type_coercions.rb
+++ b/lib/chef/mixin/powershell_type_coercions.rb
@@ -63,7 +63,7 @@ class Chef
end
def unsafe?(s)
- ["'", '#', "`", '"'].any? do |x|
+ ["'", "#", "`", '"'].any? do |x|
s.include? x
end
end
diff --git a/lib/chef/mixin/properties.rb b/lib/chef/mixin/properties.rb
index ae2406f1ae..8ff2cc4501 100644
--- a/lib/chef/mixin/properties.rb
+++ b/lib/chef/mixin/properties.rb
@@ -79,6 +79,9 @@ class Chef
# part of desired state. Defaults to `true`.
# @option options [Boolean] :identity `true` if this property
# is part of object identity. Defaults to `false`.
+ # @option options [Boolean] :sensitive `true` if this property could
+ # contain sensitive information and whose value should be redacted
+ # in any resource reporting / auditing output. Defaults to `false`.
#
# @example Bare property
# property :x
diff --git a/lib/chef/mixin/securable.rb b/lib/chef/mixin/securable.rb
index a88d534b37..55b4e0a6d1 100644
--- a/lib/chef/mixin/securable.rb
+++ b/lib/chef/mixin/securable.rb
@@ -43,7 +43,7 @@ class Chef
:mode,
arg,
:callbacks => {
- "not in valid numeric range" => lambda { |m|
+ "not in valid numeric range" => lambda do |m|
if m.kind_of?(String)
m =~ /^0/ || m = "0#{m}"
end
@@ -54,7 +54,7 @@ class Chef
else
Integer(m) <= 07777 && Integer(m) >= 0
end
- },
+ end,
}
)
end
diff --git a/lib/chef/mixin/shell_out.rb b/lib/chef/mixin/shell_out.rb
index 1f7deb21d2..a258a91075 100644
--- a/lib/chef/mixin/shell_out.rb
+++ b/lib/chef/mixin/shell_out.rb
@@ -78,6 +78,36 @@ class Chef
return my_command_args
end
+ # Helper for sublcasses to convert an array of string args into a string. It
+ # will compact nil or empty strings in the array and will join the array elements
+ # with spaces, without introducing any double spaces for nil/empty elements.
+ #
+ # @param args [String] variable number of string arguments
+ # @return [String] nicely concatenated string or empty string
+ def a_to_s(*args)
+ clean_array(*args).join(" ")
+ end
+
+ # Helper for sublcasses to reject nil and empty strings out of an array. It allows
+ # using the array form of shell_out (which avoids the need to surround arguments with
+ # quote marks to deal with shells).
+ #
+ # Usage:
+ # shell_out!(*clean_array("useradd", universal_options, useradd_options, new_resource.username))
+ #
+ # universal_options and useradd_options can be nil, empty array, empty string, strings or arrays
+ # and the result makes sense.
+ #
+ # keeping this separate from shell_out!() makes it a bit easier to write expectations against the
+ # shell_out args and be able to omit nils and such in the tests (and to test that the nils are
+ # being rejected correctly).
+ #
+ # @param args [String] variable number of string arguments
+ # @return [Array] array of strings with nil and null string rejection
+ def clean_array(*args)
+ args.flatten.reject { |i| i.nil? || i == "" }.map(&:to_s)
+ end
+
private
def shell_out_command(*command_args)
diff --git a/lib/chef/mixin/uris.rb b/lib/chef/mixin/uris.rb
index 24e8a4f9ed..7dc04d662b 100644
--- a/lib/chef/mixin/uris.rb
+++ b/lib/chef/mixin/uris.rb
@@ -17,6 +17,7 @@
#
require "uri"
+require "addressable/uri"
class Chef
module Mixin
@@ -34,7 +35,7 @@ class Chef
URI.parse(source)
rescue URI::InvalidURIError
Chef::Log.warn("#{source} was an invalid URI. Trying to escape invalid characters")
- URI.parse(URI.escape(source))
+ URI.parse(Addressable::URI.encode(source))
end
end
diff --git a/lib/chef/mixin/windows_architecture_helper.rb b/lib/chef/mixin/windows_architecture_helper.rb
index 11e1b5559d..49252af484 100644
--- a/lib/chef/mixin/windows_architecture_helper.rb
+++ b/lib/chef/mixin/windows_architecture_helper.rb
@@ -74,16 +74,15 @@ class Chef
def node_supports_windows_architecture?(node, desired_architecture)
assert_valid_windows_architecture!(desired_architecture)
- return (node_windows_architecture(node) == :x86_64 ||
- desired_architecture == :i386) ? true : false
+ return ( node_windows_architecture(node) == :x86_64 ) || ( desired_architecture == :i386 )
end
def valid_windows_architecture?(architecture)
- return (architecture == :x86_64) || (architecture == :i386)
+ return ( architecture == :x86_64 ) || ( architecture == :i386 )
end
def assert_valid_windows_architecture!(architecture)
- if ! valid_windows_architecture?(architecture)
+ if !valid_windows_architecture?(architecture)
raise Chef::Exceptions::Win32ArchitectureIncorrect,
"The specified architecture was not valid. It must be one of :i386 or :x86_64"
end
diff --git a/lib/chef/monkey_patches/webrick-utils.rb b/lib/chef/monkey_patches/webrick-utils.rb
index 7880adb202..ccca5825e2 100644
--- a/lib/chef/monkey_patches/webrick-utils.rb
+++ b/lib/chef/monkey_patches/webrick-utils.rb
@@ -31,7 +31,7 @@ module WEBrick
Socket::AI_PASSIVE) # flag
last_error = nil
sockets = []
- res.each {|ai|
+ res.each do |ai|
begin
logger.debug("TCPServer.new(#{ai[3]}, #{port})") if logger
sock = TCPServer.new(ai[3], port)
@@ -42,7 +42,7 @@ module WEBrick
logger.warn("TCPServer Error: #{ex}") if logger
last_error = ex
end
- }
+ end
raise last_error if sockets.empty?
return sockets
end
diff --git a/lib/chef/monologger.rb b/lib/chef/monologger.rb
index 8bcdae1293..82816e887f 100644
--- a/lib/chef/monologger.rb
+++ b/lib/chef/monologger.rb
@@ -61,7 +61,7 @@ class MonoLogger < Logger
@dev.close rescue nil
end
- private
+ private
def open_logfile(filename)
if FileTest.exist?(filename)
diff --git a/lib/chef/node.rb b/lib/chef/node.rb
index 54faab6d3e..212b1ced14 100644
--- a/lib/chef/node.rb
+++ b/lib/chef/node.rb
@@ -642,8 +642,8 @@ class Chef
end
end
- def <=>(other_node)
- self.name <=> other_node.name
+ def <=>(other)
+ self.name <=> other.name
end
private
diff --git a/lib/chef/node/attribute.rb b/lib/chef/node/attribute.rb
index f5fe89251d..95b3b09f7e 100644
--- a/lib/chef/node/attribute.rb
+++ b/lib/chef/node/attribute.rb
@@ -537,12 +537,12 @@ class Chef
end
def inspect
- "#<#{self.class} " << (COMPONENTS + [:@merged_attributes, :@properties]).map {|iv|
+ "#<#{self.class} " << (COMPONENTS + [:@merged_attributes, :@properties]).map do |iv|
"#{iv}=#{instance_variable_get(iv).inspect}"
- }.join(", ") << ">"
+ end.join(", ") << ">"
end
- private
+ private
# Helper method for merge_all/merge_defaults/merge_overrides.
#
diff --git a/lib/chef/platform/provider_mapping.rb b/lib/chef/platform/provider_mapping.rb
index 40474242f0..bc565d92ef 100644
--- a/lib/chef/platform/provider_mapping.rb
+++ b/lib/chef/platform/provider_mapping.rb
@@ -197,8 +197,11 @@ class Chef
def resource_matching_provider(platform, version, resource_type)
if resource_type.kind_of?(Chef::Resource)
- class_name = resource_type.class.name ? resource_type.class.name.split("::").last :
- convert_to_class_name(resource_type.resource_name.to_s)
+ class_name = if resource_type.class.name
+ resource_type.class.name.split("::").last
+ else
+ convert_to_class_name(resource_type.resource_name.to_s)
+ end
if Chef::Provider.const_defined?(class_name, false)
Chef::Log.warn("Class Chef::Provider::#{class_name} does not declare 'provides #{convert_to_snake_case(class_name).to_sym.inspect}'.")
diff --git a/lib/chef/property.rb b/lib/chef/property.rb
index 0589cb4c54..a357ba9ee3 100644
--- a/lib/chef/property.rb
+++ b/lib/chef/property.rb
@@ -230,14 +230,25 @@ class Chef
end
#
+ # Whether this property is sensitive or not.
+ #
+ # Defaults to false.
+ #
+ # @return [Boolean]
+ #
+ def sensitive?
+ options.fetch(:sensitive, false)
+ end
+
+ #
# Validation options. (See Chef::Mixin::ParamsValidate#validate.)
#
# @return [Hash<Symbol,Object>]
#
def validation_options
- @validation_options ||= options.reject { |k, v|
- [:declared_in, :name, :instance_variable_name, :desired_state, :identity, :default, :name_property, :coerce, :required, :nillable].include?(k)
- }
+ @validation_options ||= options.reject do |k, v|
+ [:declared_in, :name, :instance_variable_name, :desired_state, :identity, :default, :name_property, :coerce, :required, :nillable, :sensitive].include?(k)
+ end
end
#
diff --git a/lib/chef/provider/apt_repository.rb b/lib/chef/provider/apt_repository.rb
index 1e7db80620..9e077c8cbb 100644
--- a/lib/chef/provider/apt_repository.rb
+++ b/lib/chef/provider/apt_repository.rb
@@ -19,6 +19,7 @@
require "chef/resource"
require "chef/dsl/declare_resource"
require "chef/mixin/shell_out"
+require "chef/mixin/which"
require "chef/http/simple"
require "chef/provider/noop"
@@ -28,9 +29,10 @@ class Chef
use_inline_resources
include Chef::Mixin::ShellOut
+ extend Chef::Mixin::Which
provides :apt_repository do
- uses_apt?
+ which("apt-get")
end
def whyrun_supported?
@@ -104,12 +106,6 @@ class Chef
end
end
- def self.uses_apt?
- ENV["PATH"] ||= ""
- paths = %w{ /bin /usr/bin /sbin /usr/sbin } + ENV["PATH"].split(::File::PATH_SEPARATOR)
- paths.any? { |path| ::File.executable?(::File.join(path, "apt-get")) }
- end
-
def is_key_id?(id)
id = id[2..-1] if id.start_with?("0x")
id =~ /^\h+$/ && [8, 16, 40].include?(id.length)
@@ -254,4 +250,4 @@ class Chef
end
end
-Chef::Provider::Noop.provides :apt_resource
+Chef::Provider::Noop.provides :apt_repository
diff --git a/lib/chef/provider/apt_update.rb b/lib/chef/provider/apt_update.rb
index d2dd5cfb14..0320e9a83f 100644
--- a/lib/chef/provider/apt_update.rb
+++ b/lib/chef/provider/apt_update.rb
@@ -16,15 +16,20 @@
# limitations under the License.
#
-require "chef/resource"
-require "chef/dsl/declare_resource"
+require "chef/provider"
+require "chef/provider/noop"
+require "chef/mixin/which"
class Chef
class Provider
class AptUpdate < Chef::Provider
use_inline_resources
- provides :apt_update, os: "linux"
+ extend Chef::Mixin::Which
+
+ provides :apt_update do
+ which("apt-get")
+ end
APT_CONF_DIR = "/etc/apt/apt.conf.d"
STAMP_DIR = "/var/lib/apt/periodic"
@@ -78,3 +83,5 @@ class Chef
end
end
end
+
+Chef::Provider::Noop.provides :apt_update
diff --git a/lib/chef/provider/cron.rb b/lib/chef/provider/cron.rb
index 36b67ab6a5..7baaeec0c5 100644
--- a/lib/chef/provider/cron.rb
+++ b/lib/chef/provider/cron.rb
@@ -187,8 +187,7 @@ class Chef
end
crontab << line
end
- description = cron_found ? "remove #{@new_resource.name} from crontab" :
- "save unmodified crontab"
+ description = cron_found ? "remove #{@new_resource.name} from crontab" : "save unmodified crontab"
converge_by(description) do
write_crontab crontab
Chef::Log.info("#{@new_resource} deleted crontab entry")
@@ -237,7 +236,7 @@ class Chef
newcron = ""
newcron << "# Chef Name: #{new_resource.name}\n"
[ :mailto, :path, :shell, :home ].each do |v|
- newcron << "#{v.to_s.upcase}=#{@new_resource.send(v)}\n" if @new_resource.send(v)
+ newcron << "#{v.to_s.upcase}=\"#{@new_resource.send(v)}\"\n" if @new_resource.send(v)
end
@new_resource.environment.each do |name, value|
newcron << "#{name}=#{value}\n"
diff --git a/lib/chef/provider/dsc_script.rb b/lib/chef/provider/dsc_script.rb
index 79769d9773..66783ceb0f 100644
--- a/lib/chef/provider/dsc_script.rb
+++ b/lib/chef/provider/dsc_script.rb
@@ -32,12 +32,12 @@ class Chef
@dsc_resource = dsc_resource
@resource_converged = false
@operations = {
- :set => Proc.new { |config_manager, document, shellout_flags|
+ :set => Proc.new do |config_manager, document, shellout_flags|
config_manager.set_configuration(document, shellout_flags)
- },
- :test => Proc.new { |config_manager, document, shellout_flags|
+ end,
+ :test => Proc.new do |config_manager, document, shellout_flags|
config_manager.test_configuration(document, shellout_flags)
- } }
+ end }
end
def action_run
diff --git a/lib/chef/provider/file.rb b/lib/chef/provider/file.rb
index bb0762ceb7..7f85085eeb 100644
--- a/lib/chef/provider/file.rb
+++ b/lib/chef/provider/file.rb
@@ -154,7 +154,6 @@ class Chef
do_contents_changes
do_acl_changes
do_selinux
- do_resolv_conf_fixup
load_resource_attributes_from_file(@new_resource)
end
@@ -446,13 +445,6 @@ class Chef
end
end
- def do_resolv_conf_fixup
- # reload /etc/resolv.conf after we edit it -- only on linux -- and see lib/chef/application.rb
- if new_resource.path == "/etc/resolv.conf" && RbConfig::CONFIG["host_os"] =~ /linux/
- Resolv::DefaultResolver.replace_resolvers [Resolv::DNS.new("/etc/resolv.conf")]
- end
- end
-
def do_acl_changes
if access_controls.requires_changes?
converge_by(access_controls.describe_changes) do
diff --git a/lib/chef/provider/group/usermod.rb b/lib/chef/provider/group/usermod.rb
index e4b19181aa..bef4b667a2 100644
--- a/lib/chef/provider/group/usermod.rb
+++ b/lib/chef/provider/group/usermod.rb
@@ -57,7 +57,7 @@ class Chef
# This provider only supports adding members with
# append. Only if the action is create we will go
# ahead and add members.
- if @new_resource.action == :create
+ if @new_resource.action.include?(:create)
members.each do |member|
add_member(member)
end
diff --git a/lib/chef/provider/link.rb b/lib/chef/provider/link.rb
index 5fce97e5b3..16d30319b3 100644
--- a/lib/chef/provider/link.rb
+++ b/lib/chef/provider/link.rb
@@ -141,9 +141,16 @@ class Chef
def action_delete
if @current_resource.to # Exists
- converge_by("delete link at #{@new_resource.target_file}") do
- ::File.delete(@new_resource.target_file)
- Chef::Log.info("#{@new_resource} deleted")
+ if Chef::Platform.windows? && ::File.directory?(@current_resource.target_file)
+ converge_by("delete link to dir at #{@new_resource.target_file}") do
+ ::Dir.delete(@new_resource.target_file)
+ Chef::Log.info("#{@new_resource} deleted")
+ end
+ else
+ converge_by("delete link to file at #{@new_resource.target_file}") do
+ ::File.delete(@new_resource.target_file)
+ Chef::Log.info("#{@new_resource} deleted")
+ end
end
end
end
diff --git a/lib/chef/provider/osx_profile.rb b/lib/chef/provider/osx_profile.rb
index f2e71a6621..69ecf2ddb9 100644
--- a/lib/chef/provider/osx_profile.rb
+++ b/lib/chef/provider/osx_profile.rb
@@ -66,33 +66,33 @@ class Chef
def define_resource_requirements
requirements.assert(:remove) do |a|
if @new_profile_identifier
- a.assertion {
+ a.assertion do
!@new_profile_identifier.nil? &&
!@new_profile_identifier.end_with?(".mobileconfig") &&
- /^\w+(?:\.\w+)+$/.match(@new_profile_identifier)
- }
+ /^\w+(?:(\.| )\w+)+$/.match(@new_profile_identifier)
+ end
a.failure_message RuntimeError, "when removing using the identifier attribute, it must match the profile identifier"
else
new_profile_name = @new_resource.profile_name
- a.assertion {
+ a.assertion do
!new_profile_name.end_with?(".mobileconfig") &&
- /^\w+(?:\.\w+)+$/.match(new_profile_name)
- }
+ /^\w+(?:(\.| )\w+)+$/.match(new_profile_name)
+ end
a.failure_message RuntimeError, "When removing by resource name, it must match the profile identifier "
end
end
requirements.assert(:install) do |a|
if @new_profile_hash.is_a?(Hash)
- a.assertion {
+ a.assertion do
@new_profile_hash.include?("PayloadIdentifier")
- }
+ end
a.failure_message RuntimeError, "The specified profile does not seem to be valid"
end
if @new_profile_hash.is_a?(String)
- a.assertion {
+ a.assertion do
@new_profile_hash.end_with?(".mobileconfig")
- }
+ end
a.failure_message RuntimeError, "#{new_profile_hash}' is not a valid profile"
end
end
diff --git a/lib/chef/provider/package.rb b/lib/chef/provider/package.rb
index cac0fb6eb0..3f641145e6 100644
--- a/lib/chef/provider/package.rb
+++ b/lib/chef/provider/package.rb
@@ -194,12 +194,12 @@ class Chef
end
def action_reconfig
- if @current_resource.version == nil then
+ if @current_resource.version == nil
Chef::Log.debug("#{@new_resource} is NOT installed - nothing to do")
return
end
- unless @new_resource.response_file then
+ unless @new_resource.response_file
Chef::Log.debug("#{@new_resource} no response_file provided - nothing to do")
return
end
@@ -588,16 +588,6 @@ class Chef
end
args
end
-
- # Helper for sublcasses to convert an array of string args into a string. It
- # will compact nil or empty strings in the array and will join the array elements
- # with spaces, without introducing any double spaces for nil/empty elements.
- #
- # @param args [String] variable number of string arguments
- # @return [String] nicely concatenated string or empty string
- def a_to_s(*args)
- args.flatten.reject { |i| i.nil? || i == "" }.join(" ")
- end
end
end
end
diff --git a/lib/chef/provider/package/rubygems.rb b/lib/chef/provider/package/rubygems.rb
index 0aeec951b1..187197d143 100644
--- a/lib/chef/provider/package/rubygems.rb
+++ b/lib/chef/provider/package/rubygems.rb
@@ -159,19 +159,22 @@ class Chef
# Find the newest gem version available from Gem.sources that satisfies
# the constraints of +gem_dependency+
def find_newest_remote_version(gem_dependency, *sources)
- available_gems = dependency_installer.find_gems_with_sources(gem_dependency)
- spec, source = if available_gems.respond_to?(:last)
- # DependencyInstaller sorts the results such that the last one is
- # always the one it considers best.
- spec_with_source = available_gems.last
- spec_with_source && spec_with_source
- else
- # Rubygems 2.0 returns a Gem::Available set, which is a
- # collection of AvailableSet::Tuple structs
- available_gems.pick_best!
- best_gem = available_gems.set.first
- best_gem && [best_gem.spec, best_gem.source]
- end
+ spec, source =
+ if Chef::Config[:rubygems_cache_enabled]
+ # This code caches every gem on rubygems.org and uses lots of RAM
+ available_gems = dependency_installer.find_gems_with_sources(gem_dependency)
+ available_gems.pick_best!
+ best_gem = available_gems.set.first
+ best_gem && [best_gem.spec, best_gem.source]
+ else
+ # Use the API that 'gem install' calls which does not pull down the rubygems universe
+ begin
+ rs = dependency_installer.resolve_dependencies gem_dependency.name, gem_dependency.requirement
+ rs.specs.select { |s| s.name == gem_dependency.name }.first
+ rescue Gem::UnsatisfiableDependencyError
+ nil
+ end
+ end
version = spec && spec.version
if version
@@ -519,9 +522,7 @@ class Chef
install_via_gem_command(name, version)
end
elsif @new_resource.gem_binary.nil?
- # domain is used by Gem::DependencyInstaller rather than by Chef code
- # domain can be :local, :remote or :both
- @gem_env.install(@new_resource.source, domain: :local)
+ @gem_env.install(@new_resource.source)
else
install_via_gem_command(name, version)
end
diff --git a/lib/chef/provider/package/windows.rb b/lib/chef/provider/package/windows.rb
index a5f3ff7191..753d3c279e 100644
--- a/lib/chef/provider/package/windows.rb
+++ b/lib/chef/provider/package/windows.rb
@@ -201,6 +201,7 @@ class Chef
def resource_for_provider
@resource_for_provider = Chef::Resource::WindowsPackage.new(new_resource.name).tap do |r|
r.source(Chef::Util::PathHelper.validate_path(source_location)) unless source_location.nil?
+ r.cookbook_name = new_resource.cookbook_name
r.version(new_resource.version)
r.timeout(new_resource.timeout)
r.returns(new_resource.returns)
@@ -216,6 +217,7 @@ class Chef
def source_resource
@source_resource ||= Chef::Resource::RemoteFile.new(default_download_cache_path, run_context).tap do |r|
r.source(new_resource.source)
+ r.cookbook_name = new_resource.cookbook_name
r.checksum(new_resource.checksum)
r.backup(false)
diff --git a/lib/chef/provider/package/windows/exe.rb b/lib/chef/provider/package/windows/exe.rb
index 211845c073..44a2f19d1e 100644
--- a/lib/chef/provider/package/windows/exe.rb
+++ b/lib/chef/provider/package/windows/exe.rb
@@ -71,7 +71,7 @@ class Chef
uninstall_entries.select { |entry| [uninstall_version].flatten.include?(entry.display_version) }
.map { |version| version.uninstall_string }.uniq.each do |uninstall_string|
Chef::Log.debug("Registry provided uninstall string for #{new_resource} is '#{uninstall_string}'")
- shell_out!(uninstall_command(uninstall_string), { returns: new_resource.returns })
+ shell_out!(uninstall_command(uninstall_string), { :timeout => new_resource.timeout, :returns => new_resource.returns })
end
end
diff --git a/lib/chef/provider/package/windows/registry_uninstall_entry.rb b/lib/chef/provider/package/windows/registry_uninstall_entry.rb
index 3fa00b6081..a693558883 100644
--- a/lib/chef/provider/package/windows/registry_uninstall_entry.rb
+++ b/lib/chef/provider/package/windows/registry_uninstall_entry.rb
@@ -79,8 +79,6 @@ class Chef
attr_reader :uninstall_string
attr_reader :data
- private
-
UNINSTALL_SUBKEY = 'Software\Microsoft\Windows\CurrentVersion\Uninstall'.freeze
end
end
diff --git a/lib/chef/provider/package/yum/rpm_utils.rb b/lib/chef/provider/package/yum/rpm_utils.rb
index a748c664a9..032597d047 100644
--- a/lib/chef/provider/package/yum/rpm_utils.rb
+++ b/lib/chef/provider/package/yum/rpm_utils.rb
@@ -243,16 +243,16 @@ class Chef
self.new(*args)
end
- def <=>(y)
- compare_versions(y)
+ def <=>(other)
+ compare_versions(other)
end
- def compare(y)
- compare_versions(y, false)
+ def compare(other)
+ compare_versions(other, false)
end
- def partial_compare(y)
- compare_versions(y, true)
+ def partial_compare(other)
+ compare_versions(other, true)
end
# RPM::Version rpm_version_to_s equivalent
@@ -352,8 +352,8 @@ class Chef
alias :name :n
alias :arch :a
- def <=>(y)
- compare(y)
+ def <=>(other)
+ compare(other)
end
def compare(y)
diff --git a/lib/chef/provider/package/yum/yum_cache.rb b/lib/chef/provider/package/yum/yum_cache.rb
index fb25a91c8c..7462529113 100644
--- a/lib/chef/provider/package/yum/yum_cache.rb
+++ b/lib/chef/provider/package/yum/yum_cache.rb
@@ -197,7 +197,7 @@ class Chef
def shabang?(file)
::File.open(file, "r") do |f|
- f.read(2) == '#!'
+ f.read(2) == "#!"
end
rescue Errno::ENOENT
false
diff --git a/lib/chef/provider/remote_file/ftp.rb b/lib/chef/provider/remote_file/ftp.rb
index 5935e83301..b382c20c31 100644
--- a/lib/chef/provider/remote_file/ftp.rb
+++ b/lib/chef/provider/remote_file/ftp.rb
@@ -153,9 +153,9 @@ class Chef
def parse_path
path = uri.path.sub(%r{\A/}, "%2F") # re-encode the beginning slash because uri library decodes it.
directories = path.split(%r{/}, -1)
- directories.each {|d|
+ directories.each do |d|
d.gsub!(/%([0-9A-Fa-f][0-9A-Fa-f])/) { [$1].pack("H2") }
- }
+ end
unless filename = directories.pop
raise ArgumentError, "no filename: #{path.inspect}"
end
diff --git a/lib/chef/provider/remote_file/sftp.rb b/lib/chef/provider/remote_file/sftp.rb
index 530977e3c8..21c5c4ca04 100644
--- a/lib/chef/provider/remote_file/sftp.rb
+++ b/lib/chef/provider/remote_file/sftp.rb
@@ -68,9 +68,9 @@ class Chef
def validate_path!
path = uri.path.sub(%r{\A/}, "%2F") # re-encode the beginning slash because uri library decodes it.
directories = path.split(%r{/}, -1)
- directories.each {|d|
+ directories.each do |d|
d.gsub!(/%([0-9A-Fa-f][0-9A-Fa-f])/) { [$1].pack("H2") }
- }
+ end
unless filename = directories.pop
raise ArgumentError, "no filename: #{path.inspect}"
end
diff --git a/lib/chef/provider/service/debian.rb b/lib/chef/provider/service/debian.rb
index 67b71953f7..9d11032055 100644
--- a/lib/chef/provider/service/debian.rb
+++ b/lib/chef/provider/service/debian.rb
@@ -106,13 +106,13 @@ class Chef
def service_currently_enabled?(priority)
enabled = false
- priority.each { |runlevel, arguments|
+ priority.each do |runlevel, arguments|
Chef::Log.debug("#{new_resource} runlevel #{runlevel}, action #{arguments[0]}, priority #{arguments[1]}")
# if we are in a update-rc.d default startup runlevel && we start in this runlevel
if %w{ 1 2 3 4 5 S }.include?(runlevel) && arguments[0] == :start
enabled = true
end
- }
+ end
enabled
end
diff --git a/lib/chef/provider/service/simple.rb b/lib/chef/provider/service/simple.rb
index fe4768b2e8..d75e85989f 100644
--- a/lib/chef/provider/service/simple.rb
+++ b/lib/chef/provider/service/simple.rb
@@ -76,8 +76,9 @@ class Chef
end
requirements.assert(:all_actions) do |a|
- a.assertion { @new_resource.status_command || supports[:status] ||
- (!ps_cmd.nil? && !ps_cmd.empty?) }
+ a.assertion do
+ @new_resource.status_command || supports[:status] ||
+ (!ps_cmd.nil? && !ps_cmd.empty?) end
a.failure_message Chef::Exceptions::Service, "#{@new_resource} could not determine how to inspect the process table, please set this node's 'command.ps' attribute"
end
requirements.assert(:all_actions) do |a|
@@ -108,7 +109,7 @@ class Chef
shell_out_with_systems_locale!(@new_resource.reload_command)
end
- protected
+ protected
def determine_current_status!
if @new_resource.status_command
diff --git a/lib/chef/provider/service/solaris.rb b/lib/chef/provider/service/solaris.rb
index 1e5398eba8..868b3e1ac1 100644
--- a/lib/chef/provider/service/solaris.rb
+++ b/lib/chef/provider/service/solaris.rb
@@ -40,7 +40,7 @@ class Chef
@current_resource.service_name(@new_resource.service_name)
[@init_command, @status_command].each do |cmd|
- unless ::File.executable? cmd then
+ unless ::File.executable? cmd
raise Chef::Exceptions::Service, "#{cmd} not executable!"
end
end
diff --git a/lib/chef/provider/service/systemd.rb b/lib/chef/provider/service/systemd.rb
index 1597d46a3d..712f0f60c3 100644
--- a/lib/chef/provider/service/systemd.rb
+++ b/lib/chef/provider/service/systemd.rb
@@ -78,10 +78,10 @@ class Chef::Provider::Service::Systemd < Chef::Provider::Service::Simple
if new_resource.user
uid = node["etc"]["passwd"][new_resource.user]["uid"]
options = {
- "environment" => {
+ :environment => {
"DBUS_SESSION_BUS_ADDRESS" => "unix:path=/run/user/#{uid}/bus",
},
- "user" => new_resource.user,
+ :user => new_resource.user,
}
args = "--user"
else
diff --git a/lib/chef/provider/service/upstart.rb b/lib/chef/provider/service/upstart.rb
index 4acad768a4..941c4209dd 100644
--- a/lib/chef/provider/service/upstart.rb
+++ b/lib/chef/provider/service/upstart.rb
@@ -80,8 +80,11 @@ class Chef
shared_resource_requirements
requirements.assert(:all_actions) do |a|
if !@command_success
- whyrun_msg = @new_resource.status_command ? "Provided status command #{@new_resource.status_command} failed." :
- "Could not determine upstart state for service"
+ whyrun_msg = if @new_resource.status_command
+ "Provided status command #{@new_resource.status_command} failed."
+ else
+ "Could not determine upstart state for service"
+ end
end
a.assertion { @command_success }
# no failure here, just document the assumptions made.
@@ -116,7 +119,7 @@ class Chef
end
else
begin
- if upstart_state == "running"
+ if upstart_goal_state == "start"
@current_resource.running true
else
@current_resource.running false
@@ -224,7 +227,7 @@ class Chef
conf.write_file
end
- def upstart_state
+ def upstart_goal_state
command = "/sbin/status #{@job}"
status = popen4(command) do |pid, stdin, stdout, stderr|
stdout.each_line do |line|
@@ -235,7 +238,7 @@ class Chef
# service (goal) state
line =~ UPSTART_STATE_FORMAT
data = Regexp.last_match
- return data[2]
+ return data[1]
end
end
end
diff --git a/lib/chef/provider/support/yum_repo.erb b/lib/chef/provider/support/yum_repo.erb
new file mode 100644
index 0000000000..7d9a2d09e2
--- /dev/null
+++ b/lib/chef/provider/support/yum_repo.erb
@@ -0,0 +1,125 @@
+# This file was generated by Chef
+# Do NOT modify this file by hand.
+
+[<%= @config.repositoryid %>]
+name=<%= @config.description %>
+<% if @config.baseurl %>
+baseurl=<%= @config.baseurl %>
+<% end %>
+<% if @config.cost %>
+cost=<%= @config.cost %>
+<% end %>
+<% if @config.enabled %>
+enabled=1
+<% else %>
+enabled=0
+<% end %>
+<% if @config.enablegroups %>
+enablegroups=1
+<% end %>
+<% if @config.exclude %>
+exclude=<%= @config.exclude %>
+<% end %>
+<% if @config.failovermethod %>
+failovermethod=<%= @config.failovermethod %>
+<% end %>
+<% if @config.fastestmirror_enabled %>
+fastestmirror_enabled=<%= @config.fastestmirror_enabled %>
+<% end %>
+<% if @config.gpgcheck %>
+gpgcheck=1
+<% else %>
+gpgcheck=0
+<% end %>
+<% if @config.gpgkey %>
+gpgkey=<%= case @config.gpgkey
+ when Array
+ @config.gpgkey.join("\n ")
+ else
+ @config.gpgkey
+ end %>
+<% end -%>
+<% if @config.http_caching %>
+http_caching=<%= @config.http_caching %>
+<% end %>
+<% if @config.include_config %>
+include=<%= @config.include_config %>
+<% end %>
+<% if @config.includepkgs %>
+includepkgs=<%= @config.includepkgs %>
+<% end %>
+<% if @config.keepalive %>
+keepalive=1
+<% end %>
+<% if @config.metadata_expire %>
+metadata_expire=<%= @config.metadata_expire %>
+<% end %>
+<% if @config.mirrorlist %>
+mirrorlist=<%= @config.mirrorlist %>
+<% end %>
+<% if @config.mirror_expire %>
+mirror_expire=<%= @config.mirror_expire %>
+<% end %>
+<% if @config.mirrorlist_expire %>
+mirrorlist_expire=<%= @config.mirrorlist_expire %>
+<% end %>
+<% if @config.priority %>
+priority=<%= @config.priority %>
+<% end %>
+<% if @config.proxy %>
+proxy=<%= @config.proxy %>
+<% end %>
+<% if @config.proxy_username %>
+proxy_username=<%= @config.proxy_username %>
+<% end %>
+<% if @config.proxy_password %>
+proxy_password=<%= @config.proxy_password %>
+<% end %>
+<% if @config.username %>
+username=<%= @config.username %>
+<% end %>
+<% if @config.password %>
+password=<%= @config.password %>
+<% end %>
+<% if @config.repo_gpgcheck %>
+repo_gpgcheck=1
+<% end %>
+<% if @config.max_retries %>
+retries=<%= @config.max_retries %>
+<% end %>
+<% if @config.report_instanceid %>
+report_instanceid=<%= @config.report_instanceid %>
+<% end %>
+<% if @config.skip_if_unavailable %>
+skip_if_unavailable=1
+<% end %>
+<% if @config.sslcacert %>
+sslcacert=<%= @config.sslcacert %>
+<% end %>
+<% if @config.sslclientcert %>
+sslclientcert=<%= @config.sslclientcert %>
+<% end %>
+<% if @config.sslclientkey %>
+sslclientkey=<%= @config.sslclientkey %>
+<% end %>
+<% unless @config.sslverify.nil? %>
+sslverify=<%= ( @config.sslverify ) ? 'true' : 'false' %>
+<% end %>
+<% if @config.timeout %>
+timeout=<%= @config.timeout %>
+<% end %>
+<% if @config.options -%>
+<% @config.options.each do |key, value| -%>
+<%= key %>=<%=
+ case value
+ when Array
+ value.join("\n ")
+ when TrueClass
+ '1'
+ when FalseClass
+ '0'
+ else
+ value
+ end %>
+<% end -%>
+<% end -%>
diff --git a/lib/chef/provider/systemd_unit.rb b/lib/chef/provider/systemd_unit.rb
index b96a336765..4aa4cd0aa2 100644
--- a/lib/chef/provider/systemd_unit.rb
+++ b/lib/chef/provider/systemd_unit.rb
@@ -193,6 +193,7 @@ class Chef
f.group "root"
f.mode "0644"
f.content new_resource.to_ini
+ f.verify systemd_analyze_cmd if systemd_analyze_path
end.run_action(action)
end
@@ -224,8 +225,8 @@ class Chef
@systemctl_opts ||=
if new_resource.user
{
- "user" => new_resource.user,
- "environment" => {
+ :user => new_resource.user,
+ :environment => {
"DBUS_SESSION_BUS_ADDRESS" => "unix:path=/run/user/#{node['etc']['passwd'][new_resource.user]['uid']}/bus",
},
}
@@ -233,6 +234,14 @@ class Chef
{}
end
end
+
+ def systemd_analyze_cmd
+ @systemd_analyze_cmd ||= "#{systemd_analyze_path} verify %{path}"
+ end
+
+ def systemd_analyze_path
+ @systemd_analyze_path ||= which("systemd-analyze")
+ end
end
end
end
diff --git a/lib/chef/provider/template_finder.rb b/lib/chef/provider/template_finder.rb
index 67342a86ea..1e8b925071 100644
--- a/lib/chef/provider/template_finder.rb
+++ b/lib/chef/provider/template_finder.rb
@@ -40,7 +40,7 @@ class Chef
cookbook.preferred_filename_on_disk_location(@node, :templates, template_name)
end
- protected
+ protected
def template_source_name(name, options)
if options[:source]
diff --git a/lib/chef/provider/user.rb b/lib/chef/provider/user.rb
index 85bd674d8d..2bc4cc10bc 100644
--- a/lib/chef/provider/user.rb
+++ b/lib/chef/provider/user.rb
@@ -147,10 +147,6 @@ class Chef
end
end
- def remove_user
- raise NotImplementedError
- end
-
def action_manage
if @user_exists && compare_user
converge_by("manage user #{@new_resource.username}") do
@@ -160,10 +156,6 @@ class Chef
end
end
- def manage_user
- raise NotImplementedError
- end
-
def action_modify
if compare_user
converge_by("modify user #{@new_resource.username}") do
@@ -184,14 +176,6 @@ class Chef
end
end
- def check_lock
- raise NotImplementedError
- end
-
- def lock_user
- raise NotImplementedError
- end
-
def action_unlock
if check_lock() == true
converge_by("unlock user #{@new_resource.username}") do
@@ -203,9 +187,29 @@ class Chef
end
end
+ def create_user
+ raise NotImplementedError
+ end
+
+ def remove_user
+ raise NotImplementedError
+ end
+
+ def manage_user
+ raise NotImplementedError
+ end
+
+ def lock_user
+ raise NotImplementedError
+ end
+
def unlock_user
raise NotImplementedError
end
+
+ def check_lock
+ raise NotImplementedError
+ end
end
end
end
diff --git a/lib/chef/provider/user/aix.rb b/lib/chef/provider/user/aix.rb
index 3f168b8da3..8ac229ae4d 100644
--- a/lib/chef/provider/user/aix.rb
+++ b/lib/chef/provider/user/aix.rb
@@ -14,11 +14,14 @@
# See the License for the specific language governing permissions and
# limitations under the License.
+require "chef/provider/user/useradd"
+
class Chef
class Provider
class User
class Aix < Chef::Provider::User::Useradd
- provides :user, platform: %w{aix}
+ provides :user, os: "aix"
+ provides :aix_user
UNIVERSAL_OPTIONS = [[:comment, "-c"], [:gid, "-g"], [:shell, "-s"], [:uid, "-u"]]
@@ -66,7 +69,7 @@ class Chef
shell_out!("chuser account_locked=false #{new_resource.username}")
end
- private
+ private
def add_password
if @current_resource.password != @new_resource.password && @new_resource.password
diff --git a/lib/chef/provider/user/dscl.rb b/lib/chef/provider/user/dscl.rb
index e933bf9dc0..821fa8e8a7 100644
--- a/lib/chef/provider/user/dscl.rb
+++ b/lib/chef/provider/user/dscl.rb
@@ -48,6 +48,7 @@ class Chef
attr_accessor :authentication_authority
attr_accessor :password_shadow_conversion_algorithm
+ provides :dscl_user
provides :user, os: "darwin"
def define_resource_requirements
diff --git a/lib/chef/provider/user/linux.rb b/lib/chef/provider/user/linux.rb
new file mode 100644
index 0000000000..f09d86e98c
--- /dev/null
+++ b/lib/chef/provider/user/linux.rb
@@ -0,0 +1,128 @@
+#
+# Copyright:: Copyright 2016, Chef Software 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/provider/user"
+
+class Chef
+ class Provider
+ class User
+ class Linux < Chef::Provider::User
+ provides :linux_user
+ provides :user, os: "linux"
+
+ def create_user
+ shell_out!(*clean_array("useradd", universal_options, useradd_options, new_resource.username))
+ end
+
+ def manage_user
+ shell_out!(*clean_array("usermod", universal_options, usermod_options, new_resource.username))
+ end
+
+ def remove_user
+ shell_out!(*clean_array("userdel", userdel_options, new_resource.username))
+ end
+
+ def lock_user
+ shell_out!(*clean_array("usermod", "-L", new_resource.username))
+ end
+
+ def unlock_user
+ shell_out!(*clean_array("usermod", "-U", new_resource.username))
+ end
+
+ # common to usermod and useradd
+ def universal_options
+ opts = []
+ opts << "-c" << new_resource.comment if should_set?(:comment)
+ opts << "-g" << new_resource.gid if should_set?(:gid)
+ opts << "-p" << new_resource.password if should_set?(:password)
+ opts << "-s" << new_resource.shell if should_set?(:shell)
+ opts << "-u" << new_resource.uid if should_set?(:uid)
+ opts << "-d" << new_resource.home if updating_home?
+ opts << "-o" if new_resource.non_unique
+ opts
+ end
+
+ def usermod_options
+ opts = []
+ if updating_home?
+ if new_resource.manage_home
+ opts << "-m"
+ end
+ end
+ opts
+ end
+
+ def useradd_options
+ opts = []
+ opts << "-r" if new_resource.system
+ if new_resource.manage_home
+ opts << "-m"
+ else
+ opts << "-M"
+ end
+ opts
+ end
+
+ def userdel_options
+ opts = []
+ opts << "-r" if new_resource.manage_home
+ opts << "-f" if new_resource.force
+ opts
+ end
+
+ def should_set?(sym)
+ current_resource.send(sym).to_s != new_resource.send(sym).to_s && new_resource.send(sym)
+ end
+
+ def updating_home?
+ return false unless new_resource.home
+ return true unless current_resource.home
+ new_resource.home && Pathname.new(current_resource.home).cleanpath != Pathname.new(new_resource.home).cleanpath
+ end
+
+ def check_lock
+ # there's an old bug in rhel (https://bugzilla.redhat.com/show_bug.cgi?id=578534)
+ # which means that both 0 and 1 can be success.
+ passwd_s = shell_out("passwd", "-S", new_resource.username, returns: [ 0, 1 ])
+
+ # checking "does not exist" has to come before exit code handling since centos and ubuntu differ in exit codes
+ if passwd_s.stderr =~ /does not exist/
+ if whyrun_mode?
+ return false
+ else
+ raise Chef::Exceptions::User, "User #{new_resource.username} does not exist when checking lock status for #{new_resource}"
+ end
+ end
+
+ # now raise if we didn't get a 0 or 1 (see above)
+ passwd_s.error!
+
+ # now the actual output parsing
+ @locked = nil
+ status_line = passwd_s.stdout.split(" ")
+ @locked = false if status_line[1] =~ /^[PN]/
+ @locked = true if status_line[1] =~ /^L/
+
+ raise Chef::Exceptions::User, "Cannot determine if user #{new_resource.username} is locked for #{new_resource}" if @locked.nil?
+
+ # FIXME: should probably go on the current_resource
+ @locked
+ end
+ end
+ end
+ end
+end
diff --git a/lib/chef/provider/user/pw.rb b/lib/chef/provider/user/pw.rb
index 949a21790b..a1d7671c28 100644
--- a/lib/chef/provider/user/pw.rb
+++ b/lib/chef/provider/user/pw.rb
@@ -22,7 +22,8 @@ class Chef
class Provider
class User
class Pw < Chef::Provider::User
- provides :user, platform: %w{freebsd}
+ provides :pw_user
+ provides :user, os: "freebsd"
def load_current_resource
super
diff --git a/lib/chef/provider/user/solaris.rb b/lib/chef/provider/user/solaris.rb
index 1f0cbb6054..8d3df9e68b 100644
--- a/lib/chef/provider/user/solaris.rb
+++ b/lib/chef/provider/user/solaris.rb
@@ -24,7 +24,8 @@ class Chef
class Provider
class User
class Solaris < Chef::Provider::User::Useradd
- provides :user, platform: %w{omnios solaris2}
+ provides :solaris_user
+ provides :user, os: %w{omnios solaris2}
UNIVERSAL_OPTIONS = [[:comment, "-c"], [:gid, "-g"], [:shell, "-s"], [:uid, "-u"]]
attr_writer :password_file
@@ -70,7 +71,7 @@ class Chef
shell_out!("passwd", "-u", new_resource.username)
end
- private
+ private
def manage_password
if @current_resource.password != @new_resource.password && @new_resource.password
diff --git a/lib/chef/provider/user/useradd.rb b/lib/chef/provider/user/useradd.rb
index 3fef8d3642..68b62812a7 100644
--- a/lib/chef/provider/user/useradd.rb
+++ b/lib/chef/provider/user/useradd.rb
@@ -23,7 +23,7 @@ class Chef
class Provider
class User
class Useradd < Chef::Provider::User
- provides :user
+ # MAJOR XXX: this should become the base class of all Useradd providers instead of the linux implementation
UNIVERSAL_OPTIONS = [[:comment, "-c"], [:gid, "-g"], [:password, "-p"], [:shell, "-s"], [:uid, "-u"]]
@@ -116,15 +116,15 @@ class Chef
update_options(field, option, opts)
end
if updating_home?
+ opts << "-d" << new_resource.home
if managing_home_dir?
Chef::Log.debug("#{new_resource} managing the users home directory")
- opts << "-d" << new_resource.home << "-m"
+ opts << "-m"
else
Chef::Log.debug("#{new_resource} setting home to #{new_resource.home}")
- opts << "-d" << new_resource.home
end
end
- opts << "-o" if new_resource.non_unique || new_resource.supports[:non_unique]
+ opts << "-o" if new_resource.non_unique
opts
end
end
@@ -141,6 +141,7 @@ class Chef
def useradd_options
opts = []
opts << "-r" if new_resource.system
+ opts << "-M" unless managing_home_dir?
opts
end
diff --git a/lib/chef/provider/user/windows.rb b/lib/chef/provider/user/windows.rb
index 9545b1fd59..b086a1e32b 100644
--- a/lib/chef/provider/user/windows.rb
+++ b/lib/chef/provider/user/windows.rb
@@ -26,7 +26,7 @@ class Chef
class Provider
class User
class Windows < Chef::Provider::User
-
+ provides :windows_user
provides :user, os: "windows"
def initialize(new_resource, run_context)
diff --git a/lib/chef/provider/windows_script.rb b/lib/chef/provider/windows_script.rb
index 2de127addf..3b0202790c 100644
--- a/lib/chef/provider/windows_script.rb
+++ b/lib/chef/provider/windows_script.rb
@@ -33,8 +33,11 @@ class Chef
super( new_resource, run_context )
@script_extension = script_extension
- target_architecture = new_resource.architecture.nil? ?
- node_windows_architecture(run_context.node) : new_resource.architecture
+ target_architecture = if new_resource.architecture.nil?
+ node_windows_architecture(run_context.node)
+ else
+ new_resource.architecture
+ end
@is_wow64 = wow64_architecture_override_required?(run_context.node, target_architecture)
diff --git a/lib/chef/provider/yum_repository.rb b/lib/chef/provider/yum_repository.rb
new file mode 100644
index 0000000000..09ff2c5512
--- /dev/null
+++ b/lib/chef/provider/yum_repository.rb
@@ -0,0 +1,121 @@
+#
+# Author:: Thom May (<thom@chef.io>)
+# Copyright:: Copyright (c) 2016 Chef Software, 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"
+require "chef/dsl/declare_resource"
+require "chef/mixin/shell_out"
+require "chef/mixin/which"
+require "chef/http/simple"
+require "chef/provider/noop"
+
+class Chef
+ class Provider
+ class YumRepository < Chef::Provider
+ use_inline_resources
+
+ extend Chef::Mixin::Which
+
+ provides :yum_repository do
+ which "yum"
+ end
+
+ def whyrun_supported?; true; end
+
+ def load_current_resource; end
+
+ action :create do
+ declare_resource(:template, "/etc/yum.repos.d/#{new_resource.repositoryid}.repo") do
+ if template_available?(new_resource.source)
+ source new_resource.source
+ else
+ source ::File.expand_path("../support/yum_repo.erb", __FILE__)
+ local true
+ end
+ sensitive new_resource.sensitive
+ variables(config: new_resource)
+ mode new_resource.mode
+ if new_resource.make_cache
+ notifies :run, "execute[yum clean metadata #{new_resource.repositoryid}]", :immediately if new_resource.clean_metadata || new_resource.clean_headers
+ notifies :run, "execute[yum-makecache-#{new_resource.repositoryid}]", :immediately
+ notifies :create, "ruby_block[yum-cache-reload-#{new_resource.repositoryid}]", :immediately
+ end
+ end
+
+ declare_resource(:execute, "yum clean metadata #{new_resource.repositoryid}") do
+ command "yum clean metadata --disablerepo=* --enablerepo=#{new_resource.repositoryid}"
+ action :nothing
+ end
+
+ # get the metadata for this repo only
+ declare_resource(:execute, "yum-makecache-#{new_resource.repositoryid}") do
+ command "yum -q -y makecache --disablerepo=* --enablerepo=#{new_resource.repositoryid}"
+ action :nothing
+ only_if { new_resource.enabled }
+ end
+
+ # reload internal Chef yum cache
+ declare_resource(:ruby_block, "yum-cache-reload-#{new_resource.repositoryid}") do
+ block { Chef::Provider::Package::Yum::YumCache.instance.reload }
+ action :nothing
+ end
+ end
+
+ action :delete do
+ declare_resource(:file, "/etc/yum.repos.d/#{new_resource.repositoryid}.repo") do
+ action :delete
+ notifies :run, "execute[yum clean all #{new_resource.repositoryid}]", :immediately
+ notifies :create, "ruby_block[yum-cache-reload-#{new_resource.repositoryid}]", :immediately
+ end
+
+ declare_resource(:execute, "yum clean all #{new_resource.repositoryid}") do
+ command "yum clean all --disablerepo=* --enablerepo=#{new_resource.repositoryid}"
+ only_if "yum repolist | grep -P '^#{new_resource.repositoryid}([ \t]|$)'"
+ action :nothing
+ end
+
+ declare_resource(:ruby_block, "yum-cache-reload-#{new_resource.repositoryid}") do
+ block { Chef::Provider::Package::Yum::YumCache.instance.reload }
+ action :nothing
+ end
+ end
+
+ action :makecache do
+ declare_resource(:execute, "yum-makecache-#{new_resource.repositoryid}") do
+ command "yum -q -y makecache --disablerepo=* --enablerepo=#{new_resource.repositoryid}"
+ action :run
+ only_if { new_resource.enabled }
+ end
+
+ declare_resource(:ruby_block, "yum-cache-reload-#{new_resource.repositoryid}") do
+ block { Chef::Provider::Package::Yum::YumCache.instance.reload }
+ action :run
+ end
+ end
+
+ alias_method :action_add, :action_create
+ alias_method :action_remove, :action_delete
+
+ def template_available?(path)
+ !path.nil? && run_context.has_template_in_cookbook?(new_resource.cookbook_name, path)
+ end
+
+ end
+ end
+end
+
+Chef::Provider::Noop.provides :yum_repository
diff --git a/lib/chef/providers.rb b/lib/chef/providers.rb
index 14c47df939..affa5ca2c1 100644
--- a/lib/chef/providers.rb
+++ b/lib/chef/providers.rb
@@ -58,6 +58,7 @@ require "chef/provider/systemd_unit"
require "chef/provider/template"
require "chef/provider/user"
require "chef/provider/whyrun_safe_ruby_block"
+require "chef/provider/yum_repository"
require "chef/provider/env/windows"
@@ -101,12 +102,13 @@ require "chef/provider/service/macosx"
require "chef/provider/service/aixinit"
require "chef/provider/service/aix"
+require "chef/provider/user/aix"
require "chef/provider/user/dscl"
+require "chef/provider/user/linux"
require "chef/provider/user/pw"
+require "chef/provider/user/solaris"
require "chef/provider/user/useradd"
require "chef/provider/user/windows"
-require "chef/provider/user/solaris"
-require "chef/provider/user/aix"
require "chef/provider/group/aix"
require "chef/provider/group/dscl"
diff --git a/lib/chef/recipe.rb b/lib/chef/recipe.rb
index 3cc5634dc8..77d82f83ab 100644
--- a/lib/chef/recipe.rb
+++ b/lib/chef/recipe.rb
@@ -18,16 +18,7 @@
#
require "chef/dsl/recipe"
-require "chef/dsl/data_query"
-require "chef/dsl/platform_introspection"
-require "chef/dsl/include_recipe"
-require "chef/dsl/registry_helper"
-require "chef/dsl/reboot_pending"
-require "chef/dsl/audit"
-require "chef/dsl/powershell"
-
require "chef/mixin/from_file"
-
require "chef/mixin/deprecation"
class Chef
diff --git a/lib/chef/resource.rb b/lib/chef/resource.rb
index 479eb0a7e2..d11fa1c80c 100644
--- a/lib/chef/resource.rb
+++ b/lib/chef/resource.rb
@@ -497,7 +497,7 @@ class Chef
state_properties = self.class.state_properties
state_properties.each do |property|
if property.identity? || property.is_set?(self)
- state[property.name] = send(property.name)
+ state[property.name] = property.sensitive? ? "*sensitive value suppressed*" : send(property.name)
end
end
state
@@ -1276,15 +1276,15 @@ class Chef
# resolve_resource_reference on each in turn, causing them to
# resolve lazy/forward references.
def resolve_notification_references
- run_context.before_notifications(self).each { |n|
+ run_context.before_notifications(self).each do |n|
n.resolve_resource_reference(run_context.resource_collection)
- }
- run_context.immediate_notifications(self).each { |n|
+ end
+ run_context.immediate_notifications(self).each do |n|
n.resolve_resource_reference(run_context.resource_collection)
- }
- run_context.delayed_notifications(self).each {|n|
+ end
+ run_context.delayed_notifications(self).each do |n|
n.resolve_resource_reference(run_context.resource_collection)
- }
+ end
end
# Helper for #notifies
@@ -1575,8 +1575,6 @@ class Chef
end
end
- private
-
def self.remove_canonical_dsl
if @resource_name
remaining = Chef.resource_handler_map.delete_canonical(@resource_name, self)
diff --git a/lib/chef/resource/conditional.rb b/lib/chef/resource/conditional.rb
index cdb9f13c45..452718cae8 100644
--- a/lib/chef/resource/conditional.rb
+++ b/lib/chef/resource/conditional.rb
@@ -103,7 +103,15 @@ class Chef
end
def evaluate_block
- @block.call
+ @block.call.tap do |rv|
+ if rv.is_a?(String) && !rv.empty?
+ # This is probably a mistake:
+ # not_if { "command" }
+ sanitized_rv = @parent_resource.sensitive ? "a string" : rv.inspect
+ Chef::Log.warn("#{@positivity} block for #{@parent_resource} returned #{sanitized_rv}, did you mean to run a command?" +
+ (@parent_resource.sensitive ? "" : " If so use '#{@positivity} #{sanitized_rv}' in your code."))
+ end
+ end
end
def short_description
diff --git a/lib/chef/resource/freebsd_package.rb b/lib/chef/resource/freebsd_package.rb
index 540774e864..a94dd0a928 100644
--- a/lib/chef/resource/freebsd_package.rb
+++ b/lib/chef/resource/freebsd_package.rb
@@ -45,7 +45,7 @@ class Chef
def ships_with_pkgng?
# It was not until __FreeBSD_version 1000017 that pkgng became
# the default binary package manager. See '/usr/ports/Mk/bsd.port.mk'.
- node.automatic[:os_version].to_i >= 1000017
+ node[:os_version].to_i >= 1000017
end
def assign_provider
diff --git a/lib/chef/resource/launchd.rb b/lib/chef/resource/launchd.rb
index f3c378a6a8..8dca90ef0e 100644
--- a/lib/chef/resource/launchd.rb
+++ b/lib/chef/resource/launchd.rb
@@ -68,7 +68,7 @@ class Chef
property :hard_resource_limits, Hash
property :inetd_compatibility, Hash
property :init_groups, [ TrueClass, FalseClass ]
- property :keep_alive, [ TrueClass, FalseClass ]
+ property :keep_alive, [ TrueClass, FalseClass, Hash ]
property :launch_only_once, [ TrueClass, FalseClass ]
property :ld_group, String
property :limit_load_from_hosts, Array
diff --git a/lib/chef/resource/user.rb b/lib/chef/resource/user.rb
index 012fa278f1..a07ce8b24b 100644
--- a/lib/chef/resource/user.rb
+++ b/lib/chef/resource/user.rb
@@ -21,6 +21,7 @@ require "chef/resource"
class Chef
class Resource
class User < Chef::Resource
+ resource_name :user_resource_abstract_base_class # this prevents magickal class name DSL wiring
identity_attr :username
state_attrs :uid, :gid, :home
@@ -42,8 +43,8 @@ class Chef
@force = false
@non_unique = false
@supports = {
- :manage_home => false,
- :non_unique => false,
+ manage_home: false,
+ non_unique: false,
}
@iterations = 27855
@salt = nil
@@ -154,7 +155,6 @@ class Chef
:kind_of => [ TrueClass, FalseClass ]
)
end
-
end
end
end
diff --git a/lib/chef/resource/user/aix_user.rb b/lib/chef/resource/user/aix_user.rb
new file mode 100644
index 0000000000..7c07db2e25
--- /dev/null
+++ b/lib/chef/resource/user/aix_user.rb
@@ -0,0 +1,31 @@
+#
+# Copyright:: Copyright 2016, Chef Software 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/user"
+
+class Chef
+ class Resource
+ class User
+ class AixUser < Chef::Resource::User
+ resource_name :aix_user
+
+ provides :aix_user
+ provides :user, os: "aix"
+ end
+ end
+ end
+end
diff --git a/lib/chef/resource/user/dscl_user.rb b/lib/chef/resource/user/dscl_user.rb
new file mode 100644
index 0000000000..61517d8b44
--- /dev/null
+++ b/lib/chef/resource/user/dscl_user.rb
@@ -0,0 +1,31 @@
+#
+# Copyright:: Copyright 2016, Chef Software 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/user"
+
+class Chef
+ class Resource
+ class User
+ class DsclUser < Chef::Resource::User
+ resource_name :dscl_user
+
+ provides :dscl_user
+ provides :user, os: "darwin"
+ end
+ end
+ end
+end
diff --git a/lib/chef/resource/user/linux_user.rb b/lib/chef/resource/user/linux_user.rb
new file mode 100644
index 0000000000..23d6129373
--- /dev/null
+++ b/lib/chef/resource/user/linux_user.rb
@@ -0,0 +1,51 @@
+#
+# Copyright:: Copyright 2016, Chef Software 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/user"
+
+class Chef
+ class Resource
+ class User
+ class LinuxUser < Chef::Resource::User
+ resource_name :linux_user
+
+ provides :linux_user
+ provides :user, os: "linux"
+
+ def initialize(name, run_context = nil)
+ super
+ @supports = {
+ manage_home: true,
+ non_unique: true,
+ }
+ @manage_home = false
+ end
+
+ def supports(args = {})
+ Chef.log_deprecation "setting supports on the linux_user resource is deprecated"
+ # setting is deliberately disabled
+ super({})
+ end
+
+ def supports=(args)
+ # setting is deliberately disabled
+ supports({})
+ end
+ end
+ end
+ end
+end
diff --git a/lib/chef/resource/user/pw_user.rb b/lib/chef/resource/user/pw_user.rb
new file mode 100644
index 0000000000..873be19d59
--- /dev/null
+++ b/lib/chef/resource/user/pw_user.rb
@@ -0,0 +1,31 @@
+#
+# Copyright:: Copyright 2016, Chef Software 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/user"
+
+class Chef
+ class Resource
+ class User
+ class PwUser < Chef::Resource::User
+ resource_name :pw_user
+
+ provides :pw_user
+ provides :user, os: "freebsd"
+ end
+ end
+ end
+end
diff --git a/lib/chef/resource/user/solaris_user.rb b/lib/chef/resource/user/solaris_user.rb
new file mode 100644
index 0000000000..bb897228b9
--- /dev/null
+++ b/lib/chef/resource/user/solaris_user.rb
@@ -0,0 +1,31 @@
+#
+# Copyright:: Copyright 2016, Chef Software 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/user"
+
+class Chef
+ class Resource
+ class User
+ class SolarisUser < Chef::Resource::User
+ resource_name :solaris_user
+
+ provides :solaris_user
+ provides :user, os: %w{omnios solaris2}
+ end
+ end
+ end
+end
diff --git a/lib/chef/resource/user/windows_user.rb b/lib/chef/resource/user/windows_user.rb
new file mode 100644
index 0000000000..d1a249fb50
--- /dev/null
+++ b/lib/chef/resource/user/windows_user.rb
@@ -0,0 +1,31 @@
+#
+# Copyright:: Copyright 2016, Chef Software 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/user"
+
+class Chef
+ class Resource
+ class User
+ class WindowsUser < Chef::Resource::User
+ resource_name :windows_user
+
+ provides :windows_user
+ provides :user, os: "windows"
+ end
+ end
+ end
+end
diff --git a/lib/chef/resource/yum_package.rb b/lib/chef/resource/yum_package.rb
index 1f749b93c0..9d69897f5f 100644
--- a/lib/chef/resource/yum_package.rb
+++ b/lib/chef/resource/yum_package.rb
@@ -27,18 +27,19 @@ class Chef
# Install a specific arch
property :arch, [ String, Array ]
- property :flush_cache, Hash, default: { before: false, after: false }, coerce: proc { |v|
- # TODO these append rather than set. This is probably wrong behavior, but we're preserving it until we know
- if v.is_a?(Array)
- v.each { |arg| flush_cache[arg] = true }
- flush_cache
- elsif v.any?
- v
- else
- # TODO calling flush_cache({}) does a get instead of a set. This is probably wrong behavior, but we're preserving it until we know
- flush_cache
- end
- }
+ # the {} on the proc here is because rspec chokes if it's do...end
+ property :flush_cache,
+ Hash,
+ default: { before: false, after: false },
+ coerce: proc { |v|
+ if v.is_a?(Array)
+ v.each_with_object({}) { |arg, obj| obj[arg] = true }
+ elsif v.any?
+ v
+ else
+ { before: v, after: v }
+ end
+ }
property :allow_downgrade, [ true, false ], default: false
property :yum_binary, String
diff --git a/lib/chef/resource/yum_repository.rb b/lib/chef/resource/yum_repository.rb
new file mode 100644
index 0000000000..4b3c6edfb7
--- /dev/null
+++ b/lib/chef/resource/yum_repository.rb
@@ -0,0 +1,76 @@
+#
+# Author:: Thom May (<thom@chef.io>)
+# Copyright:: Copyright (c) 2016 Chef Software, 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"
+
+class Chef
+ class Resource
+ class YumRepository < Chef::Resource
+ resource_name :yum_repository
+ provides :yum_repository
+
+ # http://linux.die.net/man/5/yum.conf
+ property :baseurl, String, regex: /.*/
+ property :cost, String, regex: /^\d+$/
+ property :clean_headers, [TrueClass, FalseClass], default: false # deprecated
+ property :clean_metadata, [TrueClass, FalseClass], default: true
+ property :description, String, regex: /.*/, default: "Ye Ole Rpm Repo"
+ property :enabled, [TrueClass, FalseClass], default: true
+ property :enablegroups, [TrueClass, FalseClass]
+ property :exclude, String, regex: /.*/
+ property :failovermethod, String, equal_to: %w{priority roundrobin}
+ property :fastestmirror_enabled, [TrueClass, FalseClass]
+ property :gpgcheck, [TrueClass, FalseClass]
+ property :gpgkey, [String, Array], regex: /.*/
+ property :http_caching, String, equal_to: %w{packages all none}
+ property :include_config, String, regex: /.*/
+ property :includepkgs, String, regex: /.*/
+ property :keepalive, [TrueClass, FalseClass]
+ property :make_cache, [TrueClass, FalseClass], default: true
+ property :max_retries, [String, Integer]
+ property :metadata_expire, String, regex: [/^\d+$/, /^\d+[mhd]$/, /never/]
+ property :mirrorexpire, String, regex: /.*/
+ property :mirrorlist, String, regex: /.*/
+ property :mirror_expire, String, regex: [/^\d+$/, /^\d+[mhd]$/]
+ property :mirrorlist_expire, String, regex: [/^\d+$/, /^\d+[mhd]$/]
+ property :mode, default: "0644"
+ property :priority, String, regex: /^(\d?[0-9]|[0-9][0-9])$/
+ property :proxy, String, regex: /.*/
+ property :proxy_username, String, regex: /.*/
+ property :proxy_password, String, regex: /.*/
+ property :username, String, regex: /.*/
+ property :password, String, regex: /.*/
+ property :repo_gpgcheck, [TrueClass, FalseClass]
+ property :report_instanceid, [TrueClass, FalseClass]
+ property :repositoryid, String, regex: /.*/, name_attribute: true
+ property :sensitive, [TrueClass, FalseClass], default: false
+ property :skip_if_unavailable, [TrueClass, FalseClass]
+ property :source, String, regex: /.*/
+ property :sslcacert, String, regex: /.*/
+ property :sslclientcert, String, regex: /.*/
+ property :sslclientkey, String, regex: /.*/
+ property :sslverify, [TrueClass, FalseClass]
+ property :timeout, String, regex: /^\d+$/
+
+ property :options, Hash
+
+ default_action :create
+ allowed_actions :create, :remove, :make_cache, :add
+ end
+ end
+end
diff --git a/lib/chef/resource_builder.rb b/lib/chef/resource_builder.rb
index 1641fe60f2..57c57dd8c3 100644
--- a/lib/chef/resource_builder.rb
+++ b/lib/chef/resource_builder.rb
@@ -31,7 +31,7 @@ class Chef
attr_reader :resource
# FIXME (ruby-2.1 syntax): most of these are mandatory
- def initialize(type:nil, name:nil, created_at: nil, params: nil, run_context: nil, cookbook_name: nil, recipe_name: nil, enclosing_provider: nil)
+ def initialize(type: nil, name: nil, created_at: nil, params: nil, run_context: nil, cookbook_name: nil, recipe_name: nil, enclosing_provider: nil)
@type = type
@name = name
@created_at = created_at
diff --git a/lib/chef/resource_collection/stepable_iterator.rb b/lib/chef/resource_collection/stepable_iterator.rb
index d1165764ca..958ffa28cb 100644
--- a/lib/chef/resource_collection/stepable_iterator.rb
+++ b/lib/chef/resource_collection/stepable_iterator.rb
@@ -100,9 +100,7 @@ class Chef
end
def iterate
- while @position < size && !paused?
- step
- end
+ step while @position < size && !paused?
collection
end
diff --git a/lib/chef/resource_reporter.rb b/lib/chef/resource_reporter.rb
index 4135483441..8422870e2a 100644
--- a/lib/chef/resource_reporter.rb
+++ b/lib/chef/resource_reporter.rb
@@ -26,11 +26,11 @@ require "chef/event_dispatch/base"
class Chef
class ResourceReporter < EventDispatch::Base
- class ResourceReport < Struct.new(:new_resource,
- :current_resource,
- :action,
- :exception,
- :elapsed_time)
+ ResourceReport = Struct.new(:new_resource,
+ :current_resource,
+ :action,
+ :exception,
+ :elapsed_time) do
def self.new_with_current_state(new_resource, action, current_resource)
report = new
diff --git a/lib/chef/resources.rb b/lib/chef/resources.rb
index af9c918f55..2afd47a8f4 100644
--- a/lib/chef/resources.rb
+++ b/lib/chef/resources.rb
@@ -82,9 +82,16 @@ require "chef/resource/smartos_package"
require "chef/resource/template"
require "chef/resource/timestamped_deploy"
require "chef/resource/user"
+require "chef/resource/user/aix_user"
+require "chef/resource/user/dscl_user"
+require "chef/resource/user/linux_user"
+require "chef/resource/user/pw_user"
+require "chef/resource/user/solaris_user"
+require "chef/resource/user/windows_user"
require "chef/resource/whyrun_safe_ruby_block"
require "chef/resource/windows_package"
require "chef/resource/yum_package"
+require "chef/resource/yum_repository"
require "chef/resource/lwrp_base"
require "chef/resource/bff_package"
require "chef/resource/zypper_package"
diff --git a/lib/chef/run_context.rb b/lib/chef/run_context.rb
index 7ef476c44b..5d29f766c9 100644
--- a/lib/chef/run_context.rb
+++ b/lib/chef/run_context.rb
@@ -658,9 +658,11 @@ ERROR_MESSAGE
}.map { |x| x.to_sym }
# Verify that we didn't miss any methods
- missing_methods = superclass.instance_methods(false) - instance_methods(false) - CHILD_STATE
- if !missing_methods.empty?
- raise "ERROR: not all methods of RunContext accounted for in ChildRunContext! All methods must be marked as child methods with CHILD_STATE or delegated to the parent_run_context. Missing #{missing_methods.join(", ")}."
+ unless @__skip_method_checking # hook specifically for compat_resource
+ missing_methods = superclass.instance_methods(false) - instance_methods(false) - CHILD_STATE
+ if !missing_methods.empty?
+ raise "ERROR: not all methods of RunContext accounted for in ChildRunContext! All methods must be marked as child methods with CHILD_STATE or delegated to the parent_run_context. Missing #{missing_methods.join(", ")}."
+ end
end
end
end
diff --git a/lib/chef/run_context/cookbook_compiler.rb b/lib/chef/run_context/cookbook_compiler.rb
index bdf3a1251c..b2a8d236a3 100644
--- a/lib/chef/run_context/cookbook_compiler.rb
+++ b/lib/chef/run_context/cookbook_compiler.rb
@@ -137,13 +137,14 @@ class Chef
@events.recipe_load_start(run_list_expansion.recipes.size)
run_list_expansion.recipes.each do |recipe|
begin
+ path = resolve_recipe(recipe)
@run_context.load_recipe(recipe)
+ @events.recipe_file_loaded(path, recipe)
rescue Chef::Exceptions::RecipeNotFound => e
@events.recipe_not_found(e)
raise
rescue Exception => e
- path = resolve_recipe(recipe)
- @events.recipe_file_load_failed(path, e)
+ @events.recipe_file_load_failed(path, e, recipe)
raise
end
end
diff --git a/lib/chef/run_list.rb b/lib/chef/run_list.rb
index 4dea938423..3ac5fab07b 100644
--- a/lib/chef/run_list.rb
+++ b/lib/chef/run_list.rb
@@ -47,13 +47,13 @@ class Chef
end
def role_names
- @run_list_items.inject([]) { |memo, run_list_item| memo << run_list_item.name if run_list_item.role? ; memo }
+ @run_list_items.inject([]) { |memo, run_list_item| memo << run_list_item.name if run_list_item.role?; memo }
end
alias :roles :role_names
def recipe_names
- @run_list_items.inject([]) { |memo, run_list_item| memo << run_list_item.name if run_list_item.recipe? ; memo }
+ @run_list_items.inject([]) { |memo, run_list_item| memo << run_list_item.name if run_list_item.recipe?; memo }
end
alias :recipes :recipe_names
diff --git a/lib/chef/search/query.rb b/lib/chef/search/query.rb
index ebf13bec36..bea8205935 100644
--- a/lib/chef/search/query.rb
+++ b/lib/chef/search/query.rb
@@ -21,6 +21,7 @@ require "chef/exceptions"
require "chef/server_api"
require "uri"
+require "addressable/uri"
class Chef
class Search
@@ -29,7 +30,7 @@ class Chef
attr_accessor :rest
attr_reader :config
- def initialize(url = nil, config:Chef::Config)
+ def initialize(url = nil, config: Chef::Config)
@config = config
@url = url
end
@@ -134,19 +135,21 @@ WARNDEP
args_h
end
- def escape(s)
- s && URI.escape(s.to_s)
+ QUERY_PARAM_VALUE = Addressable::URI::CharacterClasses::QUERY + "\\&\\;"
+
+ def escape_value(s)
+ s && Addressable::URI.encode_component(s.to_s, QUERY_PARAM_VALUE)
end
def create_query_string(type, query, rows, start, sort)
- qstr = "search/#{type}?q=#{escape(query)}"
- qstr += "&sort=#{escape(sort)}" if sort
- qstr += "&start=#{escape(start)}" if start
- qstr += "&rows=#{escape(rows)}" if rows
+ qstr = "search/#{type}?q=#{escape_value(query)}"
+ qstr += "&sort=#{escape_value(sort)}" if sort
+ qstr += "&start=#{escape_value(start)}" if start
+ qstr += "&rows=#{escape_value(rows)}" if rows
qstr
end
- def call_rest_service(type, query:"*:*", rows:nil, start:0, sort:"X_CHEF_id_CHEF_X asc", filter_result:nil)
+ def call_rest_service(type, query: "*:*", rows: nil, start: 0, sort: "X_CHEF_id_CHEF_X asc", filter_result: nil)
query_string = create_query_string(type, query, rows, start, sort)
if filter_result
diff --git a/lib/chef/shell/ext.rb b/lib/chef/shell/ext.rb
index 40d7e10d2e..0c10309521 100644
--- a/lib/chef/shell/ext.rb
+++ b/lib/chef/shell/ext.rb
@@ -39,13 +39,13 @@ module Shell
# irb breaks if you prematurely define IRB::JobMangager
# so these methods need to be defined at the latest possible time.
unless jobs.respond_to?(:select_session_by_context)
- def jobs.select_session_by_context(&block)
+ def jobs.select_session_by_context(&block) # rubocop:disable Lint/NestedMethodDefinition
@jobs.select { |job| block.call(job[1].context.main) }
end
end
unless jobs.respond_to?(:session_select)
- def jobs.select_shell_session(target_context)
+ def jobs.select_shell_session(target_context) # rubocop:disable Lint/NestedMethodDefinition
session = if target_context.kind_of?(Class)
select_session_by_context { |main| main.kind_of?(target_context) }
else
diff --git a/lib/chef/shell/shell_session.rb b/lib/chef/shell/shell_session.rb
index 0a8cba5be3..a458286157 100644
--- a/lib/chef/shell/shell_session.rb
+++ b/lib/chef/shell/shell_session.rb
@@ -126,7 +126,7 @@ module Shell
end
def shorten_node_inspect
- def @node.inspect
+ def @node.inspect # rubocop:disable Lint/NestedMethodDefinition
"<Chef::Node:0x#{self.object_id.to_s(16)} @name=\"#{self.name}\">"
end
end
diff --git a/lib/chef/util/dsc/configuration_generator.rb b/lib/chef/util/dsc/configuration_generator.rb
index 739a463ad5..8b492d483a 100644
--- a/lib/chef/util/dsc/configuration_generator.rb
+++ b/lib/chef/util/dsc/configuration_generator.rb
@@ -48,7 +48,7 @@ class Chef::Util::DSC
configuration_document_location = find_configuration_document(configuration_name)
if ! configuration_document_location
- raise RuntimeError, "No DSC configuration for '#{configuration_name}' was generated from supplied DSC script"
+ raise "No DSC configuration for '#{configuration_name}' was generated from supplied DSC script"
end
configuration_document = get_configuration_document(configuration_document_location)
diff --git a/lib/chef/util/powershell/cmdlet.rb b/lib/chef/util/powershell/cmdlet.rb
index 6ab380c071..e300266b1e 100644
--- a/lib/chef/util/powershell/cmdlet.rb
+++ b/lib/chef/util/powershell/cmdlet.rb
@@ -62,8 +62,11 @@ class Chef
json_depth = @output_format_options[:depth]
end
- json_command = @json_format ? " | convertto-json -compress -depth #{json_depth} "\
- "> #{streams[:json].path}" : ""
+ json_command = if @json_format
+ " | convertto-json -compress -depth #{json_depth} > #{streams[:json].path}"
+ else
+ ""
+ end
redirections = "4> '#{streams[:verbose].path}'"
command_string = "powershell.exe -executionpolicy bypass -noprofile -noninteractive "\
"-command \"trap [Exception] {write-error -exception "\
diff --git a/lib/chef/util/selinux.rb b/lib/chef/util/selinux.rb
index 1aac7eeeca..edca589034 100644
--- a/lib/chef/util/selinux.rb
+++ b/lib/chef/util/selinux.rb
@@ -78,7 +78,7 @@ class Chef
when 0
return true
else
- raise RuntimeError, "Unknown exit code from command #{selinuxenabled_path}: #{cmd.exitstatus}"
+ raise "Unknown exit code from command #{selinuxenabled_path}: #{cmd.exitstatus}"
end
else
# We assume selinux is not enabled if selinux utils are not
diff --git a/lib/chef/version.rb b/lib/chef/version.rb
index dbf514e6ca..1789bf46ad 100644
--- a/lib/chef/version.rb
+++ b/lib/chef/version.rb
@@ -21,7 +21,7 @@
class Chef
CHEF_ROOT = File.expand_path("../..", __FILE__)
- VERSION = "12.13.16"
+ VERSION = "12.14.60"
end
#
diff --git a/lib/chef/version_class.rb b/lib/chef/version_class.rb
index 35a9f3282f..f26368902d 100644
--- a/lib/chef/version_class.rb
+++ b/lib/chef/version_class.rb
@@ -32,10 +32,15 @@ class Chef
"#{@major}.#{@minor}.#{@patch}"
end
- def <=>(v)
+ def <=>(other)
[:major, :minor, :patch].each do |method|
- ans = (self.send(method) <=> v.send(method))
- return ans if ans != 0
+ version = self.send(method)
+ begin
+ ans = (version <=> other.send(method))
+ rescue NoMethodError # if the other thing isn't a version object, return nil
+ return nil
+ end
+ return ans unless ans == 0
end
0
end
diff --git a/lib/chef/version_constraint.rb b/lib/chef/version_constraint.rb
index d4fa5df775..f10325f946 100644
--- a/lib/chef/version_constraint.rb
+++ b/lib/chef/version_constraint.rb
@@ -57,8 +57,8 @@ class Chef
"#{@op} #{@raw_version}"
end
- def eql?(o)
- o.class == self.class && @op == o.op && @version == o.version
+ def eql?(other)
+ other.class == self.class && @op == other.op && @version == other.version
end
alias_method :==, :eql?
diff --git a/lib/chef/win32/api/error.rb b/lib/chef/win32/api/error.rb
index dc83f9cb2b..12ccdb5ee9 100644
--- a/lib/chef/win32/api/error.rb
+++ b/lib/chef/win32/api/error.rb
@@ -194,12 +194,12 @@ class Chef
ERROR_INVALID_EXE_SIGNATURE = 191
ERROR_EXE_MARKED_INVALID = 192
ERROR_BAD_EXE_FORMAT = 193
- ERROR_ITERATED_DATA_EXCEEDS_64k = 194
+ ERROR_ITERATED_DATA_EXCEEDS_64k = 194 # rubocop:disable Style/ConstantName
ERROR_INVALID_MINALLOCSIZE = 195
ERROR_DYNLINK_FROM_INVALID_RING = 196
ERROR_IOPL_NOT_ENABLED = 197
ERROR_INVALID_SEGDPL = 198
- ERROR_AUTODATASEG_EXCEEDS_64k = 199
+ ERROR_AUTODATASEG_EXCEEDS_64k = 199 # rubocop:disable Style/ConstantName
ERROR_RING2SEG_MUST_BE_MOVABLE = 200
ERROR_RELOC_CHAIN_XEEDS_SEGLIM = 201
ERROR_INFLOOP_IN_RELOC_CHAIN = 202
diff --git a/lib/chef/win32/api/net.rb b/lib/chef/win32/api/net.rb
index bec00f638a..abf0dd83ec 100644
--- a/lib/chef/win32/api/net.rb
+++ b/lib/chef/win32/api/net.rb
@@ -45,7 +45,7 @@ class Chef
USE_FORCE = 1
USE_LOTS_OF_FORCE = 2 #every windows API should support this flag
- NERR_Success = 0
+ NERR_Success = 0 # rubocop:disable Style/ConstantName
ERROR_MORE_DATA = 234
ffi_lib "netapi32"
diff --git a/lib/chef/win32/eventlog.rb b/lib/chef/win32/eventlog.rb
index 4254b8ead3..eae0ae4abf 100644
--- a/lib/chef/win32/eventlog.rb
+++ b/lib/chef/win32/eventlog.rb
@@ -26,6 +26,6 @@ if Chef::Platform.windows? && (not Chef::Platform.windows_server_2003?)
end
require "win32/eventlog"
- Chef::Win32EventLogLoaded = true
+ Chef::Win32EventLogLoaded = true # rubocop:disable Style/ConstantName
end
end
diff --git a/lib/chef/win32/file.rb b/lib/chef/win32/file.rb
index 2a8f453432..1009f8c5a9 100644
--- a/lib/chef/win32/file.rb
+++ b/lib/chef/win32/file.rb
@@ -39,7 +39,7 @@ class Chef
# returns nil as per MRI.
#
def self.link(old_name, new_name)
- raise Errno::ENOENT, "(#{old_name}, #{new_name})" unless ::File.exist?(old_name)
+ raise Errno::ENOENT, "(#{old_name}, #{new_name})" unless ::File.exist?(old_name) || ::File.symlink?(old_name)
# TODO do a check for CreateHardLinkW and
# raise NotImplemented exception on older Windows
old_name = encode_path(old_name)
@@ -56,7 +56,7 @@ class Chef
# returns nil as per MRI.
#
def self.symlink(old_name, new_name)
- # raise Errno::ENOENT, "(#{old_name}, #{new_name})" unless ::File.exist?(old_name)
+ # raise Errno::ENOENT, "(#{old_name}, #{new_name})" unless ::File.exist?(old_name) || ::File.symlink?(old_name)
# TODO do a check for CreateSymbolicLinkW and
# raise NotImplemented exception on older Windows
flags = ::File.directory?(old_name) ? SYMBOLIC_LINK_FLAG_DIRECTORY : 0
@@ -75,7 +75,7 @@ class Chef
def self.symlink?(file_name)
is_symlink = false
path = encode_path(file_name)
- if ::File.exists?(file_name)
+ if ::File.exists?(file_name) || ::File.symlink?(file_name)
if (GetFileAttributesW(path) & FILE_ATTRIBUTE_REPARSE_POINT) > 0
file_search_handle(file_name) do |handle, find_data|
if find_data[:dw_reserved_0] == IO_REPARSE_TAG_SYMLINK
@@ -93,7 +93,7 @@ class Chef
# will raise a NotImplementedError, as per MRI.
#
def self.readlink(link_name)
- raise Errno::ENOENT, link_name unless ::File.exists?(link_name)
+ raise Errno::ENOENT, link_name unless ::File.exists?(link_name) || ::File.symlink?(link_name)
symlink_file_handle(link_name) do |handle|
# Go to DeviceIoControl to get the symlink information
# http://msdn.microsoft.com/en-us/library/windows/desktop/aa364571(v=vs.85).aspx
diff --git a/lib/chef/win32/net.rb b/lib/chef/win32/net.rb
index 0454b17d49..09db2af89d 100644
--- a/lib/chef/win32/net.rb
+++ b/lib/chef/win32/net.rb
@@ -207,7 +207,7 @@ class Chef
def self.members_to_lgrmi3(members)
buf = FFI::MemoryPointer.new(LOCALGROUP_MEMBERS_INFO_3, members.size)
- members.size.times.collect do |i|
+ Array.new(members.size) do |i|
member_info = LOCALGROUP_MEMBERS_INFO_3.new(
buf + i * LOCALGROUP_MEMBERS_INFO_3.size)
member_info[:lgrmi3_domainandname] = FFI::MemoryPointer.from_string(wstring(members[i]))
diff --git a/lib/chef/win32/security/sid.rb b/lib/chef/win32/security/sid.rb
index 9951b931c9..f6b88c60ce 100644
--- a/lib/chef/win32/security/sid.rb
+++ b/lib/chef/win32/security/sid.rb
@@ -279,7 +279,7 @@ class Chef
status = NetUserEnum(servername, level, filter, bufptr, prefmaxlen, entriesread, totalentries, resume_handle)
if status == NERR_Success || status == ERROR_MORE_DATA
- entriesread.read_long.times.collect do |i|
+ Array.new(entriesread.read_long) do |i|
user_info = USER_INFO_3.new(bufptr.read_pointer + i * USER_INFO_3.size)
# Check if the account is the Administrator account
# RID for the Administrator account is always 500 and it's privilage is set to USER_PRIV_ADMIN