diff options
author | Lamont Granquist <lamont@scriptkiddie.org> | 2019-07-02 15:09:07 -0700 |
---|---|---|
committer | Lamont Granquist <lamont@scriptkiddie.org> | 2019-07-02 15:09:07 -0700 |
commit | 7a1a6c8ef26c787e4b6dd1602f3d158b37e81720 (patch) | |
tree | 1e390cd535b38368d091cbb33e5d419408d5ce00 | |
parent | 77f8739a4741e2370e40ec39345a92a6ea393a1a (diff) | |
download | chef-7a1a6c8ef26c787e4b6dd1602f3d158b37e81720.tar.gz |
fix Layout/EmptyLineAfterGuardClause
i like this one, gives visual priority to returns or raises that are
buried in the middle of things.
Signed-off-by: Lamont Granquist <lamont@scriptkiddie.org>
220 files changed, 481 insertions, 0 deletions
diff --git a/chef-config/lib/chef-config/config.rb b/chef-config/lib/chef-config/config.rb index 051cdbfb7f..2348f0677f 100644 --- a/chef-config/lib/chef-config/config.rb +++ b/chef-config/lib/chef-config/config.rb @@ -103,6 +103,7 @@ module ChefConfig if option.empty? || !option.include?("=") raise UnparsableConfigOption, "Unparsable config option #{option.inspect}" end + # Split including whitespace if someone does truly odd like # --config-option "foo = bar" key, value = option.split(/\s*=\s*/, 2) @@ -144,6 +145,7 @@ module ChefConfig unless is_valid_url? uri raise ConfigurationError, "#{uri} is an invalid chef_server_url. The URL must start with http://, https://, or chefzero://." end + uri.to_s.strip end diff --git a/chef-config/lib/chef-config/mixin/credentials.rb b/chef-config/lib/chef-config/mixin/credentials.rb index 5b0078d1cc..3882924d1a 100644 --- a/chef-config/lib/chef-config/mixin/credentials.rb +++ b/chef-config/lib/chef-config/mixin/credentials.rb @@ -65,6 +65,7 @@ module ChefConfig def parse_credentials_file credentials_file = credentials_file_path return nil unless File.file?(credentials_file) + begin Tomlrb.load_file(credentials_file) rescue => e @@ -85,10 +86,12 @@ module ChefConfig profile = credentials_profile(profile) config = parse_credentials_file return if config.nil? # No credentials, nothing to do here. + if config[profile].nil? # Unknown profile name. For "default" just silently ignore, otherwise # raise an error. return if profile == "default" + raise ChefConfig::ConfigurationError, "Profile #{profile} doesn't exist. Please add it to #{credentials_file}." end apply_credentials(config[profile], profile) diff --git a/chef-config/lib/chef-config/workstation_config_loader.rb b/chef-config/lib/chef-config/workstation_config_loader.rb index a3aa40433a..d38cae3d88 100644 --- a/chef-config/lib/chef-config/workstation_config_loader.rb +++ b/chef-config/lib/chef-config/workstation_config_loader.rb @@ -155,6 +155,7 @@ module ChefConfig if creds.key?("node_name") && creds.key?("client_name") raise ChefConfig::ConfigurationError, "Do not specify both node_name and client_name. You should prefer client_name." end + # Load credentials data into the Chef configuration. creds.each do |key, value| case key.to_s diff --git a/lib/chef/action_collection.rb b/lib/chef/action_collection.rb index af28bf8542..7b1997cfaf 100644 --- a/lib/chef/action_collection.rb +++ b/lib/chef/action_collection.rb @@ -145,6 +145,7 @@ class Chef # def converge_failed(exception) return if consumers.empty? + detect_unprocessed_resources end @@ -156,6 +157,7 @@ class Chef # def resource_action_start(new_resource, action, notification_type = nil, notifier = nil) return if consumers.empty? + pending_updates << ActionRecord.new(new_resource, action, pending_updates.length) end @@ -166,6 +168,7 @@ class Chef # def resource_current_state_loaded(new_resource, action, current_resource) return if consumers.empty? + current_record.current_resource = current_resource end @@ -175,6 +178,7 @@ class Chef # def resource_up_to_date(new_resource, action) return if consumers.empty? + current_record.status = :up_to_date end @@ -184,6 +188,7 @@ class Chef # def resource_skipped(resource, action, conditional) return if consumers.empty? + current_record.status = :skipped current_record.conditional = conditional end @@ -194,6 +199,7 @@ class Chef # def resource_updated(new_resource, action) return if consumers.empty? + current_record.status = :updated end @@ -203,6 +209,7 @@ class Chef # def resource_failed(new_resource, action, exception) return if consumers.empty? + current_record.status = :failed current_record.exception = exception end @@ -213,6 +220,7 @@ class Chef # def resource_completed(new_resource) return if consumers.empty? + current_record.elapsed_time = new_resource.elapsed_time # Verify if the resource has sensitive data and create a new blank resource with only diff --git a/lib/chef/api_client/registration.rb b/lib/chef/api_client/registration.rb index dc4bb4e57a..07ecd9a2a5 100644 --- a/lib/chef/api_client/registration.rb +++ b/lib/chef/api_client/registration.rb @@ -60,6 +60,7 @@ class Chef rescue Net::HTTPFatalError => e # HTTPFatalError implies 5xx. raise if retries <= 0 + retries -= 1 Chef::Log.warn("Failed to register new client, #{retries} tries remaining") Chef::Log.warn("Response: HTTP #{e.response.code} - #{e}") @@ -97,6 +98,7 @@ class Chef # If create fails because the client exists, attempt to update. This # requires admin privileges. raise unless e.response.code == "409" + update end diff --git a/lib/chef/api_client_v1.rb b/lib/chef/api_client_v1.rb index 513d546e64..20d1989d38 100644 --- a/lib/chef/api_client_v1.rb +++ b/lib/chef/api_client_v1.rb @@ -270,6 +270,7 @@ class Chef # rescue API V0 if 406 and the server supports V0 supported_versions = server_client_api_version_intersection(e, SUPPORTED_API_VERSIONS) raise e unless supported_versions && supported_versions.include?(0) + new_client = chef_rest_v0.put("clients/#{name}", payload) end diff --git a/lib/chef/application.rb b/lib/chef/application.rb index 0b4ae139d7..a632a97319 100644 --- a/lib/chef/application.rb +++ b/lib/chef/application.rb @@ -353,6 +353,7 @@ class Chef def handle_child_exit(pid_and_status) status = pid_and_status[1] return true if status.success? + message = if status.signaled? "Chef run process terminated by signal #{status.termsig} (#{Signal.list.invert[status.termsig]})" else diff --git a/lib/chef/chef_fs/chef_fs_data_store.rb b/lib/chef/chef_fs/chef_fs_data_store.rb index 50badef794..6b0cb4630a 100644 --- a/lib/chef/chef_fs/chef_fs_data_store.rb +++ b/lib/chef/chef_fs/chef_fs_data_store.rb @@ -279,6 +279,7 @@ class Chef if !policy_group["policies"] || !policy_group["policies"][path[3]] raise ChefZero::DataStore::DataNotFoundError.new(path, entry) end + # The policy group looks like: # { # "policies": { @@ -401,6 +402,7 @@ class Chef unless group["policies"] && group["policies"].key?(path[3]) raise ChefZero::DataStore::DataNotFoundError.new(path) end + group["policies"].delete(path[3]) group end @@ -413,6 +415,7 @@ class Chef if result.size == members.size raise ChefZero::DataStore::DataNotFoundError.new(path) end + result end @@ -424,6 +427,7 @@ class Chef if result.size == invitations.size raise ChefZero::DataStore::DataNotFoundError.new(path) end + result end @@ -457,6 +461,7 @@ class Chef policies.children.each do |policy| # 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 @@ -502,6 +507,7 @@ class Chef revisions << revision if name == path[1] end raise ChefZero::DataStore::DataNotFoundError.new(path) if revisions.empty? + revisions end @@ -544,6 +550,7 @@ class Chef if result.empty? raise ChefZero::DataStore::DataNotFoundError.new(path) end + result else # list /cookbooks/name = <single version> @@ -846,6 +853,7 @@ class Chef def ensure_dir(entry) return entry if entry.exists? + parent = entry.parent if parent ensure_dir(parent) diff --git a/lib/chef/chef_fs/command_line.rb b/lib/chef/chef_fs/command_line.rb index 56c0c574e8..217fb208d3 100644 --- a/lib/chef/chef_fs/command_line.rb +++ b/lib/chef/chef_fs/command_line.rb @@ -44,6 +44,7 @@ class Chef when :directory_to_file next if diff_filter && diff_filter !~ /T/ + if output_mode == :name_only yield "#{new_path}\n" elsif output_mode == :name_status @@ -54,6 +55,7 @@ class Chef when :file_to_directory next if diff_filter && diff_filter !~ /T/ + if output_mode == :name_only yield "#{new_path}\n" elsif output_mode == :name_status @@ -71,6 +73,7 @@ class Chef new_path += File.extname(old_path) end next if diff_filter && diff_filter !~ /D/ + if output_mode == :name_only yield "#{new_path}\n" elsif output_mode == :name_status @@ -86,6 +89,7 @@ class Chef when :added next if diff_filter && diff_filter !~ /A/ + if output_mode == :name_only yield "#{new_path}\n" elsif output_mode == :name_status @@ -101,6 +105,7 @@ class Chef when :modified next if diff_filter && diff_filter !~ /M/ + if output_mode == :name_only yield "#{new_path}\n" elsif output_mode == :name_status diff --git a/lib/chef/chef_fs/config.rb b/lib/chef/chef_fs/config.rb index c6f6878c00..7940dbf1fe 100644 --- a/lib/chef/chef_fs/config.rb +++ b/lib/chef/chef_fs/config.rb @@ -272,6 +272,7 @@ class Chef # cookbooks -> cookbook_path singular_name = INFLECTIONS[object_name] raise "Unknown object name #{object_name}" unless singular_name + variable_name = "#{singular_name}_path" paths = Array(@chef_config[variable_name]).flatten result[object_name] = paths.map { |path| File.expand_path(path) } diff --git a/lib/chef/chef_fs/file_pattern.rb b/lib/chef/chef_fs/file_pattern.rb index 88604e2b8f..5e3e276541 100644 --- a/lib/chef/chef_fs/file_pattern.rb +++ b/lib/chef/chef_fs/file_pattern.rb @@ -74,6 +74,7 @@ class Chef argument_is_absolute = Chef::ChefFS::PathUtils.is_absolute?(path) return false if is_absolute != argument_is_absolute + path = path[1, path.length - 1] if argument_is_absolute path_parts = Chef::ChefFS::PathUtils.split(path) @@ -81,6 +82,7 @@ class Chef return false if regexp_parts.length <= path_parts.length && !has_double_star # If the path doesn't match up to this point, children won't match either. return false if path_parts.zip(regexp_parts).any? { |part, regexp| !regexp.nil? && !regexp.match(part) } + # Otherwise, it's possible we could match: the path matches to this point, and the pattern is longer than the path. # TODO There is one edge case where the double star comes after some characters like abc**def--we could check whether the next # bit of path starts with abc in that case. @@ -114,6 +116,7 @@ class Chef path = path[1, path.length - 1] if Chef::ChefFS::PathUtils.is_absolute?(path) dirs_in_path = Chef::ChefFS::PathUtils.split(path).length return nil if exact_parts.length <= dirs_in_path + exact_parts[dirs_in_path] end @@ -124,6 +127,7 @@ class Chef # abc/x\\yz.exact_path == 'abc/xyz' def exact_path return nil if has_double_star || exact_parts.any? { |part| part.nil? } + result = Chef::ChefFS::PathUtils.join(*exact_parts) is_absolute ? Chef::ChefFS::PathUtils.join("", result) : result end @@ -151,6 +155,7 @@ class Chef def match?(path) argument_is_absolute = Chef::ChefFS::PathUtils.is_absolute?(path) return false if is_absolute != argument_is_absolute + path = path[1, path.length - 1] if argument_is_absolute !!regexp.match(path) end @@ -213,6 +218,7 @@ class Chef if has_double_star_prev raise ArgumentError, ".. overlapping a ** is unsupported" end + full_regexp_parts.pop normalized_parts.pop if !@has_double_star diff --git a/lib/chef/chef_fs/file_system.rb b/lib/chef/chef_fs/file_system.rb index ff85a4a1b1..dbf0704c9e 100644 --- a/lib/chef/chef_fs/file_system.rb +++ b/lib/chef/chef_fs/file_system.rb @@ -94,6 +94,7 @@ class Chef def self.resolve_path(entry, path) return entry if path.length == 0 return resolve_path(entry.root, path) if path[0, 1] == "/" && entry.root != entry + if path[0, 1] == "/" path = path[1, path.length - 1] end diff --git a/lib/chef/chef_fs/file_system/base_fs_object.rb b/lib/chef/chef_fs/file_system/base_fs_object.rb index f7516232ac..e319232b0e 100644 --- a/lib/chef/chef_fs/file_system/base_fs_object.rb +++ b/lib/chef/chef_fs/file_system/base_fs_object.rb @@ -32,6 +32,7 @@ class Chef if name != "" raise ArgumentError, "Name of root object must be empty string: was '#{name}' instead" end + @path = "/" end end @@ -108,12 +109,14 @@ class Chef # Override children to report your *actual* list of children as an array. def children raise NotFoundError.new(self) if !exists? + [] end # Expand this entry into a chef object (Chef::Role, ::Node, etc.) def chef_object raise NotFoundError.new(self) if !exists? + nil end @@ -125,6 +128,7 @@ class Chef # file_contents. This is used for knife upload /cookbooks/cookbookname. def create_child(name, file_contents) raise NotFoundError.new(self) if !exists? + raise OperationNotAllowedError.new(:create_child, self) end @@ -132,6 +136,7 @@ class Chef # directory unless recurse is true. def delete(recurse) raise NotFoundError.new(self) if !exists? + raise OperationNotAllowedError.new(:delete, self) end @@ -167,12 +172,14 @@ class Chef # Read the contents of this file entry. def read raise NotFoundError.new(self) if !exists? + raise OperationNotAllowedError.new(:read, self) end # Write the contents of this file entry. def write(file_contents) raise NotFoundError.new(self) if !exists? + raise OperationNotAllowedError.new(:write, self) end diff --git a/lib/chef/chef_fs/file_system/chef_server/cookbook_dir.rb b/lib/chef/chef_fs/file_system/chef_server/cookbook_dir.rb index b8e1b7b43c..336f3592d5 100644 --- a/lib/chef/chef_fs/file_system/chef_server/cookbook_dir.rb +++ b/lib/chef/chef_fs/file_system/chef_server/cookbook_dir.rb @@ -69,6 +69,7 @@ class Chef def can_have_child?(name, is_dir) return name != "root_files" if is_dir + true end @@ -117,6 +118,7 @@ class Chef end else raise NotFoundError.new(self) if !exists? + raise MustDeleteRecursivelyError.new(self, "#{path_for_printing} must be deleted recursively") end end @@ -134,6 +136,7 @@ class Chef if !other.dir? return [ !exists?, nil, nil ] end + are_same = true Chef::ChefFS::CommandLine.diff_entries(self, other, nil, :name_only).each do |type, old_entry, new_entry| if [ :directory_to_file, :file_to_directory, :deleted, :added, :modified ].include?(type) diff --git a/lib/chef/chef_fs/file_system/chef_server/data_bag_dir.rb b/lib/chef/chef_fs/file_system/chef_server/data_bag_dir.rb index fb8a537596..317fbb91cc 100644 --- a/lib/chef/chef_fs/file_system/chef_server/data_bag_dir.rb +++ b/lib/chef/chef_fs/file_system/chef_server/data_bag_dir.rb @@ -50,6 +50,7 @@ class Chef def delete(recurse) if !recurse raise NotFoundError.new(self) if !exists? + raise MustDeleteRecursivelyError.new(self, "#{path_for_printing} must be deleted recursively") end begin diff --git a/lib/chef/chef_fs/file_system/chef_server/environments_dir.rb b/lib/chef/chef_fs/file_system/chef_server/environments_dir.rb index 09ab30c799..f213430d14 100644 --- a/lib/chef/chef_fs/file_system/chef_server/environments_dir.rb +++ b/lib/chef/chef_fs/file_system/chef_server/environments_dir.rb @@ -41,11 +41,13 @@ class Chef def delete(recurse) raise NotFoundError.new(self) if !exists? + raise DefaultEnvironmentCannotBeModifiedError.new(:delete, self) end def write(file_contents) raise NotFoundError.new(self) if !exists? + raise DefaultEnvironmentCannotBeModifiedError.new(:write, self) end end diff --git a/lib/chef/chef_fs/file_system/chef_server/policies_dir.rb b/lib/chef/chef_fs/file_system/chef_server/policies_dir.rb index d0674075c6..073bea7a95 100644 --- a/lib/chef/chef_fs/file_system/chef_server/policies_dir.rb +++ b/lib/chef/chef_fs/file_system/chef_server/policies_dir.rb @@ -95,6 +95,7 @@ class Chef if e.response.code == "404" raise Chef::ChefFS::FileSystem::NotFoundError.new(self, $!) end + raise Chef::ChefFS::FileSystem::OperationFailedError.new(:children, self, e, "HTTP error retrieving children: #{e}") end # Anything else is unexpected (OperationFailedError) diff --git a/lib/chef/chef_fs/file_system/chef_server/rest_list_dir.rb b/lib/chef/chef_fs/file_system/chef_server/rest_list_dir.rb index 7c5e01bf7e..d2c5bdc9b7 100644 --- a/lib/chef/chef_fs/file_system/chef_server/rest_list_dir.rb +++ b/lib/chef/chef_fs/file_system/chef_server/rest_list_dir.rb @@ -94,6 +94,7 @@ class Chef if e.response.code == "404" raise Chef::ChefFS::FileSystem::NotFoundError.new(self, $!) end + raise Chef::ChefFS::FileSystem::OperationFailedError.new(:children, self, e, "HTTP error retrieving children: #{e}") end else 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 ade5fc2039..b36a1ae214 100644 --- a/lib/chef/chef_fs/file_system/repository/base_file.rb +++ b/lib/chef/chef_fs/file_system/repository/base_file.rb @@ -132,6 +132,7 @@ class Chef if is_ruby_file? raise Chef::ChefFS::FileSystem::RubyFileError.new(:write, self) end + if content && write_pretty_json && is_json_file? content = minimize(content, self) end diff --git a/lib/chef/chef_fs/file_system/repository/chef_repository_file_system_cookbook_dir.rb b/lib/chef/chef_fs/file_system/repository/chef_repository_file_system_cookbook_dir.rb index 5098d55727..2d8699621b 100644 --- a/lib/chef/chef_fs/file_system/repository/chef_repository_file_system_cookbook_dir.rb +++ b/lib/chef/chef_fs/file_system/repository/chef_repository_file_system_cookbook_dir.rb @@ -34,6 +34,7 @@ class Chef def fs_entry_valid? return false unless File.directory?(file_path) && name_valid? + if can_upload? true else @@ -54,6 +55,7 @@ class Chef if exists? raise Chef::ChefFS::FileSystem::AlreadyExistsError.new(:create_child, self) end + begin Dir.mkdir(file_path) rescue Errno::EEXIST @@ -103,6 +105,7 @@ class Chef elsif name == Chef::Cookbook::CookbookVersionLoader::UPLOADED_COOKBOOK_VERSION_FILE return false end + super(name, is_dir) end @@ -110,6 +113,7 @@ class Chef def self.canonical_cookbook_name(entry_name) name_match = Chef::ChefFS::FileSystem::ChefServer::VersionedCookbookDir::VALID_VERSIONED_COOKBOOK_NAME.match(entry_name) return nil if name_match.nil? + name_match[1] end 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 a6cae64c6d..7a0dc80f79 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 @@ -101,6 +101,7 @@ class Chef if child.exists? raise Chef::ChefFS::FileSystem::AlreadyExistsError.new(:create_child, child) end + if file_contents child.write(file_contents) else @@ -124,6 +125,7 @@ class Chef if !recurse raise MustDeleteRecursivelyError.new(self, $!) end + FileUtils.rm_r(file_path) else File.delete(file_path) diff --git a/lib/chef/chef_fs/file_system/repository/chef_repository_file_system_root_dir.rb b/lib/chef/chef_fs/file_system/repository/chef_repository_file_system_root_dir.rb index 30ccf8c736..6b5da9421c 100644 --- a/lib/chef/chef_fs/file_system/repository/chef_repository_file_system_root_dir.rb +++ b/lib/chef/chef_fs/file_system/repository/chef_repository_file_system_root_dir.rb @@ -180,6 +180,7 @@ class Chef def make_child_entry(name) if CHILDREN.include?(name) return nil if !root_dir + return root_dir.child(name) end @@ -187,6 +188,7 @@ class Chef if paths.size == 0 return NonexistentFSObject.new(name, self) end + case name when "acls" dirs = paths.map { |path| AclsDir.new(name, self, path) } diff --git a/lib/chef/chef_fs/file_system/repository/chef_repository_file_system_versioned_cookbook_dir.rb b/lib/chef/chef_fs/file_system/repository/chef_repository_file_system_versioned_cookbook_dir.rb index 4fb214cff8..442fa879ad 100644 --- a/lib/chef/chef_fs/file_system/repository/chef_repository_file_system_versioned_cookbook_dir.rb +++ b/lib/chef/chef_fs/file_system/repository/chef_repository_file_system_versioned_cookbook_dir.rb @@ -30,6 +30,7 @@ class Chef # want to spend a lot of time adding code to the main Chef libraries canonical_name = canonical_cookbook_name(File.basename(file_path)) raise "When versioned_cookbooks mode is on, cookbook #{file_path} must match format <cookbook_name>-x.y.z" unless canonical_name + # KLUDGE: We shouldn't have to use instance_variable_set loader.instance_variable_set(:@cookbook_name, canonical_name) loader.load_cookbooks diff --git a/lib/chef/chef_fs/file_system/repository/directory.rb b/lib/chef/chef_fs/file_system/repository/directory.rb index f428e939d3..1275cb4621 100644 --- a/lib/chef/chef_fs/file_system/repository/directory.rb +++ b/lib/chef/chef_fs/file_system/repository/directory.rb @@ -71,6 +71,7 @@ class Chef def children return FileSystemCache.instance.children(file_path) if FileSystemCache.instance.exist?(file_path) + children = dir_ls.sort .map { |child_name| make_child_entry(child_name) } .select { |new_child| new_child.fs_entry_valid? && can_have_child?(new_child.name, new_child.dir?) } @@ -84,6 +85,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) @@ -122,6 +124,7 @@ class Chef if exists? raise Chef::ChefFS::FileSystem::AlreadyExistsError.new(:create_child, self) end + begin FileSystemCache.instance.delete!(file_path) Dir.mkdir(file_path) @@ -139,6 +142,7 @@ class Chef if !recurse raise MustDeleteRecursivelyError.new(self, $!) end + FileUtils.rm_r(file_path) FileSystemCache.instance.delete!(file_path) else diff --git a/lib/chef/chef_fs/file_system/repository/file_system_entry.rb b/lib/chef/chef_fs/file_system/repository/file_system_entry.rb index 33b4de8014..ed6a3d598c 100644 --- a/lib/chef/chef_fs/file_system/repository/file_system_entry.rb +++ b/lib/chef/chef_fs/file_system/repository/file_system_entry.rb @@ -92,6 +92,7 @@ class Chef if child.exists? raise Chef::ChefFS::FileSystem::AlreadyExistsError.new(:create_child, child) end + if file_contents child.write(file_contents) else @@ -111,6 +112,7 @@ class Chef if !recurse raise MustDeleteRecursivelyError.new(self, $!) end + FileUtils.rm_r(file_path) else File.delete(file_path) diff --git a/lib/chef/chef_fs/file_system_cache.rb b/lib/chef/chef_fs/file_system_cache.rb index e36dbbce7c..0024a49098 100644 --- a/lib/chef/chef_fs/file_system_cache.rb +++ b/lib/chef/chef_fs/file_system_cache.rb @@ -73,6 +73,7 @@ class Chef 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 diff --git a/lib/chef/chef_fs/parallelizer/parallel_enumerable.rb b/lib/chef/chef_fs/parallelizer/parallel_enumerable.rb index 2291220ef8..143b38aef8 100644 --- a/lib/chef/chef_fs/parallelizer/parallel_enumerable.rb +++ b/lib/chef/chef_fs/parallelizer/parallel_enumerable.rb @@ -147,6 +147,7 @@ class Chef if @each_running raise "each() called on parallel enumerable twice simultaneously! Bad mojo" end + @each_running = true begin # Grab all the inputs, yielding any responses during enumeration diff --git a/lib/chef/chef_fs/path_utils.rb b/lib/chef/chef_fs/path_utils.rb index fe6428a5b1..c490f50c17 100644 --- a/lib/chef/chef_fs/path_utils.rb +++ b/lib/chef/chef_fs/path_utils.rb @@ -42,6 +42,7 @@ class Chef def self.join(*parts) return "" if parts.length == 0 + # Determine if it started with a slash absolute = parts[0].length == 0 || parts[0].length > 0 && parts[0] =~ /^#{regexp_path_separator}/ # Remove leading and trailing slashes from each part so that the join will work (and the slash at the end will go away) @@ -87,6 +88,7 @@ class Chef # This can occur if a path such as "C:" is given. Ruby gives the parent as "C:." # for reasons only it knows. raise ArgumentError "Invalid path segment #{path}" if parent_path.length > path.length + begin path = File.realpath(path) break @@ -113,6 +115,7 @@ class Chef def self.descendant_path(path, ancestor) candidate_fragment = path[0, ancestor.length] return nil unless PathUtils.os_path_eq?(candidate_fragment, ancestor) + if ancestor.length == path.length "" elsif path[ancestor.length, 1] =~ /#{PathUtils.regexp_path_separator}/ diff --git a/lib/chef/client.rb b/lib/chef/client.rb index 51a93440e9..37cc7cd6d1 100644 --- a/lib/chef/client.rb +++ b/lib/chef/client.rb @@ -881,12 +881,14 @@ class Chef def start_profiling return unless Chef::Config[:profile_ruby] + profiling_prereqs! RubyProf.start end def end_profiling return unless Chef::Config[:profile_ruby] + profiling_prereqs! path = Chef::FileCache.create_cache_path("graph_profile.out", false) File.open(path, "w+") do |file| diff --git a/lib/chef/cookbook/cookbook_version_loader.rb b/lib/chef/cookbook/cookbook_version_loader.rb index ad7ee3b1c2..6d1b3e1f61 100644 --- a/lib/chef/cookbook/cookbook_version_loader.rb +++ b/lib/chef/cookbook/cookbook_version_loader.rb @@ -70,6 +70,7 @@ class Chef if empty? raise Exceptions::CookbookNotFoundInRepo, "The directory #{cookbook_path} does not contain a cookbook" end + file_paths_map end @@ -152,6 +153,7 @@ class Chef def metadata_filenames return @metadata_filenames unless @metadata_filenames.empty? + if File.exists?(File.join(cookbook_path, UPLOADED_COOKBOOK_VERSION_FILE)) @uploaded_cookbook_version_file = File.join(cookbook_path, UPLOADED_COOKBOOK_VERSION_FILE) end @@ -171,6 +173,7 @@ class Chef def raise_metadata_error! raise metadata_error unless metadata_error.nil? + # Metadata won't be valid if the cookbook is empty. If the cookbook is # actually empty, a metadata error here would be misleading, so don't # raise it (if called by #load!, a different error is raised). diff --git a/lib/chef/cookbook/file_system_file_vendor.rb b/lib/chef/cookbook/file_system_file_vendor.rb index 2faeb31815..b89d10cd48 100644 --- a/lib/chef/cookbook/file_system_file_vendor.rb +++ b/lib/chef/cookbook/file_system_file_vendor.rb @@ -49,6 +49,7 @@ class Chef def get_filename(filename) location = File.join(cookbooks[cookbook_name].root_dir, filename) if cookbooks.key?(cookbook_name) raise "File #{filename} does not exist for cookbook #{cookbook_name}" unless location && File.exist?(location) + location end diff --git a/lib/chef/cookbook/file_vendor.rb b/lib/chef/cookbook/file_vendor.rb index 60948cc3a5..82eb4e03f6 100644 --- a/lib/chef/cookbook/file_vendor.rb +++ b/lib/chef/cookbook/file_vendor.rb @@ -54,6 +54,7 @@ class Chef if @vendor_class.nil? raise "Must configure FileVendor to use a specific implementation before creating an instance" end + @vendor_class.new(manifest, @initialization_options) end diff --git a/lib/chef/cookbook/gem_installer.rb b/lib/chef/cookbook/gem_installer.rb index bd1d0fb93a..eab4b47241 100644 --- a/lib/chef/cookbook/gem_installer.rb +++ b/lib/chef/cookbook/gem_installer.rb @@ -43,6 +43,7 @@ class Chef args << {} unless args.last.is_a?(Hash) args.last.merge!(cookbook_gems[args.first].pop) do |key, v1, v2| raise Chef::Exceptions::GemRequirementConflict.new(args.first, key, v1, v2) if v1 != v2 + v2 end end diff --git a/lib/chef/cookbook/manifest_v0.rb b/lib/chef/cookbook/manifest_v0.rb index e285b29fd2..a4c60e5827 100644 --- a/lib/chef/cookbook/manifest_v0.rb +++ b/lib/chef/cookbook/manifest_v0.rb @@ -32,6 +32,7 @@ class Chef response = Mash.new(hash) response[:all_files] = COOKBOOK_SEGMENTS.inject([]) do |memo, segment| next memo if hash[segment].nil? || hash[segment].empty? + hash[segment].each do |file| file["name"] = "#{segment}/#{file["name"]}" memo << file diff --git a/lib/chef/cookbook/metadata.rb b/lib/chef/cookbook/metadata.rb index 6d82ae4e30..ff12d865c3 100644 --- a/lib/chef/cookbook/metadata.rb +++ b/lib/chef/cookbook/metadata.rb @@ -286,6 +286,7 @@ class Chef constraint = validate_version_constraint(:depends, cookbook, version) @dependencies[cookbook] = constraint.to_s end + @dependencies[cookbook] end @@ -583,6 +584,7 @@ class Chef def gem_dep_matches?(what, version, *deps) # always match if we have no chef_version at all return true unless deps.length > 0 + # match if we match any of the chef_version lines deps.any? { |dep| dep.match?(what, version) } end diff --git a/lib/chef/cookbook/remote_file_vendor.rb b/lib/chef/cookbook/remote_file_vendor.rb index 9ccb2ff46c..ebdb94ee54 100644 --- a/lib/chef/cookbook/remote_file_vendor.rb +++ b/lib/chef/cookbook/remote_file_vendor.rb @@ -44,6 +44,7 @@ class Chef end raise "No such segment #{segment} in cookbook #{@cookbook_name}" unless @manifest.files_for(segment) + found_manifest_record = @manifest.files_for(segment).find { |manifest_record| manifest_record[:path] == filename } raise "No such file #{filename} in #{@cookbook_name}" unless found_manifest_record diff --git a/lib/chef/cookbook/synchronizer.rb b/lib/chef/cookbook/synchronizer.rb index 8c87ababb6..b69e6b8212 100644 --- a/lib/chef/cookbook/synchronizer.rb +++ b/lib/chef/cookbook/synchronizer.rb @@ -223,6 +223,7 @@ class Chef cache.find(File.join(%w{cookbooks ** {*,.*}})).each do |cache_file| md = cache_file.match(/^cookbooks\/([^\/]+)\/([^\/]+)\/(.*)/) next unless md + ( cookbook_name, segment, file ) = md[1..3] if have_cookbook?(cookbook_name) manifest_segment = cookbook_segment(cookbook_name, segment) @@ -297,6 +298,7 @@ class Chef def cached_copy_up_to_date?(local_path, expected_checksum) return true if Chef::Config[:skip_cookbook_sync] + if cache.key?(local_path) current_checksum = CookbookVersion.checksum_cookbook_file(cache.load(local_path, false)) expected_checksum == current_checksum diff --git a/lib/chef/cookbook/syntax_check.rb b/lib/chef/cookbook/syntax_check.rb index 89061d4f5f..6c1f710f6d 100644 --- a/lib/chef/cookbook/syntax_check.rb +++ b/lib/chef/cookbook/syntax_check.rb @@ -62,6 +62,7 @@ class Chef def ensure_cache_path_created return true if @cache_path_created + FileUtils.mkdir_p(cache_path) @cache_path_created = true end @@ -86,6 +87,7 @@ class Chef unless cookbook_path raise ArgumentError, "Cannot find cookbook #{cookbook_name} unless Chef::Config.cookbook_path is set or an explicit cookbook path is given" end + new(File.join(cookbook_path, cookbook_name.to_s)) end @@ -157,6 +159,7 @@ class Chef def validate_ruby_files untested_ruby_files.each do |ruby_file| return false unless validate_ruby_file(ruby_file) + validated(ruby_file) end end @@ -164,6 +167,7 @@ class Chef def validate_templates untested_template_files.each do |template| return false unless validate_template(template) + validated(template) end end diff --git a/lib/chef/cookbook_loader.rb b/lib/chef/cookbook_loader.rb index ada19baed7..b27d751d64 100644 --- a/lib/chef/cookbook_loader.rb +++ b/lib/chef/cookbook_loader.rb @@ -176,6 +176,7 @@ class Chef if mash.key?(cookbook_name) raise Chef::Exceptions::CookbookMergingError, "Cookbook merging is no longer supported, the cookbook named #{cookbook_name} can only appear once in the cookbook_path" end + mash[cookbook_name] = loader end mash diff --git a/lib/chef/cookbook_manifest.rb b/lib/chef/cookbook_manifest.rb index e061d9ef32..13c0332cd8 100644 --- a/lib/chef/cookbook_manifest.rb +++ b/lib/chef/cookbook_manifest.rb @@ -172,6 +172,7 @@ class Chef def files_for(part) return root_files if part.to_s == "root_files" + manifest[:all_files].select do |file| seg = file[:name].split("/")[0] part.to_s == seg @@ -184,6 +185,7 @@ class Chef manifest[:all_files].each do |file| seg = file[:name].split("/")[0] next if excluded_parts.include?(seg) + yield file if block_given? end end diff --git a/lib/chef/cookbook_version.rb b/lib/chef/cookbook_version.rb index e69b2404b7..6ef66a0337 100644 --- a/lib/chef/cookbook_version.rb +++ b/lib/chef/cookbook_version.rb @@ -502,6 +502,7 @@ class Chef def <=>(other) raise Chef::Exceptions::CookbookVersionNameMismatch if 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? diff --git a/lib/chef/data_bag_item.rb b/lib/chef/data_bag_item.rb index 7ac76d9ebb..da13b02268 100644 --- a/lib/chef/data_bag_item.rb +++ b/lib/chef/data_bag_item.rb @@ -73,6 +73,7 @@ class Chef unless new_data.respond_to?(:[]) && new_data.respond_to?(:keys) raise Exceptions::ValidationFailed, "Data Bag Items must contain a Hash or Mash!" end + validate_id!(new_data["id"]) @raw_data = new_data end @@ -141,6 +142,7 @@ class Chef if Chef::Config[:solo_legacy_mode] bag = Chef::DataBag.load(data_bag) raise Exceptions::InvalidDataBagItemID, "Item #{name} not found in data bag #{data_bag}. Other items found: #{bag.keys.join(", ")}" unless bag.include?(name) + item = bag[name] else item = Chef::ServerAPI.new(Chef::Config[:chef_server_url]).get("data/#{data_bag}/#{name}") @@ -170,6 +172,7 @@ class Chef end rescue Net::HTTPClientException => e raise e unless e.response.code == "404" + r.post("data/#{data_bag}", self) end self diff --git a/lib/chef/data_collector.rb b/lib/chef/data_collector.rb index b976f9d058..aac864f485 100644 --- a/lib/chef/data_collector.rb +++ b/lib/chef/data_collector.rb @@ -174,6 +174,7 @@ class Chef # def send_to_data_collector(message) return unless Chef::Config[:data_collector][:server_url] + @http ||= setup_http_client(Chef::Config[:data_collector][:server_url]) @http.post(nil, message, headers) rescue Timeout::Error, Errno::EINVAL, Errno::ECONNRESET, diff --git a/lib/chef/data_collector/run_end_message.rb b/lib/chef/data_collector/run_end_message.rb index 70a0b59650..341df5694f 100644 --- a/lib/chef/data_collector/run_end_message.rb +++ b/lib/chef/data_collector/run_end_message.rb @@ -85,12 +85,14 @@ class Chef # @return [Integer] the number of resources successfully updated in the chef-client run def updated_resource_count(action_collection) return 0 if action_collection.nil? + action_collection.filtered_collection(up_to_date: false, skipped: false, unprocessed: false, failed: false).count end # @return [Array<Chef::ActionCollection::ActionRecord>] list of all action_records for all resources def action_records(action_collection) return [] if action_collection.nil? + action_collection.action_records end diff --git a/lib/chef/deprecated.rb b/lib/chef/deprecated.rb index da29285223..cda8e197d3 100644 --- a/lib/chef/deprecated.rb +++ b/lib/chef/deprecated.rb @@ -84,6 +84,7 @@ class Chef relevant_line = location_file.readline relevant_line.match?(/#.*chef:silence_deprecation($|[^:]|:#{self.class.deprecation_key})/) end + false end diff --git a/lib/chef/dsl/declare_resource.rb b/lib/chef/dsl/declare_resource.rb index f23ef466fb..7ae1551c04 100644 --- a/lib/chef/dsl/declare_resource.rb +++ b/lib/chef/dsl/declare_resource.rb @@ -41,6 +41,7 @@ class Chef # def with_run_context(rc) raise ArgumentError, "with_run_context is useless without a block" unless block_given? + old_run_context = @run_context @run_context = case rc @@ -202,6 +203,7 @@ class Chef # def find_resource!(type, name, run_context: self.run_context) raise ArgumentError, "find_resource! does not take a block" if block_given? + run_context.resource_collection.find(type => name) end diff --git a/lib/chef/dsl/platform_introspection.rb b/lib/chef/dsl/platform_introspection.rb index e7f0c60f0d..dfd20b6329 100644 --- a/lib/chef/dsl/platform_introspection.rb +++ b/lib/chef/dsl/platform_introspection.rb @@ -70,6 +70,7 @@ class Chef def match_versions(node) platform, version = node[:platform].to_s, node[:platform_version].to_s return nil unless @values.key?(platform) + node_version = Chef::Version::Platform.new(version) key_matches = [] keys = @values[platform].keys @@ -84,6 +85,7 @@ class Chef end end return @values[platform][version] if key_matches.include?(version) + case key_matches.length when 0 return nil diff --git a/lib/chef/encrypted_data_bag_item.rb b/lib/chef/encrypted_data_bag_item.rb index d23712dd6f..ff8512aec0 100644 --- a/lib/chef/encrypted_data_bag_item.rb +++ b/lib/chef/encrypted_data_bag_item.rb @@ -133,6 +133,7 @@ class Chef::EncryptedDataBagItem if !path raise ArgumentError, "No secret specified and no secret found at #{Chef::Config.platform_specific_path(Chef::Dist::CONF_DIR + '/encrypted_data_bag_secret')}" end + secret = case path when /^\w+:\/\// # We have a remote key @@ -147,11 +148,13 @@ class Chef::EncryptedDataBagItem if !File.exist?(path) raise Errno::ENOENT, "file not found '#{path}'" end + IO.read(path).strip end if secret.size < 1 raise ArgumentError, "invalid zero length secret in '#{path}'" end + secret end diff --git a/lib/chef/encrypted_data_bag_item/check_encrypted.rb b/lib/chef/encrypted_data_bag_item/check_encrypted.rb index 9292ce6650..ab720fa64a 100644 --- a/lib/chef/encrypted_data_bag_item/check_encrypted.rb +++ b/lib/chef/encrypted_data_bag_item/check_encrypted.rb @@ -40,6 +40,7 @@ class Chef::EncryptedDataBagItem # keys and the hash's keys. def looks_like_encrypted?(data) return false unless data.is_a?(Hash) && data.key?("version") + case data["version"] when 1 Chef::EncryptedDataBagItem::Encryptor::Version1Encryptor.encryptor_keys.sort == data.keys.sort diff --git a/lib/chef/encrypted_data_bag_item/decryptor.rb b/lib/chef/encrypted_data_bag_item/decryptor.rb index ce7cdc4036..900a8b7f04 100644 --- a/lib/chef/encrypted_data_bag_item/decryptor.rb +++ b/lib/chef/encrypted_data_bag_item/decryptor.rb @@ -188,6 +188,7 @@ class Chef::EncryptedDataBagItem def candidate_hmac_matches?(expected_hmac) return false unless @encrypted_data["hmac"] + expected_bytes = expected_hmac.bytes.to_a candidate_hmac_bytes = Base64.decode64(@encrypted_data["hmac"]).bytes.to_a valid = expected_bytes.size ^ candidate_hmac_bytes.size @@ -213,6 +214,7 @@ class Chef::EncryptedDataBagItem if auth_tag_b64.nil? raise DecryptionFailure, "Error decrypting data bag value: invalid authentication tag. Most likely the data is corrupted" end + Base64.decode64(auth_tag_b64) end diff --git a/lib/chef/encrypted_data_bag_item/encryptor.rb b/lib/chef/encrypted_data_bag_item/encryptor.rb index 514633b526..1bd79016d3 100644 --- a/lib/chef/encrypted_data_bag_item/encryptor.rb +++ b/lib/chef/encrypted_data_bag_item/encryptor.rb @@ -193,6 +193,7 @@ class Chef::EncryptedDataBagItem if @auth_tag.nil? raise EncryptionFailure, "Internal Error: GCM authentication tag read before encryption" end + @auth_tag end diff --git a/lib/chef/environment.rb b/lib/chef/environment.rb index 0e0f6776ec..6633813762 100644 --- a/lib/chef/environment.rb +++ b/lib/chef/environment.rb @@ -278,6 +278,7 @@ class Chef chef_server_rest.put("environments/#{@name}", self) rescue Net::HTTPClientException => e raise e unless e.response.code == "404" + chef_server_rest.post("environments", self) end self @@ -298,6 +299,7 @@ class Chef def self.validate_cookbook_versions(cv) return false unless cv.kind_of?(Hash) + cv.each_value do |version| return false unless Chef::Environment.validate_cookbook_version(version) end diff --git a/lib/chef/event_dispatch/dispatcher.rb b/lib/chef/event_dispatch/dispatcher.rb index 84f1d05129..31e2afc8af 100644 --- a/lib/chef/event_dispatch/dispatcher.rb +++ b/lib/chef/event_dispatch/dispatcher.rb @@ -61,6 +61,7 @@ class Chef subscribers.each do |s| # Skip new/unsupported event names next if !s.respond_to?(method_name) + mth = s.method(method_name) # Trim arguments to match what the subscriber expects to allow # adding new arguments without breaking compat. diff --git a/lib/chef/event_loggers/base.rb b/lib/chef/event_loggers/base.rb index 2fcc0d2458..89eac20fc9 100644 --- a/lib/chef/event_loggers/base.rb +++ b/lib/chef/event_loggers/base.rb @@ -45,6 +45,7 @@ class Chef event_logger_class = by_name(name.to_s) raise UnknownEventLogger, "No event logger found for #{name} (available: #{available_event_loggers.join(', ')})" unless event_logger_class raise UnavailableEventLogger unless available_event_loggers.include? name.to_s + event_logger_class.new end diff --git a/lib/chef/file_access_control/unix.rb b/lib/chef/file_access_control/unix.rb index 8774ad9498..b412dbfa1b 100644 --- a/lib/chef/file_access_control/unix.rb +++ b/lib/chef/file_access_control/unix.rb @@ -118,6 +118,7 @@ class Chef def gid_from_resource(resource) return nil if resource.nil? || resource.group.nil? + if resource.group.kind_of?(String) diminished_radix_complement( Etc.getgrnam(resource.group).gid ) elsif resource.group.kind_of?(Integer) @@ -169,6 +170,7 @@ class Chef def mode_from_resource(res) return nil if res.nil? || res.mode.nil? + (res.mode.respond_to?(:oct) ? res.mode.oct : res.mode.to_i) & 007777 end @@ -265,6 +267,7 @@ class Chef def uid_from_resource(resource) return nil if resource.nil? || resource.owner.nil? + if resource.owner.kind_of?(String) diminished_radix_complement( Etc.getpwnam(resource.owner).uid ) elsif resource.owner.kind_of?(Integer) diff --git a/lib/chef/file_access_control/windows.rb b/lib/chef/file_access_control/windows.rb index 3a5bcf9278..ebf6f1f126 100644 --- a/lib/chef/file_access_control/windows.rb +++ b/lib/chef/file_access_control/windows.rb @@ -125,12 +125,14 @@ class Chef so = Chef::ReservedNames::Win32::Security::SecurableObject.new(file.dup) end raise ArgumentError, "'file' must be a valid path or object of type 'Chef::ReservedNames::Win32::Security::SecurableObject'" unless so.kind_of? Chef::ReservedNames::Win32::Security::SecurableObject + so end end def should_update_dacl? return true unless ::File.exists?(file) || ::File.symlink?(file) + dacl = target_dacl existing_dacl = existing_descriptor.dacl inherits = target_inherits @@ -164,6 +166,7 @@ class Chef def should_update_group? return true unless ::File.exists?(file) || ::File.symlink?(file) + (group = target_group) && (group != existing_descriptor.group) end @@ -183,6 +186,7 @@ class Chef def should_update_owner? return true unless ::File.exists?(file) || ::File.symlink?(file) + (owner = target_owner) && (owner != existing_descriptor.owner) end @@ -206,6 +210,7 @@ class Chef mask |= (GENERIC_WRITE | DELETE) if mode & 2 != 0 mask |= GENERIC_EXECUTE if mode & 1 != 0 return [] if mask == 0 + [ ACE.access_allowed(sid, mask) ] end @@ -266,6 +271,7 @@ class Chef def target_dacl return nil if resource.rights.nil? && resource.deny_rights.nil? && resource.mode.nil? + acls = nil if !resource.deny_rights.nil? @@ -321,6 +327,7 @@ class Chef def target_group return nil if resource.group.nil? + get_sid(resource.group) end @@ -330,6 +337,7 @@ class Chef def target_owner return nil if resource.owner.nil? + get_sid(resource.owner) end end diff --git a/lib/chef/file_cache.rb b/lib/chef/file_cache.rb index ad271a9192..1955dbb165 100644 --- a/lib/chef/file_cache.rb +++ b/lib/chef/file_cache.rb @@ -113,6 +113,7 @@ class Chef ) cache_path = create_cache_path(path, false) raise Chef::Exceptions::FileNotFound, "Cannot find #{cache_path} for #{path}!" unless File.exists?(cache_path) + if read File.read(cache_path) else diff --git a/lib/chef/formatters/doc.rb b/lib/chef/formatters/doc.rb index 77deff5b66..43498cba1a 100644 --- a/lib/chef/formatters/doc.rb +++ b/lib/chef/formatters/doc.rb @@ -306,6 +306,7 @@ class Chef prefix = Chef::Config[:why_run] ? "Would " : "" Array(update).each do |line| next if line.nil? + output_record line if line.kind_of? String start_line "- #{prefix}#{line}", :green @@ -358,6 +359,7 @@ class Chef # in whyrun mode, in order to allow execution to continue def whyrun_assumption(action, resource, message) return unless message + [ message ].flatten.each do |line| start_line("* #{line}", :yellow) end @@ -366,6 +368,7 @@ class Chef # Called when an assertion declared by a provider fails def provider_requirement_failed(action, resource, exception, message) return unless message + color = Chef::Config[:why_run] ? :yellow : :red [ message ].flatten.each do |line| start_line("* #{line}", color) diff --git a/lib/chef/formatters/error_inspectors/cookbook_resolve_error_inspector.rb b/lib/chef/formatters/error_inspectors/cookbook_resolve_error_inspector.rb index 89d4ba7bce..b6fc4c6e14 100644 --- a/lib/chef/formatters/error_inspectors/cookbook_resolve_error_inspector.rb +++ b/lib/chef/formatters/error_inspectors/cookbook_resolve_error_inspector.rb @@ -151,6 +151,7 @@ class Chef if error_description.kind_of?(Hash) return error_description end + attempt_json_parse(error_description) end diff --git a/lib/chef/formatters/error_inspectors/resource_failure_inspector.rb b/lib/chef/formatters/error_inspectors/resource_failure_inspector.rb index 3fd6094ae0..975bb39bd0 100644 --- a/lib/chef/formatters/error_inspectors/resource_failure_inspector.rb +++ b/lib/chef/formatters/error_inspectors/resource_failure_inspector.rb @@ -63,9 +63,11 @@ class Chef def recipe_snippet return nil if dynamic_resource? + @snippet ||= begin if (file = parse_source) && (line = parse_line(file)) return nil unless ::File.exists?(file) + lines = IO.readlines(file) relevant_lines = ["# In #{file}\n\n"] diff --git a/lib/chef/http.rb b/lib/chef/http.rb index f5ad71c694..546b9c0fbe 100644 --- a/lib/chef/http.rb +++ b/lib/chef/http.rb @@ -186,6 +186,7 @@ class Chef apply_stream_complete_middleware(http_response, rest_request, return_value) end return nil if response.kind_of?(Net::HTTPRedirection) + unless response.kind_of?(Net::HTTPSuccess) response.error! end @@ -233,6 +234,7 @@ class Chef end return nil if response.kind_of?(Net::HTTPRedirection) + unless response.kind_of?(Net::HTTPSuccess) response.error! end @@ -309,6 +311,7 @@ class Chef # @api private def create_url(path) return path if path.is_a?(URI) + if path =~ /^(http|https|chefzero):\/\//i URI.parse(path) elsif path.nil? || path.empty? @@ -479,6 +482,7 @@ class Chef # @api private def follow_redirect raise Chef::Exceptions::RedirectLimitExceeded if @redirects_followed >= redirect_limit + @redirects_followed += 1 Chef::Log.trace("Following redirect #{@redirects_followed}/#{redirect_limit}") @@ -498,6 +502,7 @@ class Chef return nil unless response.kind_of?(Net::HTTPRedirection) # Net::HTTPNotModified is undesired subclass of Net::HTTPRedirection so test for this return nil if response.kind_of?(Net::HTTPNotModified) + response["location"] end diff --git a/lib/chef/http/auth_credentials.rb b/lib/chef/http/auth_credentials.rb index e761c97e9b..a1542d1f93 100644 --- a/lib/chef/http/auth_credentials.rb +++ b/lib/chef/http/auth_credentials.rb @@ -40,6 +40,7 @@ class Chef def signature_headers(request_params = {}) raise ArgumentError, "Cannot sign the request without a client name, check that :node_name is assigned" if client_name.nil? + Chef::Log.trace("Signing the request as #{client_name}") # params_in = {:http_method => :GET, :path => "/clients", :body => "", :host => "localhost"} diff --git a/lib/chef/http/decompressor.rb b/lib/chef/http/decompressor.rb index f43f054366..3c3960e02f 100644 --- a/lib/chef/http/decompressor.rb +++ b/lib/chef/http/decompressor.rb @@ -64,6 +64,7 @@ class Chef # temporary hack, skip processing if return_value is false # needed to keep conditional get stuff working correctly. return [http_response, rest_request, return_value] if return_value == false + response_body = decompress_body(http_response) http_response.body.replace(response_body) if http_response.body.respond_to?(:replace) [http_response, rest_request, return_value] diff --git a/lib/chef/http/json_output.rb b/lib/chef/http/json_output.rb index 5fe2622f94..f2c3e81f95 100644 --- a/lib/chef/http/json_output.rb +++ b/lib/chef/http/json_output.rb @@ -46,6 +46,7 @@ class Chef # temporary hack, skip processing if return_value is false # needed to keep conditional get stuff working correctly. return [http_response, rest_request, return_value] if return_value == false + if http_response["content-type"] =~ /json/ if http_response.body.nil? return_value = nil diff --git a/lib/chef/http/socketless_chef_zero_client.rb b/lib/chef/http/socketless_chef_zero_client.rb index 61673c28a6..95f511a4d3 100644 --- a/lib/chef/http/socketless_chef_zero_client.rb +++ b/lib/chef/http/socketless_chef_zero_client.rb @@ -181,6 +181,7 @@ class Chef body = chunked_body.join("") msg = STATUS_MESSAGE[code] raise "Cannot determine HTTP status message for code #{code}" unless msg + response = Net::HTTPResponse.send(:response_class, code.to_s).new("1.0", code.to_s, msg) response.instance_variable_set(:@body, body) headers.each do |name, value| diff --git a/lib/chef/http/ssl_policies.rb b/lib/chef/http/ssl_policies.rb index 3f7dd34404..a299a8d7ca 100644 --- a/lib/chef/http/ssl_policies.rb +++ b/lib/chef/http/ssl_policies.rb @@ -62,11 +62,13 @@ class Chef unless ::File.exist?(config[:ssl_ca_path]) raise Chef::Exceptions::ConfigurationError, "The configured ssl_ca_path #{config[:ssl_ca_path]} does not exist" end + http_client.ca_path = config[:ssl_ca_path] elsif config[:ssl_ca_file] unless ::File.exist?(config[:ssl_ca_file]) raise Chef::Exceptions::ConfigurationError, "The configured ssl_ca_file #{config[:ssl_ca_file]} does not exist" end + http_client.ca_file = config[:ssl_ca_file] end end @@ -96,6 +98,7 @@ class Chef unless ::File.exists?(config[:ssl_client_key]) raise Chef::Exceptions::ConfigurationError, "The configured ssl_client_key #{config[:ssl_client_key]} does not exist" end + http_client.cert = OpenSSL::X509::Certificate.new(::File.read(config[:ssl_client_cert])) http_client.key = OpenSSL::PKey::RSA.new(::File.read(config[:ssl_client_key])) end diff --git a/lib/chef/http/validate_content_length.rb b/lib/chef/http/validate_content_length.rb index 1b1a8a398a..e5e514459f 100644 --- a/lib/chef/http/validate_content_length.rb +++ b/lib/chef/http/validate_content_length.rb @@ -74,6 +74,7 @@ class Chef def response_content_length(response) return nil if response["content-length"].nil? + if response["content-length"].is_a?(Array) response["content-length"].first.to_i else diff --git a/lib/chef/key.rb b/lib/chef/key.rb index 7f4591c2c7..632820efa4 100644 --- a/lib/chef/key.rb +++ b/lib/chef/key.rb @@ -87,6 +87,7 @@ class Chef def public_key(arg = nil) raise Chef::Exceptions::InvalidKeyAttribute, "you cannot set the public_key if create_key is true" if !arg.nil? && @create_key + set_or_return(:public_key, arg, kind_of: String) end @@ -106,6 +107,7 @@ class Chef def create_key(arg = nil) raise Chef::Exceptions::InvalidKeyAttribute, "you cannot set create_key to true if the public_key field exists" if arg == true && !@public_key.nil? + set_or_return(:create_key, arg, kind_of: [TrueClass, FalseClass]) end diff --git a/lib/chef/knife.rb b/lib/chef/knife.rb index 48226bb344..02f38e9f89 100644 --- a/lib/chef/knife.rb +++ b/lib/chef/knife.rb @@ -244,6 +244,7 @@ class Chef 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) @@ -386,6 +387,7 @@ class Chef return :cli if @original_config.include? key return :config if config_file_settings.key? key return :cli_default if default_config.include? key + nil end @@ -476,6 +478,7 @@ class Chef end rescue Exception => e raise if raise_exception || ( Chef::Config[:verbosity] && Chef::Config[:verbosity] >= 2 ) + humanize_exception(e) exit 100 end diff --git a/lib/chef/knife/bootstrap.rb b/lib/chef/knife/bootstrap.rb index 13f8731c77..7eb20e6dfb 100644 --- a/lib/chef/knife/bootstrap.rb +++ b/lib/chef/knife/bootstrap.rb @@ -195,6 +195,7 @@ class Chef unless valid_values.include?(v) raise "Invalid value '#{v}' for --node-ssl-verify-mode. Valid values are: #{valid_values.join(", ")}" end + v } @@ -647,6 +648,7 @@ class Chef q.echo = false end end + opts.merge! force_ssh_password_opts(password) do_connect(opts) else @@ -661,6 +663,7 @@ class Chef # we'll use the one that you gave in the URL. def connection_protocol return @connection_protocol if @connection_protocol + from_url = host_descriptor =~ /^(.*):\/\// ? $1 : nil from_cli = config[:connection_protocol] from_knife = Chef::Config[:knife][:connection_protocol] @@ -678,6 +681,7 @@ class Chef if @config[:first_boot_attributes] && @config[:first_boot_attributes_from_file] raise Chef::Exceptions::BootstrapCommandInputError end + true end @@ -842,6 +846,7 @@ class Chef # host via train def connection_opts(reset: false) return @connection_opts unless @connection_opts.nil? || reset == true + @connection_opts = {} @connection_opts.merge! base_opts @connection_opts.merge! host_verify_opts @@ -892,6 +897,7 @@ class Chef def ssh_opts opts = {} return opts if winrm? + opts[:pty] = true # ensure we can talk to systems with requiretty set true in sshd config opts[:non_interactive] = true # Prevent password prompts from underlying net/ssh opts[:forward_agent] = (config_value(:ssh_forward_agent) === true) @@ -902,6 +908,7 @@ class Chef def ssh_identity_opts opts = {} return opts if winrm? + identity_file = config_value(:ssh_identity_file) if identity_file opts[:key_files] = [identity_file] @@ -962,6 +969,7 @@ class Chef # should we change that for consistency? def sudo_opts return {} if winrm? + opts = { sudo: false } if config[:use_sudo] opts[:sudo] = true @@ -977,6 +985,7 @@ class Chef def winrm_opts return {} unless winrm? + auth_method = config_value(:winrm_auth_method, :winrm_auth_method, "negotiate") opts = { winrm_transport: auth_method, # winrm gem and train calls auth method 'transport' @@ -1085,6 +1094,7 @@ class Chef def session_timeout timeout = config_value(:session_timeout) return options[:session_timeout][:default] if timeout.nil? + timeout.to_i end end diff --git a/lib/chef/knife/bootstrap/chef_vault_handler.rb b/lib/chef/knife/bootstrap/chef_vault_handler.rb index 605a9d359b..b6a292fda0 100644 --- a/lib/chef/knife/bootstrap/chef_vault_handler.rb +++ b/lib/chef/knife/bootstrap/chef_vault_handler.rb @@ -145,6 +145,7 @@ class Chef if Gem::Version.new(ChefVault::VERSION) < Gem::Version.new("2.6.0") raise error_message end + true rescue LoadError raise error_message diff --git a/lib/chef/knife/bootstrap/client_builder.rb b/lib/chef/knife/bootstrap/client_builder.rb index 87dd03d6ed..3dee318414 100644 --- a/lib/chef/knife/bootstrap/client_builder.rb +++ b/lib/chef/knife/bootstrap/client_builder.rb @@ -188,6 +188,7 @@ class Chef true rescue Net::HTTPClientException => e raise unless e.response.code == "404" + false end diff --git a/lib/chef/knife/bootstrap/train_connector.rb b/lib/chef/knife/bootstrap/train_connector.rb index da5db65de0..490be38f3e 100644 --- a/lib/chef/knife/bootstrap/train_connector.rb +++ b/lib/chef/knife/bootstrap/train_connector.rb @@ -213,6 +213,7 @@ class Chef if result.exit_status != 0 raise RemoteExecutionFailed.new(hostname, command, result) end + result end @@ -247,6 +248,7 @@ class Chef # Return a hash of winrm options based on configuration already built. def opts_inferred_from_winrm(config, opts_in) return {} unless config[:backend] == "winrm" + opts_out = {} if opts_in[:ssl] @@ -296,6 +298,7 @@ class Chef # itself - causing SSH config data to be ignored def missing_opts_from_ssh_config(config, opts_in) return {} unless config[:backend] == "ssh" + host_cfg = ssh_config_for_host(config[:host]) opts_out = {} opts_in.each do |key, _value| diff --git a/lib/chef/knife/client_bulk_delete.rb b/lib/chef/knife/client_bulk_delete.rb index 703ccb7747..6997110612 100644 --- a/lib/chef/knife/client_bulk_delete.rb +++ b/lib/chef/knife/client_bulk_delete.rb @@ -45,6 +45,7 @@ class Chef validators_to_delete = {} all_clients.each do |name, client| next unless name =~ matcher + if client.validator validators_to_delete[client.name] = client else diff --git a/lib/chef/knife/core/subcommand_loader.rb b/lib/chef/knife/core/subcommand_loader.rb index f2dc06ce36..5b9474515a 100644 --- a/lib/chef/knife/core/subcommand_loader.rb +++ b/lib/chef/knife/core/subcommand_loader.rb @@ -82,6 +82,7 @@ class Chef # Load all the sub-commands def load_commands return true if @loaded + subcommand_files.each { |subcommand| Kernel.load subcommand } @loaded = true end diff --git a/lib/chef/knife/core/ui.rb b/lib/chef/knife/core/ui.rb index 7961e1b523..663db90585 100644 --- a/lib/chef/knife/core/ui.rb +++ b/lib/chef/knife/core/ui.rb @@ -69,6 +69,7 @@ class Chef stdout.puts message rescue Errno::EPIPE => e raise e if @config[:verbosity] >= 2 + exit 0 end @@ -85,6 +86,7 @@ class Chef unless lines.empty? prefix, = first_line.split(":", 2) return if prefix.nil? + prefix_len = prefix.length prefix_len -= 9 if color? # prefix includes 9 bytes of color escape sequences prefix_len += 2 # include room to align to the ": " following PREFIX @@ -95,6 +97,7 @@ class Chef end rescue Errno::EPIPE => e raise e if @config[:verbosity] >= 2 + exit 0 end @@ -186,6 +189,7 @@ class Chef stdout.puts data rescue Errno::EPIPE => e raise e if @config[:verbosity] >= 2 + exit 0 end diff --git a/lib/chef/knife/data_bag_create.rb b/lib/chef/knife/data_bag_create.rb index 92ea981a2b..c520bba570 100644 --- a/lib/chef/knife/data_bag_create.rb +++ b/lib/chef/knife/data_bag_create.rb @@ -55,6 +55,7 @@ class Chef ui.info("Data bag #{@data_bag_name} already exists") rescue Net::HTTPClientException => e raise unless e.to_s =~ /^404/ + # if it doesn't exists, try to create it rest.post("data", { "name" => @data_bag_name }) ui.info("Created data_bag[#{@data_bag_name}]") diff --git a/lib/chef/knife/environment_compare.rb b/lib/chef/knife/environment_compare.rb index b00fc4fc3b..38e259a856 100644 --- a/lib/chef/knife/environment_compare.rb +++ b/lib/chef/knife/environment_compare.rb @@ -109,6 +109,7 @@ class Chef environments.each { |n| total << constraints[n][c] } if total.uniq.count == 1 next if config[:mismatch] + color = :white else color = :yellow diff --git a/lib/chef/knife/key_list.rb b/lib/chef/knife/key_list.rb index 5295238f6f..aefb1928df 100644 --- a/lib/chef/knife/key_list.rb +++ b/lib/chef/knife/key_list.rb @@ -70,6 +70,7 @@ class Chef keys.each do |key| next if !key["expired"] && @config[:only_expired] next if key["expired"] && @config[:only_non_expired] + display = "#{colorize(key['name'].ljust(max_length))} #{key['uri']}" display = "#{display} (expired)" if key["expired"] display_info(display) @@ -78,6 +79,7 @@ class Chef keys.each do |key| next if !key["expired"] && @config[:only_expired] next if key["expired"] && @config[:only_non_expired] + display_info(key["name"]) end end diff --git a/lib/chef/knife/node_bulk_delete.rb b/lib/chef/knife/node_bulk_delete.rb index 04d19648d2..030260b944 100644 --- a/lib/chef/knife/node_bulk_delete.rb +++ b/lib/chef/knife/node_bulk_delete.rb @@ -40,6 +40,7 @@ class Chef all_nodes.each do |name, node| next unless name =~ matcher + nodes_to_delete[name] = node end diff --git a/lib/chef/knife/role_bulk_delete.rb b/lib/chef/knife/role_bulk_delete.rb index 7e5fafb26b..1277c966be 100644 --- a/lib/chef/knife/role_bulk_delete.rb +++ b/lib/chef/knife/role_bulk_delete.rb @@ -41,6 +41,7 @@ class Chef roles_to_delete = {} all_roles.each do |name, role| next unless name =~ matcher + roles_to_delete[role.name] = role end diff --git a/lib/chef/knife/ssh.rb b/lib/chef/knife/ssh.rb index e979002c75..c7bf57325f 100644 --- a/lib/chef/knife/ssh.rb +++ b/lib/chef/knife/ssh.rb @@ -245,10 +245,12 @@ class Chef # we should skip the loop to next iteration if the item # returned by the search is nil next if item.nil? + # next if we couldn't find the specified attribute in the # returned node object host = get_ssh_attribute(item) next if host.nil? + prefix = get_prefix_attribute(item) ssh_port = item.dig("cloud", "public_ssh_port") srv = [host, ssh_port, prefix] @@ -363,6 +365,7 @@ class Chef chan.request_pty chan.exec command do |ch, success| raise ArgumentError, "Cannot execute #{command}" unless success + ch.on_data do |ichannel, data| print_data(ichannel.connection[:prefix], data) if data =~ /^knife sudo password: / @@ -545,6 +548,7 @@ class Chef def get_stripped_unfrozen_value(value) return nil if value.nil? + value.strip end diff --git a/lib/chef/knife/supermarket_share.rb b/lib/chef/knife/supermarket_share.rb index f0c0970f9d..b4fd933fa1 100644 --- a/lib/chef/knife/supermarket_share.rb +++ b/lib/chef/knife/supermarket_share.rb @@ -114,6 +114,7 @@ class Chef data["category"] rescue => e return "Other" if e.kind_of?(Net::HTTPClientException) && e.response.code == "404" + ui.fatal("Unable to reach Supermarket: #{e.message}. Increase log verbosity (-VV) for more information.") Chef::Log.trace("\n#{e.backtrace.join("\n")}") exit(1) diff --git a/lib/chef/knife/supermarket_unshare.rb b/lib/chef/knife/supermarket_unshare.rb index acdcf53f85..352d34fdb1 100644 --- a/lib/chef/knife/supermarket_unshare.rb +++ b/lib/chef/knife/supermarket_unshare.rb @@ -50,6 +50,7 @@ class Chef rest.delete "#{config[:supermarket_site]}/api/v1/cookbooks/#{@name_args[0]}" rescue Net::HTTPClientException => e raise e unless e.message =~ /Forbidden/ + ui.error "Forbidden: You must be the maintainer of #{@cookbook_name} to unshare it." exit 1 end diff --git a/lib/chef/log/syslog.rb b/lib/chef/log/syslog.rb index 7e63bbb553..dbc30da0e6 100644 --- a/lib/chef/log/syslog.rb +++ b/lib/chef/log/syslog.rb @@ -36,6 +36,7 @@ class Chef def initialize(program_name = "#{Chef::Dist::CLIENT}", facility = ::Syslog::LOG_DAEMON, logopts = nil) super return if defined? ::Logger::Syslog::SYSLOG + ::Logger::Syslog.const_set :SYSLOG, SYSLOG end diff --git a/lib/chef/mixin/checksum.rb b/lib/chef/mixin/checksum.rb index 5394c5ea48..6b9dfa4b5f 100644 --- a/lib/chef/mixin/checksum.rb +++ b/lib/chef/mixin/checksum.rb @@ -29,6 +29,7 @@ class Chef def short_cksum(checksum) return "none" if checksum.nil? + checksum.slice(0, 6) end diff --git a/lib/chef/mixin/convert_to_class_name.rb b/lib/chef/mixin/convert_to_class_name.rb index d6bd8a4ea7..a65fa87655 100644 --- a/lib/chef/mixin/convert_to_class_name.rb +++ b/lib/chef/mixin/convert_to_class_name.rb @@ -112,6 +112,7 @@ class Chef constant = constant.ancestors.inject do |const, ancestor| break const if ancestor == Object break ancestor if ancestor.const_defined?(name, false) + const end diff --git a/lib/chef/mixin/get_source_from_package.rb b/lib/chef/mixin/get_source_from_package.rb index 832f96064d..9aafcc6ae4 100644 --- a/lib/chef/mixin/get_source_from_package.rb +++ b/lib/chef/mixin/get_source_from_package.rb @@ -35,6 +35,7 @@ class Chef def initialize(new_resource, run_context) super return if new_resource.package_name.is_a?(Array) + # if we're passed something that looks like a filesystem path, with no source, use it # - require at least one '/' in the path to avoid gem_package "foo" breaking if a file named 'foo' exists in the cwd if new_resource.source.nil? && new_resource.package_name.match(/#{::File::SEPARATOR}/) && ::File.exist?(new_resource.package_name) diff --git a/lib/chef/mixin/homebrew_user.rb b/lib/chef/mixin/homebrew_user.rb index 82dbb36f6c..bf608b539b 100644 --- a/lib/chef/mixin/homebrew_user.rb +++ b/lib/chef/mixin/homebrew_user.rb @@ -40,6 +40,7 @@ class Chef # They could provide us a user name or a UID if provided_user return provided_user if provided_user.is_a? Integer + return Etc.getpwnam(provided_user).uid end diff --git a/lib/chef/mixin/openssl_helper.rb b/lib/chef/mixin/openssl_helper.rb index 2312d606ad..6a8a288451 100644 --- a/lib/chef/mixin/openssl_helper.rb +++ b/lib/chef/mixin/openssl_helper.rb @@ -46,6 +46,7 @@ class Chef # Check if the dhparam.pem file exists # Verify the dhparam.pem file contains a key return false unless ::File.exist?(dhparam_pem_path) + dhparam = ::OpenSSL::PKey::DH.new File.read(dhparam_pem_path) dhparam.params_ok? end @@ -158,6 +159,7 @@ class Chef def gen_ec_priv_key(curve) raise TypeError, "curve must be a string" unless curve.is_a?(String) raise ArgumentError, "Specified curve is not available on this system" unless curve == "prime256v1" || curve == "secp384r1" || curve == "secp521r1" + ::OpenSSL::PKey::EC.new(curve).generate_key end @@ -275,6 +277,7 @@ class Chef extension << ef.create_extension("basicConstraints", "CA:TRUE", true) else raise TypeError, "info['issuer'] must be a Ruby OpenSSL::X509::Certificate object" unless info["issuer"].is_a?(::OpenSSL::X509::Certificate) + cert.issuer = info["issuer"].subject ef.issuer_certificate = info["issuer"] end @@ -325,6 +328,7 @@ class Chef # @return [Integer] def get_next_crl_number(crl) raise TypeError, "crl must be a Ruby OpenSSL::X509::CRL object" unless crl.is_a?(::OpenSSL::X509::CRL) + crlnum = 1 crl.extensions.each do |e| crlnum = e.value if e.oid == "crlNumber" diff --git a/lib/chef/mixin/params_validate.rb b/lib/chef/mixin/params_validate.rb index 0f18eb4f54..eafe50382b 100644 --- a/lib/chef/mixin/params_validate.rb +++ b/lib/chef/mixin/params_validate.rb @@ -151,6 +151,7 @@ class Chef if is_required return true if opts.key?(key.to_s) && (explicitly_allows_nil || !opts[key.to_s].nil?) return true if opts.key?(key.to_sym) && (explicitly_allows_nil || !opts[key.to_sym].nil?) + raise Exceptions::ValidationFailed, _validation_message(key, "Required argument #{key.inspect} is missing!") end true @@ -320,6 +321,7 @@ class Chef # def _pv_callbacks(opts, key, callbacks) raise ArgumentError, "Callback list must be a hash!" unless callbacks.kind_of?(Hash) + value = _pv_opts_lookup(opts, key) if !value.nil? callbacks.each do |message, zeproc| @@ -342,6 +344,7 @@ class Chef if is_name_property if opts[key].nil? raise Exceptions::CannotValidateStaticallyError, "name_property cannot be evaluated without a resource." if self == Chef::Mixin::ParamsValidate + opts[key] = instance_variable_get(:"@name") end end @@ -407,6 +410,7 @@ class Chef # def _pv_is(opts, key, to_be) return true if !opts.key?(key.to_s) && !opts.key?(key.to_sym) + value = _pv_opts_lookup(opts, key) to_be = [ to_be ].flatten(1) errors = [] @@ -414,6 +418,7 @@ class Chef case tb when Proc raise Exceptions::CannotValidateStaticallyError, "is: proc { } must be evaluated once for each resource" if self == Chef::Mixin::ParamsValidate + instance_exec(value, &tb) when Property begin @@ -422,6 +427,7 @@ class Chef rescue Exceptions::ValidationFailed # re-raise immediately if there is only one "is" so we get a better stack raise if to_be.size == 1 + errors << $! false end @@ -458,9 +464,11 @@ class Chef def _pv_coerce(opts, key, coercer) if opts.key?(key.to_s) raise Exceptions::CannotValidateStaticallyError, "coerce must be evaluated for each resource." if self == Chef::Mixin::ParamsValidate + opts[key.to_s] = instance_exec(opts[key], &coercer) elsif opts.key?(key.to_sym) raise Exceptions::CannotValidateStaticallyError, "coerce must be evaluated for each resource." if self == Chef::Mixin::ParamsValidate + opts[key.to_sym] = instance_exec(opts[key], &coercer) end end diff --git a/lib/chef/mixin/properties.rb b/lib/chef/mixin/properties.rb index 03ee1d66cc..faf047885c 100644 --- a/lib/chef/mixin/properties.rb +++ b/lib/chef/mixin/properties.rb @@ -289,6 +289,7 @@ class Chef def property_is_set?(name) property = self.class.properties[name.to_sym] raise ArgumentError, "Property #{name} is not defined in class #{self}" if !property + property.is_set?(self) end @@ -302,6 +303,7 @@ class Chef def reset_property(name) property = self.class.properties[name.to_sym] raise ArgumentError, "Property #{name} is not defined in class #{self}" if !property + property.reset(self) end @@ -313,6 +315,7 @@ class Chef def property_description(name) property = self.class.properties[name.to_sym] raise ArgumentError, "Property #{name} is not defined in class #{self}" if !property + property.description end diff --git a/lib/chef/mixin/shell_out.rb b/lib/chef/mixin/shell_out.rb index 9f7b18eace..5fc7c249b9 100644 --- a/lib/chef/mixin/shell_out.rb +++ b/lib/chef/mixin/shell_out.rb @@ -75,6 +75,7 @@ class Chef # historically resources have not properly declared defaults on their timeouts, so a default default of 900s was enforced here default_val = 900 return options if options.key?(:timeout) + # FIXME: need to nuke descendents tracker out of Chef::Provider so we can just define that class here without requiring the # world, and then just use symbol lookup if obj.class.ancestors.map(&:name).include?("Chef::Provider") && obj.respond_to?(:new_resource) && obj.new_resource.respond_to?(:timeout) && !options.key?(:timeout) diff --git a/lib/chef/mixin/template.rb b/lib/chef/mixin/template.rb index f32b560e0e..38de13e6b6 100644 --- a/lib/chef/mixin/template.rb +++ b/lib/chef/mixin/template.rb @@ -102,6 +102,7 @@ class Chef # by the bare `node` everywhere. def node return @node if @node + raise "Could not find a value for node. If you are explicitly setting variables in a template, " + "include a node variable if you plan to use it." end diff --git a/lib/chef/mixin/which.rb b/lib/chef/mixin/which.rb index 974cb50fa3..a51963b6c2 100644 --- a/lib/chef/mixin/which.rb +++ b/lib/chef/mixin/which.rb @@ -56,6 +56,7 @@ class Chef File.executable?(filename) && !File.directory?(filename) end return false unless is_executable + block ? yield(filename) : true end end diff --git a/lib/chef/monkey_patches/webrick-utils.rb b/lib/chef/monkey_patches/webrick-utils.rb index c90c9fe251..fa52a753c4 100644 --- a/lib/chef/monkey_patches/webrick-utils.rb +++ b/lib/chef/monkey_patches/webrick-utils.rb @@ -24,6 +24,7 @@ module WEBrick unless port raise ArgumentError, "must specify port" end + res = Socket.getaddrinfo(address, port, Socket::AF_UNSPEC, # address family Socket::SOCK_STREAM, # socket type @@ -44,6 +45,7 @@ module WEBrick end end raise last_error if sockets.empty? + sockets end module_function :create_listeners diff --git a/lib/chef/node.rb b/lib/chef/node.rb index a6a7c06dc4..cefd656609 100644 --- a/lib/chef/node.rb +++ b/lib/chef/node.rb @@ -90,6 +90,7 @@ class Chef # and setup the node[:cookbooks] attribute so that it is published in the node object def set_cookbook_attribute return unless run_context.cookbook_collection + run_context.cookbook_collection.each do |cookbook_name, cookbook| automatic_attrs[:cookbooks][cookbook_name][:version] = cookbook.version end @@ -152,6 +153,7 @@ class Chef # @return [String] the current policy_name, or the one you just set def policy_name(arg = NULL_ARG) return @policy_name if arg.equal?(NULL_ARG) + validate({ policy_name: arg }, { policy_name: { kind_of: [ String, NilClass ], regex: /^[\-:.[:alnum:]_]+$/ } }) @policy_name = arg end @@ -174,6 +176,7 @@ class Chef # @return [String] the current policy_group, or the one you just set def policy_group(arg = NULL_ARG) return @policy_group if arg.equal?(NULL_ARG) + validate({ policy_group: arg }, { policy_group: { kind_of: [ String, NilClass ], regex: /^[\-:.[:alnum:]_]+$/ } }) @policy_group = arg end @@ -316,6 +319,7 @@ class Chef # @return [Chef::RunList] the override run list def override_runlist(*args) return @override_runlist if args.length == 0 + @override_runlist_set = true @override_runlist.reset!(args) end @@ -403,6 +407,7 @@ class Chef if attrs.key?("recipes") || attrs.key?("run_list") raise Chef::Exceptions::AmbiguousRunlistSpecification, "please set the node's run list using the 'run_list' attribute only." end + logger.info("Setting the run_list to #{new_run_list} from CLI options") run_list(new_run_list) end @@ -543,6 +548,7 @@ class Chef def self.from_hash(o) return o if o.kind_of? Chef::Node + node = new node.name(o["name"]) @@ -599,6 +605,7 @@ class Chef load(node_name) rescue Net::HTTPClientException => e raise unless e.response.code == "404" + node = build(node_name) node.create end @@ -679,6 +686,7 @@ class Chef chef_server_rest.put("nodes/#{name}", trimmed_data) rescue Net::HTTPClientException => e raise e unless e.response.code == "404" + chef_server_rest.post("nodes", trimmed_data) end diff --git a/lib/chef/node/attribute.rb b/lib/chef/node/attribute.rb index eac867899c..2fc5d55a8e 100644 --- a/lib/chef/node/attribute.rb +++ b/lib/chef/node/attribute.rb @@ -341,6 +341,7 @@ class Chef def with_deep_merged_return_value(obj, *path, last) hash = obj.read(*path) return nil unless hash.is_a?(Hash) + ret = hash[last] yield ret @@ -357,6 +358,7 @@ class Chef # - this API autovivifies (and cannot trainwreck) def default!(*args) return Decorator::Unchain.new(self, :default!) unless args.length > 0 + write(:default, *args) end @@ -365,6 +367,7 @@ class Chef # - this API autovivifies (and cannot trainwreck) def normal!(*args) return Decorator::Unchain.new(self, :normal!) unless args.length > 0 + write(:normal, *args) end @@ -373,6 +376,7 @@ class Chef # - this API autovivifies (and cannot trainwreck) def override!(*args) return Decorator::Unchain.new(self, :override!) unless args.length > 0 + write(:override, *args) end @@ -381,6 +385,7 @@ class Chef # - this API autovivifies (and cannot trainwreck) def force_default!(*args) return Decorator::Unchain.new(self, :force_default!) unless args.length > 0 + value = args.pop rm_default(*args) write(:force_default, *args, value) @@ -389,6 +394,7 @@ class Chef # clears from all override precedence levels and then sets force_override def force_override!(*args) return Decorator::Unchain.new(self, :force_override!) unless args.length > 0 + value = args.pop rm_override(*args) write(:force_override, *args, value) @@ -417,16 +423,19 @@ class Chef def normal_unless(*args) return Decorator::Unchain.new(self, :normal_unless) unless args.length > 0 + write(:normal, *args) if normal.read(*args[0...-1]).nil? end def default_unless(*args) return Decorator::Unchain.new(self, :default_unless) unless args.length > 0 + write(:default, *args) if default.read(*args[0...-1]).nil? end def override_unless(*args) return Decorator::Unchain.new(self, :override_unless) unless args.length > 0 + write(:override, *args) if override.read(*args[0...-1]).nil? end diff --git a/lib/chef/node/common_api.rb b/lib/chef/node/common_api.rb index a703c1ef54..229103556b 100644 --- a/lib/chef/node/common_api.rb +++ b/lib/chef/node/common_api.rb @@ -59,9 +59,11 @@ class Chef last = args.pop obj = args.inject(self) do |memo, key| raise Chef::Exceptions::AttributeTypeMismatch unless valid_container?(memo, key) + memo[key] end raise Chef::Exceptions::AttributeTypeMismatch unless valid_container?(obj, last) + obj[last] = value end @@ -71,6 +73,7 @@ class Chef def exist?(*path) path.inject(self) do |memo, key| return false unless valid_container?(memo, key) + if memo.is_a?(Hash) if memo.key?(key) memo[key] @@ -98,6 +101,7 @@ class Chef # non-autovivifying reader that throws an exception if the attribute does not exist def read!(*path) raise Chef::Exceptions::NoSuchAttribute unless exist?(*path) + path.inject(self) do |memo, key| memo[key] end @@ -108,11 +112,13 @@ class Chef def unlink(*path, last) hash = path.empty? ? self : read(*path) return nil unless hash.is_a?(Hash) || hash.is_a?(Array) + hash.delete(last) end def unlink!(*path) raise Chef::Exceptions::NoSuchAttribute unless exist?(*path) + unlink(*path) end diff --git a/lib/chef/node_map.rb b/lib/chef/node_map.rb index f54b3dc6bb..c2715965eb 100644 --- a/lib/chef/node_map.rb +++ b/lib/chef/node_map.rb @@ -120,6 +120,7 @@ class Chef # def get(node, key, canonical: nil) return nil unless map.key?(key) + map[key].map do |matcher| return matcher[:klass] if node_matches?(node, matcher) && canonical_matches?(canonical, matcher) end @@ -140,6 +141,7 @@ class Chef # def list(node, key, canonical: nil) return [] unless map.key?(key) + map[key].select do |matcher| node_matches?(node, matcher) && canonical_matches?(canonical, matcher) end.map { |matcher| matcher[:klass] } @@ -155,6 +157,7 @@ class Chef # @return [Hash] deleted entries in the same format as the @map def delete_class(klass) raise "please use a Class type for the klass argument" unless klass.is_a?(Class) + deleted = {} map.each do |key, matchers| deleted_matchers = [] @@ -225,6 +228,7 @@ class Chef # It's super common for the filter to be nil. Catch that so we don't # spend any time here. return true if !filters[attribute] + filter_values = Array(filters[attribute]) value = node[attribute] @@ -242,6 +246,7 @@ class Chef # It's super common for the filter to be nil. Catch that so we don't # spend any time here. return true if !filters[attribute] + filter_values = Array(filters[attribute]) value = node[attribute] @@ -257,6 +262,7 @@ class Chef # def matches_target_mode?(filters) return true unless Chef::Config.target_mode? + !!filters[:target_mode] end @@ -270,16 +276,19 @@ class Chef def block_matches?(node, block) return true if block.nil? + block.call node end def node_matches?(node, matcher) return true if !node + filters_match?(node, matcher) && block_matches?(node, matcher[:block]) end def canonical_matches?(canonical, matcher) return true if canonical.nil? + !!canonical == !!matcher[:canonical] end @@ -289,16 +298,22 @@ class Chef def compare_matchers(key, new_matcher, matcher) cmp = compare_matcher_properties(new_matcher[:block], matcher[:block]) return cmp if cmp != 0 + cmp = compare_matcher_properties(new_matcher[:platform_version], matcher[:platform_version]) return cmp if cmp != 0 + cmp = compare_matcher_properties(new_matcher[:platform], matcher[:platform]) return cmp if cmp != 0 + cmp = compare_matcher_properties(new_matcher[:platform_family], matcher[:platform_family]) return cmp if cmp != 0 + cmp = compare_matcher_properties(new_matcher[:os], matcher[:os]) return cmp if cmp != 0 + cmp = compare_matcher_properties(new_matcher[:override], matcher[:override]) return cmp if cmp != 0 + # If all things are identical, return 0 0 end diff --git a/lib/chef/platform/query_helpers.rb b/lib/chef/platform/query_helpers.rb index 6e56eba120..ffcd7e0bd9 100644 --- a/lib/chef/platform/query_helpers.rb +++ b/lib/chef/platform/query_helpers.rb @@ -26,6 +26,7 @@ class Chef def windows_nano_server? return false unless windows? + require "win32/registry" unless defined?(Win32::Registry) # This method may be called before ohai runs (e.g., it may be used to @@ -48,6 +49,7 @@ class Chef def supports_msi? return false unless windows? + require "win32/registry" unless defined?(Win32::Registry) key = "System\\CurrentControlSet\\Services\\msiserver" @@ -90,6 +92,7 @@ class Chef def supported_powershell_version?(node, version_string) return false unless node[:languages] && node[:languages][:powershell] + require "rubygems" unless defined?(Gem) Gem::Version.new(node[:languages][:powershell][:version]) >= Gem::Version.new(version_string) diff --git a/lib/chef/powershell.rb b/lib/chef/powershell.rb index 3fe58b254b..2de0bfe40b 100644 --- a/lib/chef/powershell.rb +++ b/lib/chef/powershell.rb @@ -35,11 +35,13 @@ class Chef # @return [Object] output def initialize(script) raise "Chef::PowerShell can only be used on the Windows platform." unless RUBY_PLATFORM =~ /mswin|mingw32|windows/ + exec(script) end def error? return true if errors.count > 0 + false end diff --git a/lib/chef/property.rb b/lib/chef/property.rb index c26146a96b..24dbd56f2c 100644 --- a/lib/chef/property.rb +++ b/lib/chef/property.rb @@ -130,6 +130,7 @@ class Chef if options.key?(:name_property) raise ArgumentError, "name_attribute and name_property are functionally identical and both cannot be specified on a property at once. Use just one on property #{self}" end + # replace name_property with name_attribute in place options = Hash[options.map { |k, v| k == :name_attribute ? [ :name_property, v ] : [ k, v ] }] @options = options @@ -230,6 +231,7 @@ class Chef def default return options[:default] if options.key?(:default) return Chef::DelayedEvaluator.new { name } if name_property? + nil end @@ -260,6 +262,7 @@ class Chef # def desired_state? return true if !options.key?(:desired_state) + options[:desired_state] end diff --git a/lib/chef/provider/cookbook_file.rb b/lib/chef/provider/cookbook_file.rb index b8ec86cd92..3d09d291a3 100644 --- a/lib/chef/provider/cookbook_file.rb +++ b/lib/chef/provider/cookbook_file.rb @@ -39,6 +39,7 @@ class Chef def managing_content? return true if new_resource.checksum return true if !new_resource.source.nil? && @action != :create_if_missing + false end diff --git a/lib/chef/provider/cron.rb b/lib/chef/provider/cron.rb index 577876ccf2..7a6f3d666f 100644 --- a/lib/chef/provider/cron.rb +++ b/lib/chef/provider/cron.rb @@ -203,6 +203,7 @@ class Chef def read_crontab so = shell_out!("crontab -l -u #{new_resource.user}", returns: [0, 1]) return nil if so.exitstatus == 1 + so.stdout rescue => e raise Chef::Exceptions::Cron, "Error determining state of #{new_resource.name}, error: #{e}" diff --git a/lib/chef/provider/cron/unix.rb b/lib/chef/provider/cron/unix.rb index c89491cf45..f807ede3bb 100644 --- a/lib/chef/provider/cron/unix.rb +++ b/lib/chef/provider/cron/unix.rb @@ -42,6 +42,7 @@ class Chef raise Chef::Exceptions::Cron, "Error determining state of #{@new_resource.name}, exit: #{status}" end return nil if status > 0 + crontab.stdout.chomp << "\n" end diff --git a/lib/chef/provider/file.rb b/lib/chef/provider/file.rb index bf38a36a6a..ca5f11ba43 100644 --- a/lib/chef/provider/file.rb +++ b/lib/chef/provider/file.rb @@ -190,6 +190,7 @@ class Chef def managing_content? return true if new_resource.checksum return true if !new_resource.content.nil? && @action != :create_if_missing + false end @@ -459,6 +460,7 @@ class Chef # reporting won't work for Windows. return end + acl_scanner = ScanAccessControl.new(new_resource, resource) acl_scanner.set_all! end diff --git a/lib/chef/provider/git.rb b/lib/chef/provider/git.rb index 4d39485a62..3dd574c401 100644 --- a/lib/chef/provider/git.rb +++ b/lib/chef/provider/git.rb @@ -111,6 +111,7 @@ class Chef def git_gem_version return @git_gem_version if defined?(@git_gem_version) + output = git("--version").stdout match = GIT_VERSION_PATTERN.match(output) if match diff --git a/lib/chef/provider/group.rb b/lib/chef/provider/group.rb index ba84ea9468..c0396d9c6a 100644 --- a/lib/chef/provider/group.rb +++ b/lib/chef/provider/group.rb @@ -88,6 +88,7 @@ class Chef missing_members = [] new_resource.members.each do |member| next if has_current_group_member?(member) + validate_member!(member) missing_members << member end @@ -140,6 +141,7 @@ class Chef def action_remove return unless @group_exists + converge_by("remove group #{new_resource.group_name}") do remove_group logger.info("#{new_resource} removed") @@ -148,6 +150,7 @@ class Chef def action_manage return unless @group_exists && compare_group + converge_by(["manage group #{new_resource.group_name}"] + change_desc) do manage_group logger.info("#{new_resource} managed") @@ -156,6 +159,7 @@ class Chef def action_modify return unless compare_group + converge_by(["modify group #{new_resource.group_name}"] + change_desc) do manage_group logger.info("#{new_resource} modified") diff --git a/lib/chef/provider/group/aix.rb b/lib/chef/provider/group/aix.rb index 72bfc76d97..aa4d8ba4c4 100644 --- a/lib/chef/provider/group/aix.rb +++ b/lib/chef/provider/group/aix.rb @@ -54,6 +54,7 @@ class Chef def set_members(members) return if members.empty? + shell_out!("chgrpmem", "-m", "=", members.join(","), new_resource.group_name) end @@ -65,6 +66,7 @@ class Chef opts = [] { gid: "id" }.sort_by { |a| a[0] }.each do |field, option| next unless current_resource.send(field) != new_resource.send(field) + if new_resource.send(field) logger.trace("#{new_resource} setting #{field} to #{new_resource.send(field)}") opts << "#{option}=#{new_resource.send(field)}" diff --git a/lib/chef/provider/group/dscl.rb b/lib/chef/provider/group/dscl.rb index a5c4d27ddb..ce4a6adaf7 100644 --- a/lib/chef/provider/group/dscl.rb +++ b/lib/chef/provider/group/dscl.rb @@ -40,6 +40,7 @@ class Chef return "" if ( args.first =~ /^delete/ ) && ( result[1].exitstatus != 0 ) raise(Chef::Exceptions::Group, "dscl error: #{result.inspect}") unless result[1].exitstatus == 0 raise(Chef::Exceptions::Group, "dscl error: #{result.inspect}") if result[2] =~ /No such key: / + result[2] end @@ -88,6 +89,7 @@ class Chef def gid_used?(gid) return false unless gid + search_gids = safe_dscl("search", "/Groups", "PrimaryGroupID", gid.to_s) # dscl -search should not return anything if the gid doesn't exist, @@ -99,6 +101,7 @@ class Chef def set_gid new_resource.gid(get_free_gid) if [nil, ""].include? new_resource.gid raise(Chef::Exceptions::Group, "gid is already in use") if gid_used?(new_resource.gid) + safe_dscl("create", "/Groups/#{new_resource.group_name}", "PrimaryGroupID", new_resource.gid) end diff --git a/lib/chef/provider/group/groupadd.rb b/lib/chef/provider/group/groupadd.rb index dd99a1c49a..eca104b565 100644 --- a/lib/chef/provider/group/groupadd.rb +++ b/lib/chef/provider/group/groupadd.rb @@ -111,6 +111,7 @@ class Chef { gid: "-g" }.sort_by { |a| a[0] }.each do |field, option| next unless current_resource.send(field) != new_resource.send(field) next unless new_resource.send(field) + opts << option opts << new_resource.send(field) logger.trace("#{new_resource} set #{field} to #{new_resource.send(field)}") diff --git a/lib/chef/provider/group/usermod.rb b/lib/chef/provider/group/usermod.rb index 79a774a4c3..b4e93580ff 100644 --- a/lib/chef/provider/group/usermod.rb +++ b/lib/chef/provider/group/usermod.rb @@ -59,6 +59,7 @@ class Chef unless new_resource.action.include?(:create) raise Chef::Exceptions::UnsupportedAction, "Setting members directly is not supported by #{self}" end + members.each do |member| add_member(member) end diff --git a/lib/chef/provider/ifconfig.rb b/lib/chef/provider/ifconfig.rb index 0ca419da0f..992d2ae144 100644 --- a/lib/chef/provider/ifconfig.rb +++ b/lib/chef/provider/ifconfig.rb @@ -87,6 +87,7 @@ class Chef end next unless @interfaces.key?(new_resource.device) + @interface = @interfaces.fetch(new_resource.device) current_resource.target(new_resource.target) @@ -132,6 +133,7 @@ class Chef end next unless @interfaces.key?(new_resource.device) + @interface = @interfaces.fetch(new_resource.device) current_resource.target(new_resource.target) @@ -144,6 +146,7 @@ class Chef current_resource.metric(@interface["metric"]) end end + current_resource end @@ -177,6 +180,7 @@ class Chef # enables, but does not manage config files return if current_resource.inet_addr return if new_resource.device == loopback_device + command = enable_command converge_by("run #{command.join(' ')} to enable #{new_resource}") do shell_out!(command) @@ -222,6 +226,7 @@ class Chef def generate_config return unless can_generate_config? + b = binding template = ::ERB.new(@config_template) config = resource_for_config(@config_path) @@ -232,6 +237,7 @@ class Chef def delete_config return unless can_generate_config? + config = resource_for_config(@config_path) config.run_action(:delete) new_resource.updated_by_last_action(true) if config.updated? diff --git a/lib/chef/provider/ifconfig/aix.rb b/lib/chef/provider/ifconfig/aix.rb index 1b52060ad2..2f83336f8d 100644 --- a/lib/chef/provider/ifconfig/aix.rb +++ b/lib/chef/provider/ifconfig/aix.rb @@ -66,6 +66,7 @@ class Chef def add_command # ifconfig changes are temporary, chdev persist across reboots. raise Chef::Exceptions::Ifconfig, "interface metric property cannot be set for :add action" if new_resource.metric + command = [ "chdev", "-l", new_resource.device, "-a", "netaddr=#{new_resource.name}" ] command += [ "-a", "netmask=#{new_resource.mask}" ] if new_resource.mask command += [ "-a", "mtu=#{new_resource.mtu}" ] if new_resource.mtu diff --git a/lib/chef/provider/ifconfig/debian.rb b/lib/chef/provider/ifconfig/debian.rb index 614cd7baf9..17d5fdd243 100644 --- a/lib/chef/provider/ifconfig/debian.rb +++ b/lib/chef/provider/ifconfig/debian.rb @@ -65,6 +65,7 @@ iface <%= new_resource.device %> <%= new_resource.family %> static def enforce_interfaces_dot_d_sanity # on ubuntu 18.04 there's no interfaces file and it uses interfaces.d by default return if ::File.directory?(INTERFACES_DOT_D_DIR) && !::File.exist?(INTERFACES_FILE) + # create /etc/network/interfaces.d via dir resource (to get reporting, etc) dir = Chef::Resource::Directory.new(INTERFACES_DOT_D_DIR, run_context) dir.run_action(:create) diff --git a/lib/chef/provider/launchd.rb b/lib/chef/provider/launchd.rb index 880c5d9aa7..838ec22abd 100644 --- a/lib/chef/provider/launchd.rb +++ b/lib/chef/provider/launchd.rb @@ -90,6 +90,7 @@ class Chef def manage_plist(action) return unless manage_agent?(action) + if source res = cookbook_file_resource else @@ -102,6 +103,7 @@ class Chef def manage_service(action) return unless manage_agent?(action) + res = service_resource res.run_action(action) new_resource.updated_by_last_action(true) if res.updated? @@ -179,6 +181,7 @@ class Chef def gen_hash return nil unless new_resource.program || new_resource.program_arguments + { "label" => "Label", "program" => "Program", diff --git a/lib/chef/provider/mount.rb b/lib/chef/provider/mount.rb index e8e2b4dc7b..f7843319f0 100644 --- a/lib/chef/provider/mount.rb +++ b/lib/chef/provider/mount.rb @@ -167,6 +167,7 @@ class Chef if (tries -= 1) < 0 raise Chef::Exceptions::Mount, "Retries exceeded waiting for filesystem to unmount" end + sleep 0.1 end end diff --git a/lib/chef/provider/mount/mount.rb b/lib/chef/provider/mount/mount.rb index 304d922966..fe9a6ffc4f 100644 --- a/lib/chef/provider/mount/mount.rb +++ b/lib/chef/provider/mount/mount.rb @@ -47,6 +47,7 @@ class Chef elsif @new_resource.mount_point != "none" && !::File.exists?(@new_resource.mount_point) raise Chef::Exceptions::Mount, "Mount point #{@new_resource.mount_point} does not exist" end + true end diff --git a/lib/chef/provider/package.rb b/lib/chef/provider/package.rb index 2c984b780e..72ba0ac088 100644 --- a/lib/chef/provider/package.rb +++ b/lib/chef/provider/package.rb @@ -102,6 +102,7 @@ class Chef description = [] target_version_array.each_with_index do |target_version, i| next if target_version.nil? + package_name = package_name_array[i] description << "install version #{target_version} of package #{package_name}" end @@ -130,6 +131,7 @@ class Chef description = [] target_version_array.each_with_index do |target_version, i| next if target_version.nil? + package_name = package_name_array[i] candidate_version = candidate_version_array[i] current_version = current_version_array[i] || "uninstalled" @@ -322,6 +324,7 @@ class Chef # def version_equals?(v1, v2) return false unless v1 && v2 + v1 == v2 end @@ -507,6 +510,7 @@ class Chef missing = [] each_package do |package_name, new_version, current_version, candidate_version| next if new_version.nil? || current_version.nil? + if !version_requirement_satisfied?(current_version, new_version) && candidate_version.nil? missing.push(package_name) end diff --git a/lib/chef/provider/package/apt.rb b/lib/chef/provider/package/apt.rb index cd28746411..b8f2356811 100644 --- a/lib/chef/provider/package/apt.rb +++ b/lib/chef/provider/package/apt.rb @@ -134,6 +134,7 @@ class Chef # @return [Boolean] if apt-get supports --allow-downgrades def supports_allow_downgrade? return @supports_allow_downgrade unless @supports_allow_downgrade.nil? + @supports_allow_downgrade = ( version_compare(apt_version, "1.1.0") >= 0 ) end @@ -194,6 +195,7 @@ class Chef showpkg = run_noninteractive("apt-cache", "showpkg", pkg).stdout partitions = showpkg.rpartition(/Reverse Provides: ?#{$/}/) return nil if partitions[0] == "" && partitions[1] == "" # not found in output + set = partitions[2].lines.each_with_object(Set.new) do |line, acc| # there may be multiple reverse provides for a single package acc.add(line.split[0]) @@ -201,6 +203,7 @@ class Chef if set.size > 1 raise Chef::Exceptions::Package, "#{new_resource.package_name} is a virtual package provided by multiple packages, you must explicitly select one" end + set.to_a.first end diff --git a/lib/chef/provider/package/bff.rb b/lib/chef/provider/package/bff.rb index b0a89454b5..0b358dcb46 100644 --- a/lib/chef/provider/package/bff.rb +++ b/lib/chef/provider/package/bff.rb @@ -84,6 +84,7 @@ class Chef def candidate_version return @candidate_version if @candidate_version + if package_source_found? ret = shell_out("installp", "-L", "-d", new_resource.source) ret.stdout.each_line do |line| diff --git a/lib/chef/provider/package/cab.rb b/lib/chef/provider/package/cab.rb index 9b2aaa048f..c98e135868 100644 --- a/lib/chef/provider/package/cab.rb +++ b/lib/chef/provider/package/cab.rb @@ -78,6 +78,7 @@ class Chef result = shell_out("dism.exe /Online /English #{command} /NoRestart", { timeout: new_resource.timeout }) if result.exitstatus == -2146498530 raise Chef::Exceptions::Package, "The specified package is not applicable to this image." if result.stdout.include?("0x800f081e") + result.error! end result @@ -127,6 +128,7 @@ class Chef text.each_line do |line| key, value = line.split(":") if line.start_with?("Package Identity") next if key.nil? || value.nil? + package = {} package[key.downcase.strip.tr(" ", "_")] = value.strip.chomp packages << package diff --git a/lib/chef/provider/package/chocolatey.rb b/lib/chef/provider/package/chocolatey.rb index a7e6096cd6..98cb57cb79 100644 --- a/lib/chef/provider/package/chocolatey.rb +++ b/lib/chef/provider/package/chocolatey.rb @@ -154,6 +154,7 @@ class Chef # run before choco.exe gets called from #load_current_resource. exe_path = ::File.join(choco_install_path.to_s, "bin", "choco.exe") raise Chef::Exceptions::MissingLibrary, CHOCO_MISSING_MSG unless ::File.exist?(exe_path) + exe_path end end @@ -230,6 +231,7 @@ class Chef # @return [Hash] name-to-version mapping of available packages def available_packages return @available_packages if @available_packages + @available_packages = {} package_name_array.each do |pkg| available_versions = @@ -266,6 +268,7 @@ class Chef hash = {} choco_command(*args).stdout.each_line do |line| next if line.start_with?("Chocolatey v") + name, version = line.split("|") hash[name.downcase] = version&.chomp end diff --git a/lib/chef/provider/package/dnf/python_helper.rb b/lib/chef/provider/package/dnf/python_helper.rb index 881c852392..c5edbfbc3a 100644 --- a/lib/chef/provider/package/dnf/python_helper.rb +++ b/lib/chef/provider/package/dnf/python_helper.rb @@ -161,6 +161,7 @@ class Chef retry else raise e if output.empty? + raise "dnf-helper.py had stderr output:\n\n#{output}" end end diff --git a/lib/chef/provider/package/freebsd/base.rb b/lib/chef/provider/package/freebsd/base.rb index 7c1b244283..bfd828552c 100644 --- a/lib/chef/provider/package/freebsd/base.rb +++ b/lib/chef/provider/package/freebsd/base.rb @@ -51,6 +51,7 @@ class Chef unless path = whereis.stdout[/^#{Regexp.escape(port)}:\s+(.+)$/, 1] raise Chef::Exceptions::Package, "Could not find port with the name #{port}" end + path end end diff --git a/lib/chef/provider/package/macports.rb b/lib/chef/provider/package/macports.rb index 384435778d..1d0bfa9984 100644 --- a/lib/chef/provider/package/macports.rb +++ b/lib/chef/provider/package/macports.rb @@ -93,6 +93,7 @@ class Chef unless status.exitstatus == 0 || status.exitstatus == 1 raise Chef::Exceptions::Package, "#{command} failed - #{status.inspect}!" end + output end end diff --git a/lib/chef/provider/package/msu.rb b/lib/chef/provider/package/msu.rb index 073d3f6454..0f2dca1290 100644 --- a/lib/chef/provider/package/msu.rb +++ b/lib/chef/provider/package/msu.rb @@ -54,6 +54,7 @@ class Chef else current_resource.version(get_current_versions) end + current_resource end @@ -148,6 +149,7 @@ class Chef cab_files end + cab_files end diff --git a/lib/chef/provider/package/paludis.rb b/lib/chef/provider/package/paludis.rb index 27854f31be..3fd526abe4 100644 --- a/lib/chef/provider/package/paludis.rb +++ b/lib/chef/provider/package/paludis.rb @@ -38,6 +38,7 @@ class Chef shell_out!("cave", "-L", "warning", "print-ids", "-M", "none", "-m", new_resource.package_name, "-f", "%c/%p %v %r\n").stdout.each_line do |line| res = re.match(line) next if res.nil? + case res[3] when "accounts", "installed-accounts" next diff --git a/lib/chef/provider/package/powershell.rb b/lib/chef/provider/package/powershell.rb index 7901569532..c10150a32c 100644 --- a/lib/chef/provider/package/powershell.rb +++ b/lib/chef/provider/package/powershell.rb @@ -39,6 +39,7 @@ class Chef if powershell_out("$PSVersionTable.PSVersion.Major").stdout.strip.to_i < 5 raise "Minimum installed PowerShell Version required is 5" end + requirements.assert(:install) do |a| a.assertion { candidates_exist_for_all_uninstalled? } a.failure_message(Chef::Exceptions::Package, "No candidate version available for #{packages_missing_candidates.join(', ')}") diff --git a/lib/chef/provider/package/rpm.rb b/lib/chef/provider/package/rpm.rb index 45dbf91061..75b41a26e4 100644 --- a/lib/chef/provider/package/rpm.rb +++ b/lib/chef/provider/package/rpm.rb @@ -116,6 +116,7 @@ class Chef def uri_scheme?(str) scheme = URI.split(str).first return false unless scheme + %w{http https ftp file}.include?(scheme.downcase) rescue URI::InvalidURIError false diff --git a/lib/chef/provider/package/rubygems.rb b/lib/chef/provider/package/rubygems.rb index 8179deceed..1980629da1 100644 --- a/lib/chef/provider/package/rubygems.rb +++ b/lib/chef/provider/package/rubygems.rb @@ -444,6 +444,7 @@ class Chef def source_is_remote? return true if new_resource.source.nil? return true if new_resource.source.is_a?(Array) + scheme = URI.parse(new_resource.source).scheme # URI.parse gets confused by MS Windows paths with forward slashes. scheme = nil if scheme =~ /^[a-z]$/ @@ -516,6 +517,7 @@ class Chef def version_requirement_satisfied?(current_version, new_version) return false unless current_version && new_version + Gem::Requirement.new(new_version).satisfied_by?(Gem::Version.new(current_version)) end diff --git a/lib/chef/provider/package/smartos.rb b/lib/chef/provider/package/smartos.rb index be1e6f81a3..a44280ec75 100644 --- a/lib/chef/provider/package/smartos.rb +++ b/lib/chef/provider/package/smartos.rb @@ -56,6 +56,7 @@ class Chef def candidate_version return @candidate_version if @candidate_version + name = nil version = nil pkg = shell_out!("/opt/local/bin/pkgin", "se", new_resource.package_name, env: nil, returns: [0, 1]) diff --git a/lib/chef/provider/package/snap.rb b/lib/chef/provider/package/snap.rb index 8096f54659..c9f9e1134f 100644 --- a/lib/chef/provider/package/snap.rb +++ b/lib/chef/provider/package/snap.rb @@ -154,6 +154,7 @@ class Chef if response["type"] == "error" raise "status: #{response["status"]}, kind: #{response["result"]["kind"]}, message: #{response["result"]["message"]}" end + response["change"] end @@ -177,6 +178,7 @@ class Chef end n += 1 raise "Snap operating timed out after #{n} seconds." if n == 300 + sleep(1) end end @@ -319,6 +321,7 @@ class Chef unless [200, 404].include? json["status-code"] raise Chef::Exceptions::Package, json["result"], caller end + json["result"] end @@ -338,6 +341,7 @@ class Chef unless [200, 404].include? json["status-code"] raise Chef::Exceptions::Package, json["result"], caller end + json["result"] end diff --git a/lib/chef/provider/package/solaris.rb b/lib/chef/provider/package/solaris.rb index d30e783a1e..fb0e88ecdb 100644 --- a/lib/chef/provider/package/solaris.rb +++ b/lib/chef/provider/package/solaris.rb @@ -83,6 +83,7 @@ class Chef def candidate_version return @candidate_version if @candidate_version + status = shell_out("pkginfo", "-l", "-d", new_resource.source, new_resource.package_name) status.stdout.each_line do |line| case line @@ -95,6 +96,7 @@ class Chef unless status.exitstatus == 0 raise Chef::Exceptions::Package, "pkginfo -l -d #{new_resource.source} - #{status.inspect}!" end + @candidate_version end diff --git a/lib/chef/provider/package/windows/msi.rb b/lib/chef/provider/package/windows/msi.rb index 870aff6865..c034d9d31b 100644 --- a/lib/chef/provider/package/windows/msi.rb +++ b/lib/chef/provider/package/windows/msi.rb @@ -60,6 +60,7 @@ class Chef def package_version return new_resource.version if new_resource.version + if !new_resource.source.nil? && ::File.exist?(new_resource.source) logger.trace("#{new_resource} getting product version for package at #{new_resource.source}") get_product_property(new_resource.source, "ProductVersion") diff --git a/lib/chef/provider/package/windows/registry_uninstall_entry.rb b/lib/chef/provider/package/windows/registry_uninstall_entry.rb index d57f700799..6f8f359894 100644 --- a/lib/chef/provider/package/windows/registry_uninstall_entry.rb +++ b/lib/chef/provider/package/windows/registry_uninstall_entry.rb @@ -58,6 +58,7 @@ class Chef def self.quiet_uninstall_string_key?(quiet_uninstall_string, hkey, key, entry) return RegistryUninstallEntry.new(hkey, key, entry) if quiet_uninstall_string.nil? + RegistryUninstallEntry.new(hkey, key, entry, "QuietUninstallString") end diff --git a/lib/chef/provider/package/yum.rb b/lib/chef/provider/package/yum.rb index 74343fa10d..08a9c857c9 100644 --- a/lib/chef/provider/package/yum.rb +++ b/lib/chef/provider/package/yum.rb @@ -186,16 +186,19 @@ class Chef def version_gt?(v1, v2) return false if v1.nil? || v2.nil? + python_helper.compare_versions(v1, v2) == 1 end def version_equals?(v1, v2) return false if v1.nil? || v2.nil? + python_helper.compare_versions(v1, v2) == 0 end def version_compare(v1, v2) return false if v1.nil? || v2.nil? + python_helper.compare_versions(v1, v2) end diff --git a/lib/chef/provider/package/yum/python_helper.rb b/lib/chef/provider/package/yum/python_helper.rb index ee7f64d1ea..af0f25bea9 100644 --- a/lib/chef/provider/package/yum/python_helper.rb +++ b/lib/chef/provider/package/yum/python_helper.rb @@ -212,6 +212,7 @@ class Chef retry else raise e if output.empty? + raise "yum-helper.py had stderr/stdout output:\n\n#{output}" end end diff --git a/lib/chef/provider/remote_file.rb b/lib/chef/provider/remote_file.rb index ba384ea3ba..4427680b51 100644 --- a/lib/chef/provider/remote_file.rb +++ b/lib/chef/provider/remote_file.rb @@ -58,6 +58,7 @@ class Chef def managing_content? return true if new_resource.checksum return true if !new_resource.source.nil? && @action != :create_if_missing + false end diff --git a/lib/chef/provider/remote_file/fetcher.rb b/lib/chef/provider/remote_file/fetcher.rb index 3011dd80a0..282309301d 100644 --- a/lib/chef/provider/remote_file/fetcher.rb +++ b/lib/chef/provider/remote_file/fetcher.rb @@ -27,6 +27,7 @@ class Chef if !Chef::Platform.windows? raise Exceptions::UnsupportedPlatform, "Fetching the file on a network share is supported only on the Windows platform. Please change your source: #{uri}" end + Chef::Provider::RemoteFile::NetworkFile.new(uri, new_resource, current_resource) else case uri.scheme diff --git a/lib/chef/provider/route.rb b/lib/chef/provider/route.rb index 1f78db07ad..729ac98386 100644 --- a/lib/chef/provider/route.rb +++ b/lib/chef/provider/route.rb @@ -111,6 +111,7 @@ class Chef # Skip formatting lines (header, etc) next unless destination && gateway && mask + logger.trace("#{new_resource} system has route: dest=#{destination} mask=#{mask} gw=#{gateway}") # check if what were trying to configure is already there @@ -164,6 +165,7 @@ class Chef # walk the collection run_context.resource_collection.each do |resource| next unless resource.is_a? Chef::Resource::Route + # default to eth0 dev = if resource.device resource.device diff --git a/lib/chef/provider/service/arch.rb b/lib/chef/provider/service/arch.rb index fd1b54a302..cbd2340610 100644 --- a/lib/chef/provider/service/arch.rb +++ b/lib/chef/provider/service/arch.rb @@ -34,6 +34,7 @@ class Chef::Provider::Service::Arch < Chef::Provider::Service::Init def load_current_resource raise Chef::Exceptions::Service, "Could not find /etc/rc.conf" unless ::File.exists?("/etc/rc.conf") raise Chef::Exceptions::Service, "No DAEMONS found in /etc/rc.conf" unless ::File.read("/etc/rc.conf") =~ /DAEMONS=\((.*)\)/m + super @current_resource.enabled(daemons.include?(@current_resource.service_name)) diff --git a/lib/chef/provider/service/debian.rb b/lib/chef/provider/service/debian.rb index 059b9777d9..3e1d6e7652 100644 --- a/lib/chef/provider/service/debian.rb +++ b/lib/chef/provider/service/debian.rb @@ -73,6 +73,7 @@ class Chef # returns a list of levels that the service should be stopped or started on def parse_init_file(path) return [] unless ::File.exist?(path) + in_info = false ::File.readlines(path).each_with_object([]) do |line, acc| if line =~ /^### BEGIN INIT INFO/ diff --git a/lib/chef/provider/service/systemd.rb b/lib/chef/provider/service/systemd.rb index 46541bac73..d587b0f589 100644 --- a/lib/chef/provider/service/systemd.rb +++ b/lib/chef/provider/service/systemd.rb @@ -78,6 +78,7 @@ class Chef::Provider::Service::Systemd < Chef::Provider::Service::Simple def get_systemctl_options_args if new_resource.user raise NotImplementedError, "#{new_resource} does not support the user property on a target_mode host (yet)" if Chef::Config.target_mode? + uid = Etc.getpwnam(new_resource.user).uid options = { environment: { diff --git a/lib/chef/provider/service/upstart.rb b/lib/chef/provider/service/upstart.rb index f4ca45f8ea..d88dc4bb6f 100644 --- a/lib/chef/provider/service/upstart.rb +++ b/lib/chef/provider/service/upstart.rb @@ -51,6 +51,7 @@ class Chef def initialize(new_resource, run_context) # TODO: re-evaluate if this is needed after integrating cookbook fix raise ArgumentError, "run_context cannot be nil" unless run_context + super run_context.node diff --git a/lib/chef/provider/service/windows.rb b/lib/chef/provider/service/windows.rb index adb214711a..750da6d1fd 100644 --- a/lib/chef/provider/service/windows.rb +++ b/lib/chef/provider/service/windows.rb @@ -330,6 +330,7 @@ class Chef::Provider::Service::Windows < Chef::Provider::Service loop do break if current_state == desired_state raise Timeout::Error if ( retries += 1 ) > resource_timeout + sleep 1 end end diff --git a/lib/chef/provider/subversion.rb b/lib/chef/provider/subversion.rb index 580c879c97..d28bb3c53a 100644 --- a/lib/chef/provider/subversion.rb +++ b/lib/chef/provider/subversion.rb @@ -137,6 +137,7 @@ class Chef def find_current_revision return nil unless ::File.exist?(::File.join(new_resource.destination, ".svn")) + command = scm(:info) svn_info = shell_out!(command, run_options(cwd: cwd, returns: [0, 1])).stdout @@ -175,6 +176,7 @@ class Chef rev = (repo_attrs["Last Changed Rev"] || repo_attrs["Revision"]) rev.strip! if rev raise "Could not parse `svn info` data: #{svn_info}" if repo_attrs.empty? + logger.trace "#{new_resource} resolved revision #{new_resource.revision} to #{rev}" rev end @@ -185,6 +187,7 @@ class Chef # and will respond appropriately. def authentication return "" unless new_resource.svn_username + result = "--username #{new_resource.svn_username} " result << "--password #{new_resource.svn_password} " result diff --git a/lib/chef/provider/template.rb b/lib/chef/provider/template.rb index 4aab1697f2..f506462268 100644 --- a/lib/chef/provider/template.rb +++ b/lib/chef/provider/template.rb @@ -51,6 +51,7 @@ class Chef def managing_content? return true if new_resource.checksum return true if !new_resource.source.nil? && @action != :create_if_missing + false end diff --git a/lib/chef/provider/user.rb b/lib/chef/provider/user.rb index f4046a8bbf..da739e41ec 100644 --- a/lib/chef/provider/user.rb +++ b/lib/chef/provider/user.rb @@ -132,6 +132,7 @@ class Chef def action_remove return unless @user_exists + converge_by("remove user #{new_resource.username}") do remove_user logger.info("#{new_resource} removed") @@ -140,6 +141,7 @@ class Chef def action_manage return unless @user_exists && compare_user + converge_by("manage user #{new_resource.username}") do manage_user logger.info("#{new_resource} managed") @@ -148,6 +150,7 @@ class Chef def action_modify return unless compare_user + converge_by("modify user #{new_resource.username}") do manage_user logger.info("#{new_resource} modified") @@ -213,6 +216,7 @@ class Chef def updating_home? return false if new_resource.home.nil? return true if current_resource.home.nil? + # Pathname#cleanpath matches more edge conditions than File.expand_path() new_resource.home && Pathname.new(current_resource.home).cleanpath != Pathname.new(new_resource.home).cleanpath end diff --git a/lib/chef/provider/user/aix.rb b/lib/chef/provider/user/aix.rb index 230bc6183e..8a170d276a 100644 --- a/lib/chef/provider/user/aix.rb +++ b/lib/chef/provider/user/aix.rb @@ -32,6 +32,7 @@ class Chef add_password manage_home return if universal_options.empty? && usermod_options.empty? + shell_out!("usermod", universal_options, usermod_options, new_resource.username) end @@ -107,6 +108,7 @@ class Chef def add_password return unless current_resource.password != new_resource.password && new_resource.password + logger.trace("#{new_resource.username} setting password to #{new_resource.password}") command = "echo '#{new_resource.username}:#{new_resource.password}' | chpasswd -e" shell_out!(command) @@ -115,6 +117,7 @@ class Chef # Aix specific handling to update users home directory. def manage_home return unless updating_home? && new_resource.manage_home + # -m option does not work on aix, so move dir. if ::File.directory?(current_resource.home) logger.trace("Changing users home directory from #{current_resource.home} to #{new_resource.home}") diff --git a/lib/chef/provider/user/dscl.rb b/lib/chef/provider/user/dscl.rb index 1ec80af039..147de19a65 100644 --- a/lib/chef/provider/user/dscl.rb +++ b/lib/chef/provider/user/dscl.rb @@ -230,6 +230,7 @@ in 'password', with the associated 'salt' and 'iterations'.") # def uid_used?(uid) return false unless uid + users_uids = run_dscl("list", "/Users", "uid").split("\n") uid_map = users_uids.each_with_object({}) do |tuid, tmap| x = tuid.split @@ -562,6 +563,7 @@ in 'password', with the associated 'salt' and 'iterations'.") # def dscl_set(user_hash, key, value) raise "Unknown dscl key #{key}" unless DSCL_PROPERTY_MAP.keys.include?(key) + user_hash[DSCL_PROPERTY_MAP[key]] = [ value ] user_hash end @@ -571,6 +573,7 @@ in 'password', with the associated 'salt' and 'iterations'.") # def dscl_get(user_hash, key) raise "Unknown dscl key #{key}" unless DSCL_PROPERTY_MAP.keys.include?(key) + # DSCL values are set as arrays value = user_hash[DSCL_PROPERTY_MAP[key]] value.nil? ? value : value.first @@ -585,12 +588,14 @@ in 'password', with the associated 'salt' and 'iterations'.") return "" if ( args.first =~ /^delete/ ) && ( result.exitstatus != 0 ) raise(Chef::Exceptions::DsclCommandFailed, "dscl error: #{result.inspect}") unless result.exitstatus == 0 raise(Chef::Exceptions::DsclCommandFailed, "dscl error: #{result.inspect}") if result.stdout =~ /No such key: / + result.stdout end def run_plutil(*args) result = shell_out("plutil", "-#{args[0]}", args[1..-1]) raise(Chef::Exceptions::PlistUtilCommandFailed, "plutil error: #{result.inspect}") unless result.exitstatus == 0 + if result.stdout.encoding == Encoding::ASCII_8BIT result.stdout.encode("utf-8", "binary", undef: :replace, invalid: :replace, replace: "?") else diff --git a/lib/chef/provider/user/linux.rb b/lib/chef/provider/user/linux.rb index a9a3e23cd9..d27dbcabd4 100644 --- a/lib/chef/provider/user/linux.rb +++ b/lib/chef/provider/user/linux.rb @@ -93,6 +93,7 @@ class Chef # 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/ return false if whyrun_mode? + raise Chef::Exceptions::User, "User #{new_resource.username} does not exist when checking lock status for #{new_resource}" end diff --git a/lib/chef/provider/user/pw.rb b/lib/chef/provider/user/pw.rb index d03b7647ec..bc2991249b 100644 --- a/lib/chef/provider/user/pw.rb +++ b/lib/chef/provider/user/pw.rb @@ -77,6 +77,7 @@ class Chef field_list.sort_by { |a| a[0] }.each do |field, option| field_symbol = field.to_sym next unless current_resource.send(field_symbol) != new_resource.send(field_symbol) + if new_resource.send(field_symbol) logger.trace("#{new_resource} setting #{field} to #{new_resource.send(field_symbol)}") opts << option diff --git a/lib/chef/provider/user/solaris.rb b/lib/chef/provider/user/solaris.rb index 796d3b87cc..57893d23d5 100644 --- a/lib/chef/provider/user/solaris.rb +++ b/lib/chef/provider/user/solaris.rb @@ -37,6 +37,7 @@ class Chef def manage_user manage_password return if universal_options.empty? && usermod_options.empty? + shell_out!("usermod", universal_options, usermod_options, new_resource.username) end @@ -112,6 +113,7 @@ class Chef def manage_password return unless current_resource.password != new_resource.password && new_resource.password + logger.trace("#{new_resource} setting password to #{new_resource.password}") write_shadow_file end diff --git a/lib/chef/provider/user/windows.rb b/lib/chef/provider/user/windows.rb index 8a070f0d47..892759e93f 100644 --- a/lib/chef/provider/user/windows.rb +++ b/lib/chef/provider/user/windows.rb @@ -110,6 +110,7 @@ class Chef field_symbol = field.to_sym next unless current_resource.send(field_symbol) != new_resource.send(field_symbol) next unless new_resource.send(field_symbol) + unless field_symbol == :password logger.trace("#{new_resource} setting #{field} to #{new_resource.send(field_symbol)}") end diff --git a/lib/chef/provider/windows_env.rb b/lib/chef/provider/windows_env.rb index 6b76b23928..3fd4b18cfa 100644 --- a/lib/chef/provider/windows_env.rb +++ b/lib/chef/provider/windows_env.rb @@ -67,6 +67,7 @@ class Chef new_values.inject(0) do |index, val| next_index = current_values.find_index val return true if next_index.nil? || next_index < index + next_index end false @@ -99,6 +100,7 @@ class Chef # after we removed the element. def delete_element return false unless new_resource.delim # no delim: delete the key + needs_delete = new_values.any? { |v| current_values.include?(v) } if !needs_delete logger.trace("#{new_resource} element '#{new_resource.value}' does not exist") @@ -191,6 +193,7 @@ class Chef def env_obj(key_name) return @env_obj if @env_obj + wmi = WmiLite::Wmi.new # Note that by design this query is case insensitive with regard to key_name environment_variables = wmi.query("select * from Win32_Environment where name = '#{key_name}'") diff --git a/lib/chef/provider/windows_task.rb b/lib/chef/provider/windows_task.rb index 49f67d680d..42f662310d 100644 --- a/lib/chef/provider/windows_task.rb +++ b/lib/chef/provider/windows_task.rb @@ -603,6 +603,7 @@ class Chef validate << "Command" if new_resource.command.nil? || new_resource.command.empty? validate << "Task Name" if new_resource.task_name.nil? || new_resource.task_name.empty? return true if validate.empty? + raise Chef::Exceptions::ValidationFailed.new "Value for '#{validate.join(', ')}' option cannot be empty" end diff --git a/lib/chef/recipe.rb b/lib/chef/recipe.rb index 6bfc74d900..838cac4b5a 100644 --- a/lib/chef/recipe.rb +++ b/lib/chef/recipe.rb @@ -47,6 +47,7 @@ class Chef [ $1.to_sym, $2 ] when /^::(.+)/ raise "current_cookbook is nil, cannot resolve #{recipe_name}" if current_cookbook.nil? + [ current_cookbook.to_sym, $1 ] else [ recipe_name.to_sym, "default" ] diff --git a/lib/chef/resource.rb b/lib/chef/resource.rb index 40dcbd1ed2..f1184094f1 100644 --- a/lib/chef/resource.rb +++ b/lib/chef/resource.rb @@ -516,6 +516,7 @@ class Chef result[property.name] = send(property.name) end return result.values.first if identity_properties.size == 1 + result end @@ -581,6 +582,7 @@ class Chef begin return if should_skip?(action) + provider_for_action(action).run_action rescue StandardError => e if ignore_failure @@ -629,6 +631,7 @@ class Chef def to_text return "suppressed sensitive resource output" if sensitive + text = "# Declared in #{@source_line}\n\n" text << "#{resource_name}(\"#{name}\") do\n" @@ -699,6 +702,7 @@ class Chef safe_ivars.each do |iv| key = iv.to_s.sub(/^@/, "").to_sym next if result.key?(key) + result[key] = instance_variable_get(iv) end result @@ -811,6 +815,7 @@ class Chef if result.size > 1 raise Chef::Exceptions::MultipleIdentityError, "identity_property cannot be called on an object with more than one identity property (#{result.map { |r| r.name }.join(", ")})." end + result.first end @@ -831,6 +836,7 @@ class Chef def self.identity_attr(name = nil) property = identity_property(name) return nil if !property + property.name end @@ -1104,6 +1110,7 @@ class Chef if provider.whyrun_mode? && !provider.whyrun_supported? raise "Cannot retrieve #{self.class.current_resource} in why-run mode: #{provider} does not support why-run" end + provider.load_current_resource provider.current_resource end @@ -1376,6 +1383,7 @@ class Chef # the declared key we want to fall back on the old to_s key. def declared_key return to_s if declared_type.nil? + "#{declared_type}[#{@name}]" end @@ -1542,6 +1550,7 @@ class Chef def self.resource_for_node(short_name, node) klass = Chef::ResourceResolver.resolve(short_name, node: node) raise Chef::Exceptions::NoSuchResourceType.new(short_name, node) if klass.nil? + klass end diff --git a/lib/chef/resource/build_essential.rb b/lib/chef/resource/build_essential.rb index e37b929fa5..5a8513389e 100644 --- a/lib/chef/resource/build_essential.rb +++ b/lib/chef/resource/build_essential.rb @@ -134,6 +134,7 @@ class Chef # @return [void] def after_created return unless compile_time + Array(action).each do |action| run_action(action) end diff --git a/lib/chef/resource/chef_handler.rb b/lib/chef/resource/chef_handler.rb index d5f4525744..80ee765ade 100644 --- a/lib/chef/resource/chef_handler.rb +++ b/lib/chef/resource/chef_handler.rb @@ -67,6 +67,7 @@ class Chef new_resource.type.each do |type, enable| next unless enable + register_handler(type, handler) end end diff --git a/lib/chef/resource/cron_d.rb b/lib/chef/resource/cron_d.rb index 6fcca2a231..2c3b0bcb9f 100644 --- a/lib/chef/resource/cron_d.rb +++ b/lib/chef/resource/cron_d.rb @@ -35,9 +35,11 @@ class Chef # @return [Boolean] valid or not? def self.validate_numeric(spec, min, max) return true if spec == "*" + # binding.pry if spec.respond_to? :to_int return false unless spec >= min && spec <= max + return true end @@ -45,6 +47,7 @@ class Chef spec.split(%r{\/|-|,}).each do |x| next if x == "*" return false unless x =~ /^\d+$/ + x = x.to_i return false unless x >= min && x <= max end @@ -56,12 +59,14 @@ class Chef # @return [Boolean] valid or not? def self.validate_month(spec) return true if spec == "*" + if spec.respond_to? :to_int validate_numeric(spec, 1, 12) elsif spec.respond_to? :to_str return true if spec == "*" # Named abbreviations are permitted but not as part of a range or with stepping return true if %w{jan feb mar apr may jun jul aug sep oct nov dec}.include? spec.downcase + # 1-12 are legal for months validate_numeric(spec, 1, 12) else @@ -74,12 +79,14 @@ class Chef # @return [Boolean] valid or not? def self.validate_dow(spec) return true if spec == "*" + if spec.respond_to? :to_int validate_numeric(spec, 0, 7) elsif spec.respond_to? :to_str return true if spec == "*" # Named abbreviations are permitted but not as part of a range or with stepping return true if %w{sun mon tue wed thu fri sat}.include? spec.downcase + # 0-7 are legal for days of week validate_numeric(spec, 0, 7) else diff --git a/lib/chef/resource/dsc_script.rb b/lib/chef/resource/dsc_script.rb index 83f355c9c4..2ebb224b5b 100644 --- a/lib/chef/resource/dsc_script.rb +++ b/lib/chef/resource/dsc_script.rb @@ -45,6 +45,7 @@ class Chef if arg && configuration_name raise ArgumentError, "The 'code' and 'command' properties may not be used together" end + set_or_return( :code, arg, @@ -56,6 +57,7 @@ class Chef if arg && code raise ArgumentError, "Property `configuration_name` may not be set if `code` is set" end + set_or_return( :configuration_name, arg, @@ -67,6 +69,7 @@ class Chef if arg && code raise ArgumentError, "The 'code' and 'command' properties may not be used together" end + set_or_return( :command, arg, @@ -78,6 +81,7 @@ class Chef if arg && configuration_data_script raise ArgumentError, "The 'configuration_data' and 'configuration_data_script' properties may not be used together" end + set_or_return( :configuration_data, arg, @@ -89,6 +93,7 @@ class Chef if arg && configuration_data raise ArgumentError, "The 'configuration_data' and 'configuration_data_script' properties may not be used together" end + set_or_return( :configuration_data_script, arg, diff --git a/lib/chef/resource/file/verification.rb b/lib/chef/resource/file/verification.rb index c0739a6d44..7cd3144509 100644 --- a/lib/chef/resource/file/verification.rb +++ b/lib/chef/resource/file/verification.rb @@ -77,6 +77,7 @@ class Chef if c.nil? raise Chef::Exceptions::VerificationNotFound.new "No file verification for #{name} found." end + c end @@ -113,6 +114,7 @@ class Chef if @command.include?("%{file}") raise ArgumentError, "The %{file} expansion for verify commands has been removed. Please use %{path} instead." end + command = @command % { path: path } interpreter = Chef::GuardInterpreter.for_resource(@parent_resource, command, @command_opts) interpreter.evaluate diff --git a/lib/chef/resource/file/verification/systemd_unit.rb b/lib/chef/resource/file/verification/systemd_unit.rb index 7e4090b5ac..63e8ded89b 100644 --- a/lib/chef/resource/file/verification/systemd_unit.rb +++ b/lib/chef/resource/file/verification/systemd_unit.rb @@ -46,6 +46,7 @@ class Chef def verify(path, opts = {}) return true unless systemd_analyze_path + Dir.mktmpdir("chef-systemd-unit") do |dir| temp = "#{dir}/#{::File.basename(@parent_resource.path)}" ::FileUtils.cp(path, temp) diff --git a/lib/chef/resource/lwrp_base.rb b/lib/chef/resource/lwrp_base.rb index 54936725b1..0e19e59d6f 100644 --- a/lib/chef/resource/lwrp_base.rb +++ b/lib/chef/resource/lwrp_base.rb @@ -115,6 +115,7 @@ class Chef # +default_action+ and other DSL-y methods when extending LWRP::Base. def from_superclass(m, default = nil) return default if superclass == Chef::Resource::LWRPBase + superclass.respond_to?(m) ? superclass.send(m) : default end end diff --git a/lib/chef/resource/macos_userdefaults.rb b/lib/chef/resource/macos_userdefaults.rb index 75704400d5..02d65baee4 100644 --- a/lib/chef/resource/macos_userdefaults.rb +++ b/lib/chef/resource/macos_userdefaults.rb @@ -67,6 +67,7 @@ class Chef def coerce_booleans(val) return 1 if [true, "TRUE", "1", "true", "YES", "yes"].include?(val) return 0 if [false, "FALSE", "0", "false", "NO", "no"].include?(val) + val end diff --git a/lib/chef/resource/ohai_hint.rb b/lib/chef/resource/ohai_hint.rb index c11ef78950..30d7a3bd0c 100644 --- a/lib/chef/resource/ohai_hint.rb +++ b/lib/chef/resource/ohai_hint.rb @@ -79,6 +79,7 @@ class Chef # @return [JSON] json representation of the content of an empty string if content was nil def format_content(content) return "" if content.nil? || content.empty? + JSON.pretty_generate(content) end end @@ -88,6 +89,7 @@ class Chef # @return [void] def after_created return unless compile_time + Array(action).each do |action| run_action(action) end diff --git a/lib/chef/resource/registry_key.rb b/lib/chef/resource/registry_key.rb index 1bf73f1cdb..cd4edda5a9 100644 --- a/lib/chef/resource/registry_key.rb +++ b/lib/chef/resource/registry_key.rb @@ -86,10 +86,12 @@ class Chef @values.each do |v| raise ArgumentError, "Missing name key in RegistryKey values hash" unless v.key?(:name) + v.each_key do |key| raise ArgumentError, "Bad key #{key} in RegistryKey values hash" unless [:name, :type, :data].include?(key) end raise ArgumentError, "Type of name => #{v[:name]} should be string" unless v[:name].is_a?(String) + if v[:type] raise ArgumentError, "Type of type => #{v[:type]} should be symbol" unless v[:type].is_a?(Symbol) end diff --git a/lib/chef/resource/remote_file.rb b/lib/chef/resource/remote_file.rb index fae3e10695..d654829ee7 100644 --- a/lib/chef/resource/remote_file.rb +++ b/lib/chef/resource/remote_file.rb @@ -161,6 +161,7 @@ class Chef def validate_source(source) source = Array(source).flatten raise ArgumentError, "#{resource_name} has an empty source" if source.empty? + source.each do |src| unless absolute_uri?(src) raise Exceptions::InvalidRemoteFileURI, diff --git a/lib/chef/resource/resource_notification.rb b/lib/chef/resource/resource_notification.rb index 1b3e01696a..4bcadca60a 100644 --- a/lib/chef/resource/resource_notification.rb +++ b/lib/chef/resource/resource_notification.rb @@ -131,6 +131,7 @@ class Chef def ==(other) return false unless other.is_a?(self.class) + other.resource == resource && other.action == action && other.notifying_resource == notifying_resource end diff --git a/lib/chef/resource/sudo.rb b/lib/chef/resource/sudo.rb index 7dbae2623c..eb89687411 100644 --- a/lib/chef/resource/sudo.rb +++ b/lib/chef/resource/sudo.rb @@ -222,6 +222,7 @@ class Chef def visudo_present? return true if ::File.exist?(new_resource.visudo_binary) + Chef::Log.warn("The visudo binary cannot be found at '#{new_resource.visudo_binary}'. Skipping sudoer file validation. If visudo is on this system you can specify the path using the 'visudo_binary' property.") end end diff --git a/lib/chef/resource/sysctl.rb b/lib/chef/resource/sysctl.rb index 2986c4e914..d116b5fdc7 100644 --- a/lib/chef/resource/sysctl.rb +++ b/lib/chef/resource/sysctl.rb @@ -133,6 +133,7 @@ class Chef def get_sysctl_value(key) val = shell_out!("sysctl -n -e #{key}").stdout.tr("\t", " ").strip raise unless val == get_sysctld_value(key) + val end @@ -141,9 +142,11 @@ class Chef # or updated def get_sysctld_value(key) raise unless ::File.exist?("/etc/sysctl.d/99-chef-#{key.tr('/', '.')}.conf") + k, v = ::File.read("/etc/sysctl.d/99-chef-#{key.tr('/', '.')}.conf").match(/(.*) = (.*)/).captures raise "Unknown sysctl key!" if k.nil? raise "Unknown sysctl value!" if v.nil? + v end end diff --git a/lib/chef/resource/timezone.rb b/lib/chef/resource/timezone.rb index 0f5cf7cb0c..16a7f1031e 100644 --- a/lib/chef/resource/timezone.rb +++ b/lib/chef/resource/timezone.rb @@ -126,6 +126,7 @@ class Chef def current_windows_tz tz_shellout = shell_out("tzutil /g") raise "There was an error running the tzutil command" if tz_shellout.exitstatus == 1 + tz_shellout.stdout.strip end end diff --git a/lib/chef/resource/windows_ad_join.rb b/lib/chef/resource/windows_ad_join.rb index fd08f9149a..e62b931a75 100644 --- a/lib/chef/resource/windows_ad_join.rb +++ b/lib/chef/resource/windows_ad_join.rb @@ -96,6 +96,7 @@ class Chef def on_domain? node_domain = powershell_out!("(Get-WmiObject Win32_ComputerSystem).Domain") raise "Failed to check if the system is joined to the domain #{new_resource.domain_name}: #{node_domain.stderr}}" if node_domain.error? + node_domain.stdout.downcase.strip == new_resource.domain_name.downcase end diff --git a/lib/chef/resource/windows_dfs_folder.rb b/lib/chef/resource/windows_dfs_folder.rb index 763163eb90..e75e8b86a4 100644 --- a/lib/chef/resource/windows_dfs_folder.rb +++ b/lib/chef/resource/windows_dfs_folder.rb @@ -46,6 +46,7 @@ class Chef raise "target_path is required for install" unless property_is_set?(:target_path) raise "description is required for install" unless property_is_set?(:description) + powershell_script "Create or Update DFS Folder" do code <<-EOH diff --git a/lib/chef/resource/windows_feature_dism.rb b/lib/chef/resource/windows_feature_dism.rb index 4bbfff9823..ab4ac32ca1 100644 --- a/lib/chef/resource/windows_feature_dism.rb +++ b/lib/chef/resource/windows_feature_dism.rb @@ -69,6 +69,7 @@ class Chef shell_out!(install_command, returns: [0, 42, 127, 3010], timeout: new_resource.timeout) rescue Mixlib::ShellOut::ShellCommandFailed => e raise "Error 50 returned by DISM related to parent features, try setting the 'all' property to 'true' on the 'windows_feature_dism' resource." if required_parent_feature?(e.inspect) + raise e.message end diff --git a/lib/chef/resource/windows_feature_powershell.rb b/lib/chef/resource/windows_feature_powershell.rb index 6806c92fb9..908bb96c76 100644 --- a/lib/chef/resource/windows_feature_powershell.rb +++ b/lib/chef/resource/windows_feature_powershell.rb @@ -132,6 +132,7 @@ class Chef def powershell_version cmd = powershell_out("$PSVersionTable.psversion.major") return 1 if cmd.stdout.empty? # PowerShell 1.0 doesn't have a $PSVersionTable + Regexp.last_match(1).to_i if cmd.stdout =~ /^(\d+)/ rescue Errno::ENOENT 0 # zero as in nothing is installed @@ -245,6 +246,7 @@ class Chef # @return [void] def fail_if_removed return if new_resource.source # if someone provides a source then all is well + if node["platform_version"].to_f > 6.2 # 2012R2 or later return if registry_key_exists?('HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\Servicing') && registry_value_exists?('HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\Servicing', name: "LocalSourcePath") # if source is defined in the registry, still fine end diff --git a/lib/chef/resource/windows_pagefile.rb b/lib/chef/resource/windows_pagefile.rb index 8249436144..03a7511f47 100644 --- a/lib/chef/resource/windows_pagefile.rb +++ b/lib/chef/resource/windows_pagefile.rb @@ -87,6 +87,7 @@ class Chef # is set then this validation is not necessary / doesn't make sense at all def validate_name return if /^.:.*.sys/ =~ new_resource.path + raise "#{new_resource.path} does not match the format DRIVE:\\path\\file.sys for pagefiles. Example: C:\\pagefile.sys" end diff --git a/lib/chef/resource/windows_share.rb b/lib/chef/resource/windows_share.rb index 0dcf49e432..9869fc5e14 100644 --- a/lib/chef/resource/windows_share.rb +++ b/lib/chef/resource/windows_share.rb @@ -160,6 +160,7 @@ class Chef json_results.each do |perm| next unless perm["AccessControlType"] == 0 # allow + case perm["AccessRight"] when 0 then f_users << stripped_account(perm["AccountName"]) # 0 full control when 1 then c_users << stripped_account(perm["AccountName"]) # 1 == change @@ -218,6 +219,7 @@ class Chef def different_path? return false if current_resource.nil? # going from nil to something isn't different for our concerns return false if current_resource.path == Chef::Util::PathHelper.cleanpath(new_resource.path) + true end @@ -274,6 +276,7 @@ class Chef # set permissions for a brand new share OR # update permissions if the current state and desired state differ next unless permissions_need_update?(perm_type) + grant_command = "Grant-SmbShareAccess -Name '#{new_resource.share_name}' -AccountName \"#{new_resource.send("#{perm_type}_users").join('","')}\" -Force -AccessRight #{perm_type}" Chef::Log.debug("Running '#{grant_command}' to update the share permissions") diff --git a/lib/chef/resource/windows_task.rb b/lib/chef/resource/windows_task.rb index b985231c8a..db3eb11b96 100644 --- a/lib/chef/resource/windows_task.rb +++ b/lib/chef/resource/windows_task.rb @@ -140,6 +140,7 @@ class Chef if execution_time_limit execution_time_limit(259200) if execution_time_limit == "PT72H" raise ArgumentError, "Invalid value passed for `execution_time_limit`. Please pass seconds as an Integer (e.g. 60) or a String with numeric values only (e.g. '60')." unless numeric_value_in_string?(execution_time_limit) + execution_time_limit(sec_to_min(execution_time_limit)) end @@ -309,6 +310,7 @@ class Chef def validate_create_months(months, frequency) raise ArgumentError, "months property is only valid for tasks that run monthly" if frequency != :monthly + if months.is_a?(String) months = months.split(",") months.map! { |month| month.strip.upcase } diff --git a/lib/chef/resource/windows_workgroup.rb b/lib/chef/resource/windows_workgroup.rb index 3a983b6987..f455c013af 100644 --- a/lib/chef/resource/windows_workgroup.rb +++ b/lib/chef/resource/windows_workgroup.rb @@ -105,6 +105,7 @@ class Chef def workgroup_member? node_workgroup = powershell_out!("(Get-WmiObject -Class Win32_ComputerSystem).Workgroup") raise "Failed to determine if system already a member of workgroup #{new_resource.workgroup_name}" if node_workgroup.error? + node_workgroup.stdout.downcase.strip == new_resource.workgroup_name.downcase end end diff --git a/lib/chef/resource_builder.rb b/lib/chef/resource_builder.rb index d4d20e01ed..7d2184c06a 100644 --- a/lib/chef/resource_builder.rb +++ b/lib/chef/resource_builder.rb @@ -47,6 +47,7 @@ class Chef if resource.resource_name.nil? raise Chef::Exceptions::InvalidResourceSpecification, "#{resource}.resource_name is `nil`! Did you forget to put `provides :blah` or `resource_name :blah` in your resource class?" end + resource.source_line = created_at resource.declared_type = type diff --git a/lib/chef/resource_collection.rb b/lib/chef/resource_collection.rb index 0293f380b0..716f84b92c 100644 --- a/lib/chef/resource_collection.rb +++ b/lib/chef/resource_collection.rb @@ -134,6 +134,7 @@ class Chef rc.resource_collection.resource_set.lookup(key) rescue Chef::Exceptions::ResourceNotFound raise if rc.parent_run_context.nil? + lookup_recursive(rc.parent_run_context, key) end @@ -141,6 +142,7 @@ class Chef rc.resource_collection.resource_set.find(*args) rescue Chef::Exceptions::ResourceNotFound raise if rc.parent_run_context.nil? + find_recursive(rc.parent_run_context, *args) end end diff --git a/lib/chef/resource_collection/resource_collection_serialization.rb b/lib/chef/resource_collection/resource_collection_serialization.rb index 3008625912..d4609500aa 100644 --- a/lib/chef/resource_collection/resource_collection_serialization.rb +++ b/lib/chef/resource_collection/resource_collection_serialization.rb @@ -61,6 +61,7 @@ class Chef unless arg.kind_of?(Chef::Resource) raise ArgumentError, "Cannot insert a #{arg.class} into a resource collection: must be a subclass of Chef::Resource" end + true end end diff --git a/lib/chef/resource_collection/resource_list.rb b/lib/chef/resource_collection/resource_list.rb index 9e2b798e93..8afbd5dd06 100644 --- a/lib/chef/resource_collection/resource_list.rb +++ b/lib/chef/resource_collection/resource_list.rb @@ -69,11 +69,13 @@ class Chef def delete(key) raise ArgumentError, "Must pass a Chef::Resource or String to delete" unless key.is_a?(String) || key.is_a?(Chef::Resource) + key = key.to_s ret = @resources.reject! { |r| r.to_s == key } if ret.nil? raise Chef::Exceptions::ResourceNotFound, "Cannot find a resource matching #{key} (did you define it first?)" end + ret end diff --git a/lib/chef/resource_collection/resource_set.rb b/lib/chef/resource_collection/resource_set.rb index b1c980dbc1..9760cf4598 100644 --- a/lib/chef/resource_collection/resource_set.rb +++ b/lib/chef/resource_collection/resource_set.rb @@ -53,22 +53,26 @@ class Chef def lookup(key) raise ArgumentError, "Must pass a Chef::Resource or String to lookup" unless key.is_a?(String) || key.is_a?(Chef::Resource) + key = key.to_s res = @resources_by_key[key] unless res raise Chef::Exceptions::ResourceNotFound, "Cannot find a resource matching #{key} (did you define it first?)" end + res end def delete(key) raise ArgumentError, "Must pass a Chef::Resource or String to delete" unless key.is_a?(String) || key.is_a?(Chef::Resource) + key = key.to_s res = @resources_by_key.delete(key) if res == @resources_by_key.default raise Chef::Exceptions::ResourceNotFound, "Cannot find a resource matching #{key} (did you define it first?)" end + res end diff --git a/lib/chef/resource_collection/stepable_iterator.rb b/lib/chef/resource_collection/stepable_iterator.rb index 958ffa28cb..d010c29be5 100644 --- a/lib/chef/resource_collection/stepable_iterator.rb +++ b/lib/chef/resource_collection/stepable_iterator.rb @@ -82,6 +82,7 @@ class Chef def step return nil if @position == size + call_iterator_block @position += 1 end diff --git a/lib/chef/resource_definition.rb b/lib/chef/resource_definition.rb index 6c0f76c169..9d91fb4cb3 100644 --- a/lib/chef/resource_definition.rb +++ b/lib/chef/resource_definition.rb @@ -38,11 +38,13 @@ class Chef unless resource_name.kind_of?(Symbol) raise ArgumentError, "You must use a symbol when defining a new resource!" end + @name = resource_name if prototype_params unless prototype_params.kind_of?(Hash) raise ArgumentError, "You must pass a hash as the prototype parameters for a definition." end + @params = prototype_params end if Kernel.block_given? diff --git a/lib/chef/role.rb b/lib/chef/role.rb index d0c1bc4327..a73b9d5183 100644 --- a/lib/chef/role.rb +++ b/lib/chef/role.rb @@ -226,6 +226,7 @@ class Chef chef_server_rest.put("roles/#{@name}", self) rescue Net::HTTPClientException => e raise e unless e.response.code == "404" + chef_server_rest.post("roles", self) end self @@ -253,6 +254,7 @@ class Chef if js_files.count > 1 || rb_files.count > 1 raise Chef::Exceptions::DuplicateRole, "Multiple roles of same type found named #{name}" end + js_path, rb_path = js_files.first, rb_files.first if js_path && File.exists?(js_path) diff --git a/lib/chef/run_context/cookbook_compiler.rb b/lib/chef/run_context/cookbook_compiler.rb index 0ea66dcf52..0af7783eb7 100644 --- a/lib/chef/run_context/cookbook_compiler.rb +++ b/lib/chef/run_context/cookbook_compiler.rb @@ -207,6 +207,7 @@ class Chef list_of_attr_files.each do |filename| next unless File.extname(filename) == ".rb" + load_attribute_file(cookbook_name.to_s, filename) end end @@ -223,6 +224,7 @@ class Chef def load_libraries_from_cookbook(cookbook_name) files_in_cookbook_by_segment(cookbook_name, :libraries).each do |filename| next unless File.extname(filename) == ".rb" + begin logger.trace("Loading cookbook #{cookbook_name}'s library file: #{filename}") Kernel.require(filename) @@ -237,10 +239,12 @@ class Chef def load_lwrps_from_cookbook(cookbook_name) files_in_cookbook_by_segment(cookbook_name, :providers).each do |filename| next unless File.extname(filename) == ".rb" + load_lwrp_provider(cookbook_name, filename) end files_in_cookbook_by_segment(cookbook_name, :resources).each do |filename| next unless File.extname(filename) == ".rb" + load_lwrp_resource(cookbook_name, filename) end end diff --git a/lib/chef/run_list.rb b/lib/chef/run_list.rb index 7ec5419ab7..de9e4ad612 100644 --- a/lib/chef/run_list.rb +++ b/lib/chef/run_list.rb @@ -74,6 +74,7 @@ class Chef other.run_list_items == @run_list_items else return false unless other.respond_to?(:size) && (other.size == @run_list_items.size) + other_run_list_items = other.dup other_run_list_items.map! { |item| coerce_to_run_list_item(item) } diff --git a/lib/chef/run_list/run_list_expansion.rb b/lib/chef/run_list/run_list_expansion.rb index 9ddcdf7373..c60a7e64d3 100644 --- a/lib/chef/run_list/run_list_expansion.rb +++ b/lib/chef/run_list/run_list_expansion.rb @@ -102,6 +102,7 @@ class Chef # nil if the role does not exist def inflate_role(role_name, included_by) return false if applied_role?(role_name) # Prevent infinite loops + applied_role(role_name) fetch_role(role_name, included_by) end diff --git a/lib/chef/shell/model_wrapper.rb b/lib/chef/shell/model_wrapper.rb index c2c5f2cd09..bfeadc8793 100644 --- a/lib/chef/shell/model_wrapper.rb +++ b/lib/chef/shell/model_wrapper.rb @@ -33,6 +33,7 @@ module Shell def search(query) return all if query.to_s == "all" + results = [] Chef::Search::Query.new.search(@model_symbol, format_query(query)) do |obj| if block_given? diff --git a/lib/chef/user_v1.rb b/lib/chef/user_v1.rb index 015beb371b..baf3a67ec5 100644 --- a/lib/chef/user_v1.rb +++ b/lib/chef/user_v1.rb @@ -154,6 +154,7 @@ class Chef payload[:create_key] = @create_key unless @create_key.nil? payload[:middle_name] = @middle_name unless @middle_name.nil? raise Chef::Exceptions::InvalidUserAttribute, "You cannot set both public_key and create_key for create." if !@create_key.nil? && !@public_key.nil? + new_user = chef_root_rest_v1.post("users", payload) # get the private_key out of the chef_key hash if it exists @@ -168,6 +169,7 @@ class Chef # rescue API V0 if 406 and the server supports V0 supported_versions = server_client_api_version_intersection(e, SUPPORTED_API_VERSIONS) raise e unless supported_versions && supported_versions.include?(0) + payload = { username: @username, display_name: @display_name, diff --git a/lib/chef/util/diff.rb b/lib/chef/util/diff.rb index decff35d85..64cf41fab2 100644 --- a/lib/chef/util/diff.rb +++ b/lib/chef/util/diff.rb @@ -58,6 +58,7 @@ class Chef def for_reporting # caller needs to ensure that new files aren't posted to resource reporting return nil if @diff.nil? + @diff.join("\\n") end @@ -111,6 +112,7 @@ class Chef file_length_difference = hunk.file_length_difference next unless old_hunk next if hunk.merge(old_hunk) + diff_str << old_hunk.diff(:unified) << "\n" ensure old_hunk = hunk @@ -170,6 +172,7 @@ class Chef return buff !~ /\A[\s[:print:]]*\z/m rescue ArgumentError => e return true if e.message =~ /invalid byte sequence/ + raise end end diff --git a/lib/chef/util/dsc/configuration_generator.rb b/lib/chef/util/dsc/configuration_generator.rb index d7fe17f979..a00c703c76 100644 --- a/lib/chef/util/dsc/configuration_generator.rb +++ b/lib/chef/util/dsc/configuration_generator.rb @@ -74,6 +74,7 @@ class Chef::Util::DSC if merged_configuration_flags.key?(switch.to_s.downcase.to_sym) raise ArgumentError, "The `flags` attribute for the dsc_script resource contained a command line switch :#{switch} that is disallowed." end + merged_configuration_flags[switch.to_s.downcase.to_sym] = value end end diff --git a/lib/chef/util/file_edit.rb b/lib/chef/util/file_edit.rb index 5ea3c17129..7d6bb88f60 100644 --- a/lib/chef/util/file_edit.rb +++ b/lib/chef/util/file_edit.rb @@ -30,6 +30,7 @@ class Chef def initialize(filepath) raise ArgumentError, "File '#{filepath}' does not exist" unless File.exist?(filepath) + @editor = Editor.new(File.open(filepath, &:readlines)) @original_pathname = filepath @file_edited = false diff --git a/lib/chef/util/windows/net_user.rb b/lib/chef/util/windows/net_user.rb index 615e666b66..78bd1e31a3 100644 --- a/lib/chef/util/windows/net_user.rb +++ b/lib/chef/util/windows/net_user.rb @@ -103,6 +103,7 @@ class Chef::Util::Windows::NetUser < Chef::Util::Windows if e.to_s =~ /System Error Code: 1326/ return false end + # all other exceptions will assume we cannot logon for a different reason Chef::Log.trace("Unable to login with the specified credentials. Assuming the credentials are valid.") true diff --git a/lib/chef/win32/file.rb b/lib/chef/win32/file.rb index 274879a32d..58e28735cb 100644 --- a/lib/chef/win32/file.rb +++ b/lib/chef/win32/file.rb @@ -41,6 +41,7 @@ class Chef # def self.link(old_name, new_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) @@ -104,6 +105,7 @@ class Chef # def self.readlink(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/file/info.rb b/lib/chef/win32/file/info.rb index 9d1b16fbea..234c04cdbb 100644 --- a/lib/chef/win32/file/info.rb +++ b/lib/chef/win32/file/info.rb @@ -34,6 +34,7 @@ class Chef # http://msdn.microsoft.com/en-us/library/windows/desktop/aa363788(v=vs.85).aspx def initialize(file_name) raise Errno::ENOENT, file_name unless ::File.exist?(file_name) + @file_info = retrieve_file_info(file_name) end diff --git a/lib/chef/win32/file/version_info.rb b/lib/chef/win32/file/version_info.rb index 609d72b96a..10337a409b 100644 --- a/lib/chef/win32/file/version_info.rb +++ b/lib/chef/win32/file/version_info.rb @@ -28,6 +28,7 @@ class Chef def initialize(file_name) raise Errno::ENOENT, file_name unless ::File.exist?(file_name) + @file_version_info = retrieve_file_version_info(file_name) end diff --git a/lib/chef/win32/registry.rb b/lib/chef/win32/registry.rb index c0efa68464..94311f7954 100644 --- a/lib/chef/win32/registry.rb +++ b/lib/chef/win32/registry.rb @@ -132,6 +132,7 @@ class Chef if has_subkeys?(key_path) && !recursive raise Chef::Exceptions::Win32RegNoRecursive, "Registry key #{key_path} has subkeys, and recursive not specified" end + hive, key_including_parent = get_hive_and_key(key_path) # key_including_parent: Software\\Root\\Branch\\Fruit # key => Fruit @@ -161,6 +162,7 @@ class Chef unless key_exists?(key_path) raise Chef::Exceptions::Win32RegKeyMissing, "Registry key #{key_path} does not exist" end + true end @@ -226,6 +228,7 @@ class Chef unless value_exists?(key_path, value) raise Chef::Exceptions::Win32RegValueMissing, "Registry key #{key_path} has no value named #{value[:name]}" end + true end @@ -233,6 +236,7 @@ class Chef unless data_exists?(key_path, value) raise Chef::Exceptions::Win32RegDataMissing, "Registry key #{key_path} has no value named #{value[:name]}, containing type #{value[:type]} and data #{value[:data]}" end + true end @@ -279,6 +283,7 @@ class Chef if val.is_a? String return val.downcase end + val end diff --git a/lib/chef/win32/security.rb b/lib/chef/win32/security.rb index 9a97fd77d2..5b78b652eb 100644 --- a/lib/chef/win32/security.rb +++ b/lib/chef/win32/security.rb @@ -200,6 +200,7 @@ class Chef result = LsaEnumerateAccountRights(policy_handle.read_pointer, sid, privilege_pointer, privilege_length) win32_error = LsaNtStatusToWinError(result) return [] if win32_error == 2 # FILE_NOT_FOUND - No rights assigned + test_and_raise_lsa_nt_status(result) privilege_length.read_ulong.times do |i| @@ -327,6 +328,7 @@ class Chef elsif FFI::LastError.error != ERROR_INSUFFICIENT_BUFFER Chef::ReservedNames::Win32::Error.raise! end + owner_result_storage = FFI::MemoryPointer.new owner_result_size.read_ulong unless GetTokenInformation(token.handle.handle, :TokenOwner, owner_result_storage, owner_result_size.read_ulong, owner_result_size) Chef::ReservedNames::Win32::Error.raise! @@ -342,6 +344,7 @@ class Chef elsif FFI::LastError.error != ERROR_INSUFFICIENT_BUFFER Chef::ReservedNames::Win32::Error.raise! end + group_result_storage = FFI::MemoryPointer.new group_result_size.read_ulong unless GetTokenInformation(token.handle.handle, :TokenPrimaryGroup, group_result_storage, group_result_size.read_ulong, group_result_size) Chef::ReservedNames::Win32::Error.raise! @@ -357,6 +360,7 @@ class Chef elsif FFI::LastError.error != ERROR_INSUFFICIENT_BUFFER Chef::ReservedNames::Win32::Error.raise! end + info_ptr = FFI::MemoryPointer.new(:pointer) token_info_pointer = TOKEN_ELEVATION_TYPE.new info_ptr token_info_length = 4 @@ -653,6 +657,7 @@ class Chef process_token = open_current_process_token(TOKEN_READ) rescue Exception => run_error return false if run_error.message =~ /Access is denied/ + Chef::ReservedNames::Win32::Error.raise! end diff --git a/lib/chef/win32/security/acl.rb b/lib/chef/win32/security/acl.rb index a2700b36ac..548194fb7d 100644 --- a/lib/chef/win32/security/acl.rb +++ b/lib/chef/win32/security/acl.rb @@ -45,6 +45,7 @@ class Chef def ==(other) return false if length != other.length + 0.upto(length - 1) do |i| return false if self[i] != other[i] end diff --git a/lib/chef/win32/security/security_descriptor.rb b/lib/chef/win32/security/security_descriptor.rb index 83f5c466aa..722d8faf5d 100644 --- a/lib/chef/win32/security/security_descriptor.rb +++ b/lib/chef/win32/security/security_descriptor.rb @@ -42,6 +42,7 @@ class Chef def dacl raise "DACL not present" if !dacl_present? + present, acl, defaulted = Chef::ReservedNames::Win32::Security.get_security_descriptor_dacl(self) acl end @@ -66,6 +67,7 @@ class Chef def sacl raise "SACL not present" if !sacl_present? + Security.with_privileges("SeSecurityPrivilege") do present, acl, defaulted = Chef::ReservedNames::Win32::Security.get_security_descriptor_sacl(self) acl diff --git a/lib/chef/win32/security/sid.rb b/lib/chef/win32/security/sid.rb index 4d34f8b8a7..0d1a9138ae 100644 --- a/lib/chef/win32/security/sid.rb +++ b/lib/chef/win32/security/sid.rb @@ -338,6 +338,7 @@ class Chef end raise "Can not determine the administrator account name." if admin_account_name.nil? + admin_account_name end end diff --git a/lib/chef/win32/security/token.rb b/lib/chef/win32/security/token.rb index dfd1e31241..5710d896b7 100644 --- a/lib/chef/win32/security/token.rb +++ b/lib/chef/win32/security/token.rb @@ -64,6 +64,7 @@ class Chef unless Chef::ReservedNames::Win32::API::Security.DuplicateToken(handle.handle, security_impersonation_level, duplicate_token_handle) raise Chef::ReservedNames::Win32::Error.raise! end + Token.new(Handle.new(duplicate_token_handle.read_ulong)) end end diff --git a/spec/functional/mixin/user_context_spec.rb b/spec/functional/mixin/user_context_spec.rb index 802b1db9f1..5beed18166 100644 --- a/spec/functional/mixin/user_context_spec.rb +++ b/spec/functional/mixin/user_context_spec.rb @@ -36,12 +36,14 @@ describe Chef::Mixin::UserContext, windows_only: true do if succeeded || last_error != Chef::ReservedNames::Win32::API::Error::ERROR_INSUFFICIENT_BUFFER raise Chef::Exceptions::Win32APIError, "Expected ERROR_INSUFFICIENT_BUFFER from GetUserNameA but it returned the following error: #{last_error}" end + user_name = FFI::MemoryPointer.new :char, (name_size.read_long) succeeded = get_user_name_a.call(user_name, name_size) last_error = FFI::LastError.error if succeeded == 0 || last_error != 0 raise Chef::Exceptions::Win32APIError, "GetUserNameA failed with #{lasterror}" end + user_name.read_string end diff --git a/spec/functional/resource/cron_spec.rb b/spec/functional/resource/cron_spec.rb index f616b84ce9..16b0d2645c 100644 --- a/spec/functional/resource/cron_spec.rb +++ b/spec/functional/resource/cron_spec.rb @@ -118,6 +118,7 @@ describe Chef::Resource::Cron, :requires_root, :unix_only do def cron_attribute_should_exists(cron_name, attribute, value) return if %w{aix solaris}.include?(ohai[:platform]) + # Test if the attribute exists on newly created cron cron_should_exists(cron_name, "") expect(shell_out("crontab -l -u #{new_resource.user} | grep '#{attribute.upcase}=\"#{value}\"'").exitstatus).to eq(0) diff --git a/spec/functional/run_lock_spec.rb b/spec/functional/run_lock_spec.rb index 49972360ef..825f2810d4 100644 --- a/spec/functional/run_lock_spec.rb +++ b/spec/functional/run_lock_spec.rb @@ -334,6 +334,7 @@ describe Chef::RunLock do loop do line = readline_nonblock(read_from_process) break if line.nil? + event, time = line.split("@") example.log_event("#{name}.last_event got #{event}") example.log_event("[#{name}] #{event}", time.strip) diff --git a/spec/support/platform_helpers.rb b/spec/support/platform_helpers.rb index 02f8c28345..509ca6e71e 100644 --- a/spec/support/platform_helpers.rb +++ b/spec/support/platform_helpers.rb @@ -46,6 +46,7 @@ require "wmi-lite/wmi" if windows? def windows_domain_joined? return false unless windows? + wmi = WmiLite::Wmi.new computer_system = wmi.first_of("Win32_ComputerSystem") computer_system["partofdomain"] @@ -53,11 +54,13 @@ end def windows_2012r2? return false unless windows? + (host_version && host_version.start_with?("6.3")) end def windows_gte_10? return false unless windows? + Gem::Requirement.new(">= 10").satisfied_by?(Gem::Version.new(host_version)) end @@ -71,6 +74,7 @@ end def windows_powershell_dsc? return false unless windows? + supports_dsc = false begin wmi = WmiLite::Wmi.new("root/microsoft/windows/desiredstateconfiguration") @@ -88,6 +92,7 @@ end def windows_user_right?(right) return false unless windows? + require "chef/win32/security" Chef::ReservedNames::Win32::Security.get_account_right(ENV["USERNAME"]).include?(right) end @@ -217,6 +222,7 @@ end def root? return false if windows? + Process.euid == 0 end diff --git a/spec/support/shared/integration/integration_helper.rb b/spec/support/shared/integration/integration_helper.rb index 5fc9de4de7..6c0eca98be 100644 --- a/spec/support/shared/integration/integration_helper.rb +++ b/spec/support/shared/integration/integration_helper.rb @@ -111,6 +111,7 @@ module IntegrationSupport RSpec.shared_context "with a chef repo" do before :each do raise "Can only create one directory per test" if @repository_dir + @repository_dir = Dir.mktmpdir("chef_repo") Chef::Config.chef_repo_path = @repository_dir %w{client cookbook data_bag environment node role user}.each do |object_name| diff --git a/spec/support/shared/unit/file_system_support.rb b/spec/support/shared/unit/file_system_support.rb index 32bdb1456e..d27c90a7c3 100644 --- a/spec/support/shared/unit/file_system_support.rb +++ b/spec/support/shared/unit/file_system_support.rb @@ -26,6 +26,7 @@ module FileSystemSupport if !value.is_a?(Hash) raise "memory_fs() must take a Hash" end + dir = Chef::ChefFS::FileSystem::Memory::MemoryRoot.new(pretty_name, cannot_be_in_regex) value.each do |key, child| dir.add_child(memory_fs_value(child, key.to_s, dir)) diff --git a/spec/unit/mixin/which.rb b/spec/unit/mixin/which.rb index 1764b3b89f..c47eaf37ab 100644 --- a/spec/unit/mixin/which.rb +++ b/spec/unit/mixin/which.rb @@ -88,11 +88,13 @@ describe Chef::Mixin::Which do test_which("passes in the filename as the arg", "foo1", finds: "/dir1/foo1") do |f| raise "bad arg to block" unless f == "/dir1/foo1" + true end test_which("arrays with blocks", "foo1", "foo2", finds: "/dir2/foo1", others: [ "/dir1/foo2" ]) do |f| raise "bad arg to block" unless f == "/dir2/foo1" || f == "/dir1/foo2" + true end end diff --git a/spec/unit/property/state_spec.rb b/spec/unit/property/state_spec.rb index 5c54ec71b2..ca2cd99214 100644 --- a/spec/unit/property/state_spec.rb +++ b/spec/unit/property/state_spec.rb @@ -28,6 +28,7 @@ describe "Chef::Resource#identity and #state" do def self.english_join(values) return "<nothing>" if values.size == 0 return values[0].inspect if values.size == 1 + "#{values[0..-2].map { |v| v.inspect }.join(", ")} and #{values[-1].inspect}" end diff --git a/spec/unit/property/validation_spec.rb b/spec/unit/property/validation_spec.rb index b05d8c4e17..412fc72682 100644 --- a/spec/unit/property/validation_spec.rb +++ b/spec/unit/property/validation_spec.rb @@ -55,6 +55,7 @@ describe "Chef::Resource.property validation" do def self.english_join(values) return "<nothing>" if values.size == 0 return values[0].inspect if values.size == 1 + "#{values[0..-2].map { |v| v.inspect }.join(", ")} and #{values[-1].inspect}" end diff --git a/spec/unit/property_spec.rb b/spec/unit/property_spec.rb index 56e44fd1d1..7d04e38068 100644 --- a/spec/unit/property_spec.rb +++ b/spec/unit/property_spec.rb @@ -51,6 +51,7 @@ describe "Chef::Resource.property" do def self.english_join(values) return "<nothing>" if values.size == 0 return values[0].inspect if values.size == 1 + "#{values[0..-2].map { |v| v.inspect }.join(", ")} and #{values[-1].inspect}" end diff --git a/tasks/docs.rb b/tasks/docs.rb index 0adebce0b6..71e0e83bdc 100755 --- a/tasks/docs.rb +++ b/tasks/docs.rb @@ -14,6 +14,7 @@ namespace :docs_site do # @return [String, nil] a pretty defaul value string or nil if we want to skip it def pretty_default(default) return nil if default.nil? || default == "" || default == "lazy default" + if default.is_a?(String) return default.inspect unless default[0] == ":" end @@ -91,11 +92,13 @@ namespace :docs_site do # @return String def bolded_description(name, description) return nil if description.nil? # handle resources missing descriptions + description.gsub( "#{name} ", "**#{name}** ").split("Note: ").first.strip end def note_text(description) return nil if description.nil? + note = description.split("Note: ")[1] if note <<-HEREDOC @@ -316,6 +319,7 @@ namespace :docs_site do resources = Chef::JSONCompat.parse(ResourceInspector.inspect) resources.each do |resource, data| next if ["scm", "whyrun_safe_ruby_block", "l_w_r_p_base", "user_resource_abstract_base_class", "linux_user", "pw_user", "aix_user", "dscl_user", "solaris_user", "windows_user", ""].include?(resource) + puts "Writing out #{resource}." @name = resource @description = data["description"] |