summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/chef.rb7
-rw-r--r--lib/chef/application.rb3
-rw-r--r--lib/chef/application/agent.rb18
-rw-r--r--lib/chef/application/knife.rb3
-rw-r--r--lib/chef/application/solo.rb18
-rw-r--r--lib/chef/application/windows_service.rb1
-rw-r--r--lib/chef/applications.rb1
-rw-r--r--lib/chef/audit/audit_event_proxy.rb2
-rw-r--r--lib/chef/audit/audit_reporter.rb9
-rw-r--r--lib/chef/audit/control_group_data.rb33
-rw-r--r--lib/chef/audit/runner.rb2
-rw-r--r--lib/chef/config.rb5
-rw-r--r--lib/chef/cookbook/metadata.rb6
-rw-r--r--lib/chef/cookbook_site_streaming_uploader.rb1
-rw-r--r--lib/chef/cookbook_version.rb1
-rw-r--r--lib/chef/dsl/audit.rb13
-rw-r--r--lib/chef/dsl/reboot_pending.rb2
-rw-r--r--lib/chef/event_dispatch/base.rb2
-rw-r--r--lib/chef/http.rb1
-rw-r--r--lib/chef/knife.rb16
-rw-r--r--lib/chef/knife/core/bootstrap_context.rb4
-rw-r--r--lib/chef/knife/node_run_list_remove.rb14
-rw-r--r--lib/chef/mixin/command.rb2
-rw-r--r--lib/chef/mixin/deep_merge.rb62
-rw-r--r--lib/chef/mixin/params_validate.rb4
-rw-r--r--lib/chef/monkey_patches/file.rb26
-rw-r--r--lib/chef/monkey_patches/fileutils.rb65
-rw-r--r--lib/chef/monkey_patches/numeric.rb15
-rw-r--r--lib/chef/monkey_patches/object.rb9
-rw-r--r--lib/chef/monkey_patches/pathname.rb32
-rw-r--r--lib/chef/monkey_patches/regexp.rb34
-rw-r--r--lib/chef/monkey_patches/string.rb49
-rw-r--r--lib/chef/monkey_patches/tempfile.rb64
-rw-r--r--lib/chef/monkey_patches/uri.rb70
-rw-r--r--lib/chef/node.rb23
-rw-r--r--lib/chef/node/attribute.rb75
-rw-r--r--lib/chef/node/attribute_collections.rb5
-rw-r--r--lib/chef/node/immutable_collections.rb4
-rw-r--r--lib/chef/provider/deploy.rb3
-rw-r--r--lib/chef/provider/package/rubygems.rb5
-rw-r--r--lib/chef/provider/package/yum-dump.py4
-rw-r--r--lib/chef/provider/remote_directory.rb2
-rw-r--r--lib/chef/provider/service/upstart.rb2
-rw-r--r--lib/chef/provider/user/dscl.rb2
-rw-r--r--lib/chef/provider_resolver.rb4
-rw-r--r--lib/chef/recipe.rb2
-rw-r--r--lib/chef/resource/remote_file.rb1
-rw-r--r--lib/chef/resource_definition.rb2
-rw-r--r--lib/chef/run_list/run_list_expansion.rb4
-rw-r--r--lib/chef/shef/ext.rb19
-rw-r--r--lib/chef/util/file_edit.rb4
-rw-r--r--lib/chef/workstation_config_loader.rb2
52 files changed, 216 insertions, 541 deletions
diff --git a/lib/chef.rb b/lib/chef.rb
index 0d5fb3de2c..7f54b91f14 100644
--- a/lib/chef.rb
+++ b/lib/chef.rb
@@ -32,10 +32,3 @@ require 'chef/run_status'
require 'chef/handler'
require 'chef/handler/json_file'
-require 'chef/monkey_patches/tempfile'
-require 'chef/monkey_patches/string'
-require 'chef/monkey_patches/numeric'
-require 'chef/monkey_patches/object'
-require 'chef/monkey_patches/file'
-require 'chef/monkey_patches/uri'
-
diff --git a/lib/chef/application.rb b/lib/chef/application.rb
index a2718e7556..5a67fc9091 100644
--- a/lib/chef/application.rb
+++ b/lib/chef/application.rb
@@ -17,6 +17,7 @@
# limitations under the License.
require 'pp'
+require 'uri'
require 'socket'
require 'chef/config'
require 'chef/config_fetcher'
@@ -226,7 +227,7 @@ class Chef
private
def can_fork?
# win32-process gem exposes some form of :fork for Process
- # class. So we are seperately ensuring that the platform we're
+ # class. So we are separately ensuring that the platform we're
# running on is not windows before forking.
Chef::Config[:client_fork] && Process.respond_to?(:fork) && !Chef::Platform.windows?
end
diff --git a/lib/chef/application/agent.rb b/lib/chef/application/agent.rb
deleted file mode 100644
index 66b0c25cbf..0000000000
--- a/lib/chef/application/agent.rb
+++ /dev/null
@@ -1,18 +0,0 @@
-#
-# Author:: AJ Christensen (<aj@opscode.comz>)
-# Copyright:: Copyright (c) 2008 Opscode, Inc.
-# License:: Apache License, Version 2.0
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-require 'chef/application'
diff --git a/lib/chef/application/knife.rb b/lib/chef/application/knife.rb
index d3e2f55757..1a19a45598 100644
--- a/lib/chef/application/knife.rb
+++ b/lib/chef/application/knife.rb
@@ -20,7 +20,6 @@ require 'chef/application'
require 'mixlib/log'
require 'ohai/config'
require 'chef/monkey_patches/net_http.rb'
-require 'chef/monkey_patches/uri.rb'
class Chef::Application::Knife < Chef::Application
@@ -64,7 +63,7 @@ class Chef::Application::Knife < Chef::Application
:long => "--disable-editing",
:description => "Do not open EDITOR, just accept the data as is",
:boolean => true,
- :defaut => false
+ :default => false
option :help,
:short => "-h",
diff --git a/lib/chef/application/solo.rb b/lib/chef/application/solo.rb
index 798834304c..c3f5444ef7 100644
--- a/lib/chef/application/solo.rb
+++ b/lib/chef/application/solo.rb
@@ -160,6 +160,11 @@ class Chef::Application::Solo < Chef::Application
:description => 'Enable whyrun mode',
:boolean => true
+ option :ez,
+ :long => '--ez',
+ :description => 'A memorial for Ezra Zygmuntowicz',
+ :boolean => true
+
option :environment,
:short => '-E ENVIRONMENT',
:long => '--environment ENVIRONMENT',
@@ -216,6 +221,7 @@ class Chef::Application::Solo < Chef::Application
end
def run_application
+ for_ezra if Chef::Config[:ez]
if !Chef::Config[:client_fork] || Chef::Config[:once]
# Run immediately without interval sleep or splay
begin
@@ -230,7 +236,19 @@ class Chef::Application::Solo < Chef::Application
end
end
+
private
+
+ def for_ezra
+ puts <<-EOH
+For Ezra Zygmuntowicz:
+ The man who brought you Chef Solo
+ Early contributor to Chef
+ Kind hearted open source advocate
+ Rest in peace, Ezra.
+EOH
+ end
+
def interval_run_chef_client
if Chef::Config[:daemonize]
Chef::Daemon.daemonize("chef-client")
diff --git a/lib/chef/application/windows_service.rb b/lib/chef/application/windows_service.rb
index bea5e9fcdc..ba7c6dab5a 100644
--- a/lib/chef/application/windows_service.rb
+++ b/lib/chef/application/windows_service.rb
@@ -26,6 +26,7 @@ require 'chef/log'
require 'chef/rest'
require 'mixlib/cli'
require 'socket'
+require 'uri'
require 'win32/daemon'
require 'chef/mixin/shell_out'
diff --git a/lib/chef/applications.rb b/lib/chef/applications.rb
index 6160bb96cd..6a1a2e8a92 100644
--- a/lib/chef/applications.rb
+++ b/lib/chef/applications.rb
@@ -1,4 +1,3 @@
-require 'chef/application/agent'
require 'chef/application/client'
require 'chef/application/knife'
require 'chef/application/solo'
diff --git a/lib/chef/audit/audit_event_proxy.rb b/lib/chef/audit/audit_event_proxy.rb
index 6d5591d943..36160db9bb 100644
--- a/lib/chef/audit/audit_event_proxy.rb
+++ b/lib/chef/audit/audit_event_proxy.rb
@@ -43,7 +43,7 @@ class Chef
described_class = example.metadata[:described_class]
if described_class
resource_type = described_class.class.name.split(':')[-1]
- # TODO submit github PR to expose this
+ # TODO https://github.com/serverspec/serverspec/pull/493
resource_name = described_class.instance_variable_get(:@name)
end
diff --git a/lib/chef/audit/audit_reporter.rb b/lib/chef/audit/audit_reporter.rb
index 21ffb62829..d022ac0c47 100644
--- a/lib/chef/audit/audit_reporter.rb
+++ b/lib/chef/audit/audit_reporter.rb
@@ -28,7 +28,7 @@ class Chef
attr_reader :rest_client, :audit_data, :ordered_control_groups, :run_status
private :rest_client, :audit_data, :ordered_control_groups, :run_status
- PROTOCOL_VERSION = '0.1.0'
+ PROTOCOL_VERSION = '0.1.1'
def initialize(rest_client)
@rest_client = rest_client
@@ -36,6 +36,10 @@ class Chef
@ordered_control_groups = Hash.new
end
+ def run_context
+ run_status.run_context
+ end
+
def audit_phase_start(run_status)
Chef::Log.debug("Audit Reporter starting")
@audit_data = AuditData.new(run_status.node.name, run_status.run_id)
@@ -71,7 +75,8 @@ class Chef
if ordered_control_groups.has_key?(name)
raise Chef::Exceptions::AuditControlGroupDuplicate.new(name)
end
- ordered_control_groups.store(name, ControlGroupData.new(name))
+ metadata = run_context.audits[name].metadata
+ ordered_control_groups.store(name, ControlGroupData.new(name, metadata))
end
def control_example_success(control_group_name, example_data)
diff --git a/lib/chef/audit/control_group_data.rb b/lib/chef/audit/control_group_data.rb
index e221ae94cc..42a91ef5a7 100644
--- a/lib/chef/audit/control_group_data.rb
+++ b/lib/chef/audit/control_group_data.rb
@@ -28,19 +28,20 @@ class Chef
end
class ControlGroupData
- attr_reader :name, :status, :number_success, :number_failed, :controls
+ attr_reader :name, :status, :number_succeeded, :number_failed, :controls, :metadata
- def initialize(name)
+ def initialize(name, metadata={})
@status = "success"
@controls = []
- @number_success = 0
+ @number_succeeded = 0
@number_failed = 0
@name = name
+ @metadata = metadata
end
def example_success(control_data)
- @number_success += 1
+ @number_succeeded += 1
control = create_control(control_data)
control.status = "success"
controls << control
@@ -64,24 +65,18 @@ class Chef
h = {
:name => name,
:status => status,
- :number_success => number_success,
+ :number_succeeded => number_succeeded,
:number_failed => number_failed,
:controls => controls.collect { |c| c.to_hash }
}
- add_display_only_data(h)
+ # If there is a duplicate key, metadata will overwrite it
+ add_display_only_data(h).merge(metadata)
end
private
def create_control(control_data)
- name = control_data[:name]
- resource_type = control_data[:resource_type]
- resource_name = control_data[:resource_name]
- context = control_data[:context]
- line_number = control_data[:line_number]
- # TODO make this smarter with splat arguments so if we start passing in more control_data
- # I don't have to modify code in multiple places
- ControlData.new(name, resource_type, resource_name, context, line_number)
+ ControlData.new(control_data)
end
# The id and control sequence number are ephemeral data - they are not needed
@@ -103,12 +98,10 @@ class Chef
attr_reader :name, :resource_type, :resource_name, :context, :line_number
attr_accessor :status, :details
- def initialize(name, resource_type, resource_name, context, line_number)
- @context = context
- @name = name
- @resource_type = resource_type
- @resource_name = resource_name
- @line_number = line_number
+ def initialize(control_data={})
+ control_data.each do |k, v|
+ self.instance_variable_set("@#{k}", v)
+ end
end
def to_hash
diff --git a/lib/chef/audit/runner.rb b/lib/chef/audit/runner.rb
index 306212989a..51c007d1d0 100644
--- a/lib/chef/audit/runner.rb
+++ b/lib/chef/audit/runner.rb
@@ -142,7 +142,7 @@ class Chef
def register_controls
add_example_group_methods
run_context.audits.each do |name, group|
- ctl_grp = RSpec::Core::ExampleGroup.__controls__(*group[:args], &group[:block])
+ ctl_grp = RSpec::Core::ExampleGroup.__controls__(*group.args, &group.block)
RSpec.world.register(ctl_grp)
end
end
diff --git a/lib/chef/config.rb b/lib/chef/config.rb
index 2a9d44a3c5..957db845b0 100644
--- a/lib/chef/config.rb
+++ b/lib/chef/config.rb
@@ -271,7 +271,7 @@ class Chef
# * :fatal
# These work as you'd expect. There is also a special `:auto` setting.
# When set to :auto, Chef will auto adjust the log verbosity based on
- # context. When a tty is available (usually becase the user is running chef
+ # context. When a tty is available (usually because the user is running chef
# in a console), the log level is set to :warn, and output formatters are
# used as the primary mode of output. When a tty is not available, the
# logger is the primary mode of output, and the log level is set to :info
@@ -317,6 +317,7 @@ class Chef
default :why_run, false
default :color, false
default :client_fork, true
+ default :ez, false
default :enable_reporting, true
default :enable_reporting_url_fatals, false
# Possible values for :audit_mode
@@ -635,7 +636,7 @@ class Chef
#
# For example, on CentOS 6 with ENV['LANG'] = "en_US.UTF-8",
# `locale -a`.split fails with ArgumentError invalid UTF-8 encoding.
- locales = shell_out_with_systems_locale("locale -a").stdout.split
+ locales = shell_out_with_systems_locale!("locale -a").stdout.split
case
when locales.include?('C.UTF-8')
'C.UTF-8'
diff --git a/lib/chef/cookbook/metadata.rb b/lib/chef/cookbook/metadata.rb
index 54e930135d..781d3b40b0 100644
--- a/lib/chef/cookbook/metadata.rb
+++ b/lib/chef/cookbook/metadata.rb
@@ -227,11 +227,11 @@ class Chef
)
end
- # Sets the current cookbook version, or returns it. Can be two or three digits, seperated
+ # Sets the current cookbook version, or returns it. Can be two or three digits, separated
# by dots. ie: '2.1', '1.5.4' or '0.9'.
#
# === Parameters
- # version<String>:: The curent version, as a string
+ # version<String>:: The current version, as a string
#
# === Returns
# version<String>:: Returns the current version
@@ -246,7 +246,7 @@ class Chef
# Sets the name of the cookbook, or returns it.
#
# === Parameters
- # name<String>:: The curent cookbook name.
+ # name<String>:: The current cookbook name.
#
# === Returns
# name<String>:: Returns the current cookbook name.
diff --git a/lib/chef/cookbook_site_streaming_uploader.rb b/lib/chef/cookbook_site_streaming_uploader.rb
index c444c8251b..879a578e15 100644
--- a/lib/chef/cookbook_site_streaming_uploader.rb
+++ b/lib/chef/cookbook_site_streaming_uploader.rb
@@ -18,6 +18,7 @@
# limitations under the License.
#
+require 'uri'
require 'net/http'
require 'mixlib/authentication/signedheaderauth'
require 'openssl'
diff --git a/lib/chef/cookbook_version.rb b/lib/chef/cookbook_version.rb
index 505b403e65..3bf19296c9 100644
--- a/lib/chef/cookbook_version.rb
+++ b/lib/chef/cookbook_version.rb
@@ -24,7 +24,6 @@ require 'chef/cookbook/file_vendor'
require 'chef/cookbook/metadata'
require 'chef/version_class'
require 'pathname'
-require 'chef/monkey_patches/pathname'
require 'chef/digester'
class Chef
diff --git a/lib/chef/dsl/audit.rb b/lib/chef/dsl/audit.rb
index a11d9039ef..022bbcce01 100644
--- a/lib/chef/dsl/audit.rb
+++ b/lib/chef/dsl/audit.rb
@@ -30,11 +30,20 @@ class Chef
name = args[0]
if name.nil? || name.empty?
raise Chef::Exceptions::AuditNameMissing
- elsif run_context.controls.has_key?(name)
+ elsif run_context.audits.has_key?(name)
raise Chef::Exceptions::AuditControlGroupDuplicate.new(name)
end
- run_context.audits[name] = { :args => args, :block => block }
+ # This DSL will only work in the Recipe class because that exposes the cookbook_name
+ cookbook_name = self.cookbook_name
+ metadata = {
+ cookbook_name: cookbook_name,
+ cookbook_version: self.run_context.cookbook_collection[cookbook_name].version,
+ recipe_name: self.recipe_name,
+ line_number: block.source_location[1]
+ }
+
+ run_context.audits[name] = Struct.new(:args, :block, :metadata).new(args, block, metadata)
end
end
diff --git a/lib/chef/dsl/reboot_pending.rb b/lib/chef/dsl/reboot_pending.rb
index a81debce99..7af67e94a5 100644
--- a/lib/chef/dsl/reboot_pending.rb
+++ b/lib/chef/dsl/reboot_pending.rb
@@ -47,7 +47,7 @@ class Chef
# Vista + Server 2008 and newer may have reboots pending from CBS
registry_key_exists?('HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Component Based Servicing\RebootRequired') ||
- # The mere existance of the UpdateExeVolatile key should indicate a pending restart for certain updates
+ # The mere existence of the UpdateExeVolatile key should indicate a pending restart for certain updates
# http://support.microsoft.com/kb/832475
(registry_key_exists?('HKLM\SOFTWARE\Microsoft\Updates\UpdateExeVolatile') &&
!registry_get_values('HKLM\SOFTWARE\Microsoft\Updates\UpdateExeVolatile').select { |v| v[:name] == "Flags" }[0].nil? &&
diff --git a/lib/chef/event_dispatch/base.rb b/lib/chef/event_dispatch/base.rb
index a1306364b7..695e31cf2e 100644
--- a/lib/chef/event_dispatch/base.rb
+++ b/lib/chef/event_dispatch/base.rb
@@ -193,7 +193,7 @@ class Chef
def definition_file_load_failed(path, exception)
end
- # Called when resource defintions are done loading
+ # Called when resource definitions are done loading
def definition_load_complete
end
diff --git a/lib/chef/http.rb b/lib/chef/http.rb
index ee951bd675..8d00a38dc1 100644
--- a/lib/chef/http.rb
+++ b/lib/chef/http.rb
@@ -25,7 +25,6 @@ require 'tempfile'
require 'net/https'
require 'uri'
require 'chef/http/basic_client'
-require 'chef/monkey_patches/string'
require 'chef/monkey_patches/net_http'
require 'chef/config'
require 'chef/platform/query_helpers'
diff --git a/lib/chef/knife.rb b/lib/chef/knife.rb
index 0c079792a4..3f234d7ce3 100644
--- a/lib/chef/knife.rb
+++ b/lib/chef/knife.rb
@@ -72,6 +72,11 @@ class Chef
ui.msg(msg)
end
+ def self.reset_config_loader!
+ @@chef_config_dir = nil
+ @config_loader = nil
+ end
+
def self.reset_subcommands!
@@subcommands = {}
@subcommands_by_category = nil
@@ -162,12 +167,15 @@ class Chef
# Shared with subclasses
@@chef_config_dir = nil
+ def self.config_loader
+ @config_loader ||= WorkstationConfigLoader.new(nil, Chef::Log)
+ end
+
def self.load_config(explicit_config_file)
- config_loader = WorkstationConfigLoader.new(explicit_config_file, Chef::Log)
+ config_loader.explicit_config_file = explicit_config_file
config_loader.load
ui.warn("No knife configuration file found") if config_loader.no_config_found?
- @@chef_config_dir = config_loader.chef_config_dir
config_loader
rescue Exceptions::ConfigurationError => e
@@ -176,7 +184,7 @@ class Chef
end
def self.chef_config_dir
- @@chef_config_dir
+ @@chef_config_dir ||= config_loader.chef_config_dir
end
# Run knife for the given +args+ (ARGV), adding +options+ to the list of
@@ -252,7 +260,7 @@ class Chef
OFFICIAL_PLUGINS = %w[ec2 rackspace windows openstack terremark bluebox]
# :nodoc:
- # Error out and print usage. probably becuase the arguments given by the
+ # Error out and print usage. probably because the arguments given by the
# user could not be resolved to a subcommand.
def self.subcommand_not_found!(args)
ui.fatal("Cannot find sub command for: '#{args.join(' ')}'")
diff --git a/lib/chef/knife/core/bootstrap_context.rb b/lib/chef/knife/core/bootstrap_context.rb
index e681d7a49b..ffc36436ec 100644
--- a/lib/chef/knife/core/bootstrap_context.rb
+++ b/lib/chef/knife/core/bootstrap_context.rb
@@ -23,7 +23,7 @@ class Chef
class Knife
module Core
# Instances of BootstrapContext are the context objects (i.e., +self+) for
- # bootstrap templates. For backwards compatability, they +must+ set the
+ # bootstrap templates. For backwards compatibility, they +must+ set the
# following instance variables:
# * @config - a hash of knife's config values
# * @run_list - the run list for the node to boostrap
@@ -135,7 +135,7 @@ CONFIG
def latest_current_chef_version_string
installer_version_string = nil
if @config[:prerelease]
- installer_version_string = "-p"
+ installer_version_string = ["-p"]
else
chef_version_string = if knife_config[:bootstrap_version]
knife_config[:bootstrap_version]
diff --git a/lib/chef/knife/node_run_list_remove.rb b/lib/chef/knife/node_run_list_remove.rb
index 8519fd590a..4b8953a264 100644
--- a/lib/chef/knife/node_run_list_remove.rb
+++ b/lib/chef/knife/node_run_list_remove.rb
@@ -27,11 +27,20 @@ class Chef
require 'chef/json_compat'
end
- banner "knife node run_list remove [NODE] [ENTRIES] (options)"
+ banner "knife node run_list remove [NODE] [ENTRY[,ENTRY]] (options)"
def run
node = Chef::Node.load(@name_args[0])
- entries = @name_args[1].split(',')
+
+ if @name_args.size > 2
+ # Check for nested lists and create a single plain one
+ entries = @name_args[1..-1].map do |entry|
+ entry.split(',').map { |e| e.strip }
+ end.flatten
+ else
+ # Convert to array and remove the extra spaces
+ entries = @name_args[1].split(',').map { |e| e.strip }
+ end
entries.each { |e| node.run_list.remove(e) }
@@ -45,4 +54,3 @@ class Chef
end
end
end
-
diff --git a/lib/chef/mixin/command.rb b/lib/chef/mixin/command.rb
index c92315e718..d9a9c4f006 100644
--- a/lib/chef/mixin/command.rb
+++ b/lib/chef/mixin/command.rb
@@ -82,7 +82,7 @@ class Chef
end
# works same as above, except that it returns stdout and stderr
- # requirement => platforms like solaris 9,10 has wierd issues where
+ # requirement => platforms like solaris 9,10 has weird issues where
# even in command failure the exit code is zero, so we need to lookup stderr.
def run_command_and_return_stdout_stderr(args={})
command_output = ""
diff --git a/lib/chef/mixin/deep_merge.rb b/lib/chef/mixin/deep_merge.rb
index a8a4737758..825406a93e 100644
--- a/lib/chef/mixin/deep_merge.rb
+++ b/lib/chef/mixin/deep_merge.rb
@@ -27,17 +27,6 @@ class Chef
# http://trac.misuse.org/science/wiki/DeepMerge
module DeepMerge
- class InvalidSubtractiveMerge < ArgumentError; end
-
-
- OLD_KNOCKOUT_PREFIX = "!merge:".freeze
-
- # Regex to match the "knockout prefix" that was used to indicate
- # subtractive merging in Chef 10.x and previous. Subtractive merging is
- # removed as of Chef 11, but we detect attempted use of it and raise an
- # error (see: raise_if_knockout_used!)
- OLD_KNOCKOUT_MATCH = %r[!merge].freeze
-
extend self
def merge(first, second)
@@ -47,15 +36,6 @@ class Chef
DeepMerge.deep_merge(second, first)
end
- # Inherited roles use the knockout_prefix array subtraction functionality
- # This is likely to go away in Chef >= 0.11
- def role_merge(first, second)
- first = Mash.new(first) unless first.kind_of?(Mash)
- second = Mash.new(second) unless second.kind_of?(Mash)
-
- DeepMerge.deep_merge(second, first)
- end
-
class InvalidParameter < StandardError; end
# Deep Merge core documentation.
@@ -78,8 +58,6 @@ class Chef
dest = source; return dest
end
- raise_if_knockout_used!(source)
- raise_if_knockout_used!(dest)
case source
when nil
dest
@@ -89,7 +67,6 @@ class Chef
if dest[src_key]
dest[src_key] = deep_merge!(src_value, dest[src_key])
else # dest[src_key] doesn't exist so we take whatever source has
- raise_if_knockout_used!(src_value)
dest[src_key] = src_value
end
end
@@ -128,11 +105,19 @@ class Chef
# If there are two Hashes, recursively merge.
if merge_onto.kind_of?(Hash) && merge_with.kind_of?(Hash)
merge_with.each do |key, merge_with_value|
- merge_onto[key] = if merge_onto.has_key?(key)
- hash_only_merge(merge_onto[key], merge_with_value)
- else
- merge_with_value
- end
+ value =
+ if merge_onto.has_key?(key)
+ hash_only_merge(merge_onto[key], merge_with_value)
+ else
+ merge_with_value
+ end
+
+ if merge_onto.respond_to?(:public_method_that_only_deep_merge_should_use)
+ # we can't call ImmutableMash#[]= because its immutable, but we need to mutate it to build it in-place
+ merge_onto.public_method_that_only_deep_merge_should_use(key, value)
+ else
+ merge_onto[key] = value
+ end
end
merge_onto
@@ -146,27 +131,6 @@ class Chef
end
end
- # Checks for attempted use of subtractive merge, which was removed for
- # Chef 11.0. If subtractive merge use is detected, will raise an
- # InvalidSubtractiveMerge exception.
- def raise_if_knockout_used!(obj)
- if uses_knockout?(obj)
- raise InvalidSubtractiveMerge, "subtractive merge with !merge is no longer supported"
- end
- end
-
- # Checks for attempted use of subtractive merge in +obj+.
- def uses_knockout?(obj)
- case obj
- when String
- obj =~ OLD_KNOCKOUT_MATCH
- when Array
- obj.any? {|element| element.respond_to?(:gsub) && element =~ OLD_KNOCKOUT_MATCH }
- else
- false
- end
- end
-
def deep_merge(source, dest)
deep_merge!(safe_dup(source), safe_dup(dest))
end
diff --git a/lib/chef/mixin/params_validate.rb b/lib/chef/mixin/params_validate.rb
index bedc67f357..78d72dc801 100644
--- a/lib/chef/mixin/params_validate.rb
+++ b/lib/chef/mixin/params_validate.rb
@@ -42,8 +42,8 @@ class Chef
# method names.
# :required:: Raise an exception if this parameter is missing. Valid values are true or false,
# by default, options are not required.
- # :regex:: Match the value of the paramater against a regular expression.
- # :equal_to:: Match the value of the paramater with ==. An array means it can be equal to any
+ # :regex:: Match the value of the parameter against a regular expression.
+ # :equal_to:: Match the value of the parameter with ==. An array means it can be equal to any
# of the values.
def validate(opts, map)
#--
diff --git a/lib/chef/monkey_patches/file.rb b/lib/chef/monkey_patches/file.rb
deleted file mode 100644
index acc0ca73fe..0000000000
--- a/lib/chef/monkey_patches/file.rb
+++ /dev/null
@@ -1,26 +0,0 @@
-#
-# Author:: Daniel DeLeo (<dan@opscode.com>)
-# Copyright:: Copyright (c) 2013 Opscode, Inc.
-# License:: Apache License, Version 2.0
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-if !File.respond_to?(:realpath)
- require 'pathname'
- class File
- def self.realpath(path)
- Pathname.new(path).realpath.to_s
- end
- end
-end
diff --git a/lib/chef/monkey_patches/fileutils.rb b/lib/chef/monkey_patches/fileutils.rb
deleted file mode 100644
index f18bead144..0000000000
--- a/lib/chef/monkey_patches/fileutils.rb
+++ /dev/null
@@ -1,65 +0,0 @@
-#
-# Author:: Stephen Delano (<stephen@opscode.com>)
-# Copyright:: Copyright (c) 2012 Opscode, Inc.
-# License:: Apache License, Version 2.0
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-# == FileUtils::Entry_ (Patch)
-# On Ruby 1.9.3 and earlier, FileUtils.cp_r(foo, bar, :preserve => true) fails
-# when attempting to copy a directory containing symlinks. This has been
-# patched in the trunk of Ruby, and this is a monkey patch of the offending
-# code.
-
-unless RUBY_VERSION =~ /^2/
- require 'fileutils'
-
- class FileUtils::Entry_
- def copy_metadata(path)
- st = lstat()
- if !st.symlink?
- File.utime st.atime, st.mtime, path
- end
- begin
- if st.symlink?
- begin
- File.lchown st.uid, st.gid, path
- rescue NotImplementedError
- end
- else
- File.chown st.uid, st.gid, path
- end
- rescue Errno::EPERM
- # clear setuid/setgid
- if st.symlink?
- begin
- File.lchmod st.mode & 01777, path
- rescue NotImplementedError
- end
- else
- File.chmod st.mode & 01777, path
- end
- else
- if st.symlink?
- begin
- File.lchmod st.mode, path
- rescue NotImplementedError
- end
- else
- File.chmod st.mode, path
- end
- end
- end
- end
-end
diff --git a/lib/chef/monkey_patches/numeric.rb b/lib/chef/monkey_patches/numeric.rb
deleted file mode 100644
index f4612fdbf3..0000000000
--- a/lib/chef/monkey_patches/numeric.rb
+++ /dev/null
@@ -1,15 +0,0 @@
-unless 0.respond_to?(:fdiv)
- class Numeric
- def fdiv(other)
- to_f / other
- end
- end
-end
-
-# String elements referenced with [] <= 1.8.6 return a Fixnum. Cheat to allow
-# for the simpler "test"[2].ord construct
-class Numeric
- def ord
- return self
- end
-end
diff --git a/lib/chef/monkey_patches/object.rb b/lib/chef/monkey_patches/object.rb
deleted file mode 100644
index 017a4b7938..0000000000
--- a/lib/chef/monkey_patches/object.rb
+++ /dev/null
@@ -1,9 +0,0 @@
-class Object
- unless new.respond_to?(:tap)
- def tap
- yield self
- return self
- end
- end
-end
-
diff --git a/lib/chef/monkey_patches/pathname.rb b/lib/chef/monkey_patches/pathname.rb
deleted file mode 100644
index c0255ae7ea..0000000000
--- a/lib/chef/monkey_patches/pathname.rb
+++ /dev/null
@@ -1,32 +0,0 @@
-require 'pathname'
-
-if RUBY_VERSION.to_f < 1.9
- class Pathname
- @@old_each_filename = instance_method(:each_filename)
-
- def each_filename(&block)
- if block_given?
- EachFilenameEnumerable.new(self).each(&block)
- else
- EachFilenameEnumerable.new(self)
- end
- end
-
- def old_each_filename(&block)
- @@old_each_filename.bind(self).call(&block)
- end
-
- class EachFilenameEnumerable
- include Enumerable
- attr_reader :pathname
-
- def initialize(pathname)
- @pathname = pathname
- end
-
- def each(&block)
- @pathname.old_each_filename(&block)
- end
- end
- end
-end
diff --git a/lib/chef/monkey_patches/regexp.rb b/lib/chef/monkey_patches/regexp.rb
deleted file mode 100644
index 8a7ee77cb5..0000000000
--- a/lib/chef/monkey_patches/regexp.rb
+++ /dev/null
@@ -1,34 +0,0 @@
-# Copyright (c) 2009 Marc-Andre Lafortune
-#
-# Permission is hereby granted, free of charge, to any person obtaining
-# a copy of this software and associated documentation files (the
-# "Software"), to deal in the Software without restriction, including
-# without limitation the rights to use, copy, modify, merge, publish,
-# distribute, sublicense, and/or sell copies of the Software, and to
-# permit persons to whom the Software is furnished to do so, subject to
-# the following conditions:
-#
-# The above copyright notice and this permission notice shall be
-# included in all copies or substantial portions of the Software.
-#
-# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
-# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
-# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
-# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-
-class Regexp
- # Standard in Ruby 1.8.7+. See official documentation[http://www.ruby-doc.org/core-1.8.7/classes/Regexp.html]
- class << self
- unless (union(%w(a b)) rescue false)
- alias :union_without_array_argument :union
-
- def union(*arg)
- return union_without_array_argument(*arg) unless arg.size == 1
- union_without_array_argument(*arg.first)
- end
- end
- end
-end
diff --git a/lib/chef/monkey_patches/string.rb b/lib/chef/monkey_patches/string.rb
deleted file mode 100644
index f91e27ddc5..0000000000
--- a/lib/chef/monkey_patches/string.rb
+++ /dev/null
@@ -1,49 +0,0 @@
-#
-# Author:: Adam Jacob (<adam@opscode.com>)
-# Copyright:: Copyright (c) 2008 Opscode, Inc.
-# License:: Apache License, Version 2.0
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-# == String (Patch)
-# On ruby 1.9, Strings are aware of multibyte characters, so +size+ and +length+
-# give the actual number of characters. In Chef::REST, we need the bytesize
-# so we can correctly set the Content-Length headers, but ruby 1.8.6 and lower
-# don't define String#bytesize. Monkey patching time!
-
-begin
- require 'enumerator'
-rescue LoadError
-end
-
-class String
- unless method_defined?(:bytesize)
- alias :bytesize :size
- end
-
- unless method_defined?(:lines)
- def lines
- enum_for(:each)
- end
- end
-end
-
-# <= 1.8.6 needs some ord!
-class String
- unless method_defined?(:ord)
- def ord
- self.unpack('C').first
- end
- end
-end
diff --git a/lib/chef/monkey_patches/tempfile.rb b/lib/chef/monkey_patches/tempfile.rb
deleted file mode 100644
index b9179f182b..0000000000
--- a/lib/chef/monkey_patches/tempfile.rb
+++ /dev/null
@@ -1,64 +0,0 @@
-#
-# Author:: Adam Jacob (<adam@opscode.com>)
-# Copyright:: Copyright (c) 2008 Opscode, Inc.
-# License:: Apache License, Version 2.0
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-# == Tempfile (Patch)
-# Tempfile has a horrible bug where it causes an IOError: closed stream in its
-# finalizer, leading to intermittent application crashes with confusing stack
-# traces. Here we monkey patch the fix into place. You can track the bug on
-# ruby's redmine: http://redmine.ruby-lang.org/issues/show/3119
-#
-# The patch is slightly different for Ruby 1.8 and Ruby 1.9, both patches are
-# included here.
-class Tempfile # :nodoc:
- # Tempfile has changes between 1.8.x and 1.9.x
- # so we monkey patch separately
- if RUBY_VERSION =~ /^1\.8/
- def unlink
- # keep this order for thread safeness
- begin
- File.unlink(@tmpname) if File.exist?(@tmpname)
- @@cleanlist.delete(@tmpname)
- @tmpname = nil
- ObjectSpace.undefine_finalizer(self)
- rescue Errno::EACCES
- # may not be able to unlink on Windows; just ignore
- end
- end
- alias delete unlink
-
-
- # There is a patch for this, to be merged into 1.9 at some point.
- # When that happens, we'll want to also check the RUBY_PATCHLEVEL
- elsif RUBY_VERSION =~ /^1\.9/
- def unlink
- # keep this order for thread safeness
- return unless @tmpname
- begin
- if File.exist?(@tmpname)
- File.unlink(@tmpname)
- end
- # remove tmpname from remover
- @data[0] = @data[2] = nil
- @tmpname = nil
- rescue Errno::EACCES
- # may not be able to unlink on Windows; just ignore
- end
- end
- alias delete unlink
- end
-end
diff --git a/lib/chef/monkey_patches/uri.rb b/lib/chef/monkey_patches/uri.rb
deleted file mode 100644
index 158285e395..0000000000
--- a/lib/chef/monkey_patches/uri.rb
+++ /dev/null
@@ -1,70 +0,0 @@
-# Ruby is copyrighted free software by Yukihiro Matsumoto <matz@netlab.jp>.
-# You can redistribute it and/or modify it under either the terms of the
-# 2-clause BSDL (see the file BSDL), or the conditions below:
-#
-# 1. You may make and give away verbatim copies of the source form of the
-# software without restriction, provided that you duplicate all of the
-# original copyright notices and associated disclaimers.
-#
-# 2. You may modify your copy of the software in any way, provided that
-# you do at least ONE of the following:
-#
-# a) place your modifications in the Public Domain or otherwise
-# make them Freely Available, such as by posting said
-# modifications to Usenet or an equivalent medium, or by allowing
-# the author to include your modifications in the software.
-#
-# b) use the modified software only within your corporation or
-# organization.
-#
-# c) give non-standard binaries non-standard names, with
-# instructions on where to get the original software distribution.
-#
-# d) make other distribution arrangements with the author.
-#
-# 3. You may distribute the software in object code or binary form,
-# provided that you do at least ONE of the following:
-#
-# a) distribute the binaries and library files of the software,
-# together with instructions (in the manual page or equivalent)
-# on where to get the original distribution.
-#
-# b) accompany the distribution with the machine-readable source of
-# the software.
-#
-# c) give non-standard binaries non-standard names, with
-# instructions on where to get the original software distribution.
-#
-# d) make other distribution arrangements with the author.
-#
-# 4. You may modify and include the part of the software into any other
-# software (possibly commercial). But some files in the distribution
-# are not written by the author, so that they are not under these terms.
-#
-# For the list of those files and their copying conditions, see the
-# file LEGAL.
-#
-# 5. The scripts and library files supplied as input to or produced as
-# output from the software do not automatically fall under the
-# copyright of the software, but belong to whomever generated them,
-# and may be sold commercially, and may be aggregated with this
-# software.
-#
-# 6. THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR
-# IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
-# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
-# PURPOSE.
-
-require 'uri'
-
-unless URI::Generic.instance_methods.map {|m| m.to_s}.include?("hostname")
-
- class URI::Generic
- # Copied from the MRI source for Ruby 1.9.3
- # File lib/uri/generic.rb, line 659
- def hostname
- v = self.host
- /\A\[(.*)\]\z/ =~ v ? $1 : v
- end
- end
-end
diff --git a/lib/chef/node.rb b/lib/chef/node.rb
index dbb7852586..6055f0e1e9 100644
--- a/lib/chef/node.rb
+++ b/lib/chef/node.rb
@@ -127,6 +127,7 @@ class Chef
# Set a normal attribute of this node, but auto-vivify any Mashes that
# might be missing
def normal
+ attributes.top_level_breadcrumb = nil
attributes.set_unless_value_present = false
attributes.normal
end
@@ -136,14 +137,17 @@ class Chef
# Set a normal attribute of this node, auto-vivifying any mashes that are
# missing, but if the final value already exists, don't set it
def normal_unless
+ attributes.top_level_breadcrumb = nil
attributes.set_unless_value_present = true
attributes.normal
end
+
alias_method :set_unless, :normal_unless
# Set a default of this node, but auto-vivify any Mashes that might
# be missing
def default
+ attributes.top_level_breadcrumb = nil
attributes.set_unless_value_present = false
attributes.default
end
@@ -151,6 +155,7 @@ class Chef
# Set a default attribute of this node, auto-vivifying any mashes that are
# missing, but if the final value already exists, don't set it
def default_unless
+ attributes.top_level_breadcrumb = nil
attributes.set_unless_value_present = true
attributes.default
end
@@ -158,6 +163,7 @@ class Chef
# Set an override attribute of this node, but auto-vivify any Mashes that
# might be missing
def override
+ attributes.top_level_breadcrumb = nil
attributes.set_unless_value_present = false
attributes.override
end
@@ -165,35 +171,30 @@ class Chef
# Set an override attribute of this node, auto-vivifying any mashes that
# are missing, but if the final value already exists, don't set it
def override_unless
+ attributes.top_level_breadcrumb = nil
attributes.set_unless_value_present = true
attributes.override
end
- def override_attrs
- attributes.override
- end
+ alias :override_attrs :override
+ alias :default_attrs :default
+ alias :normal_attrs :normal
def override_attrs=(new_values)
attributes.override = new_values
end
- def default_attrs
- attributes.default
- end
-
def default_attrs=(new_values)
attributes.default = new_values
end
- def normal_attrs
- attributes.normal
- end
-
def normal_attrs=(new_values)
attributes.normal = new_values
end
def automatic_attrs
+ attributes.top_level_breadcrumb = nil
+ attributes.set_unless_value_present = false
attributes.automatic
end
diff --git a/lib/chef/node/attribute.rb b/lib/chef/node/attribute.rb
index 6130925aea..3c48f653eb 100644
--- a/lib/chef/node/attribute.rb
+++ b/lib/chef/node/attribute.rb
@@ -175,6 +175,19 @@ class Chef
# return the automatic level attribute component
attr_reader :automatic
+ # This is used to track the top level key as we descend through method chaining into
+ # a precedence level (e.g. node.default['foo']['bar']['baz']= results in 'foo' here). We
+ # need this so that when we hit the end of a method chain which results in a mutator method
+ # that we can invalidate the whole top-level deep merge cache for the top-level key. It is
+ # the responsibility of the accessor on the Chef::Node object to reset this to nil, and then
+ # the first VividMash#[] call can ||= and set this to the first key we encounter.
+ attr_accessor :top_level_breadcrumb
+
+ # Cache of deep merged values by top-level key. This is a simple hash which has keys that are the
+ # top-level keys of the node object, and we save the computed deep-merge for that key here. There is
+ # no cache of subtrees.
+ attr_accessor :deep_merge_cache
+
def initialize(normal, default, override, automatic)
@set_unless_present = false
@@ -195,6 +208,8 @@ class Chef
@merged_attributes = nil
@combined_override = nil
@combined_default = nil
+ @top_level_breadcrumb = nil
+ @deep_merge_cache = {}
end
# Debug what's going on with an attribute. +args+ is a path spec to the
@@ -230,51 +245,75 @@ class Chef
@set_unless_present = setting
end
+ # Invalidate a key in the deep_merge_cache. If called with nil, or no arg, this will invalidate
+ # the entire deep_merge cache. In the case of the user doing node.default['foo']['bar']['baz']=
+ # that eventually results in a call to reset_cache('foo') here. A node.default=hash_thing call
+ # must invalidate the entire cache and re-deep-merge the entire node object.
+ def reset_cache(path = nil)
+ if path.nil?
+ @deep_merge_cache = {}
+ else
+ deep_merge_cache.delete(path)
+ end
+ end
+
+ alias :reset :reset_cache
+
# Set the cookbook level default attribute component to +new_data+.
def default=(new_data)
+ reset
@default = VividMash.new(self, new_data)
end
# Set the role level default attribute component to +new_data+
def role_default=(new_data)
+ reset
@role_default = VividMash.new(self, new_data)
end
# Set the environment level default attribute component to +new_data+
def env_default=(new_data)
+ reset
@env_default = VividMash.new(self, new_data)
end
# Set the force_default (+default!+) level attributes to +new_data+
def force_default=(new_data)
+ reset
@force_default = VividMash.new(self, new_data)
end
# Set the normal level attribute component to +new_data+
def normal=(new_data)
+ reset
@normal = VividMash.new(self, new_data)
end
# Set the cookbook level override attribute component to +new_data+
def override=(new_data)
+ reset
@override = VividMash.new(self, new_data)
end
# Set the role level override attribute component to +new_data+
def role_override=(new_data)
+ reset
@role_override = VividMash.new(self, new_data)
end
# Set the environment level override attribute component to +new_data+
def env_override=(new_data)
+ reset
@env_override = VividMash.new(self, new_data)
end
def force_override=(new_data)
+ reset
@force_override = VividMash.new(self, new_data)
end
def automatic=(new_data)
+ reset
@automatic = VividMash.new(self, new_data)
end
@@ -284,6 +323,7 @@ class Chef
# clears attributes from all precedence levels
def rm(*args)
+ reset(args[0])
# just easier to compute our retval, rather than collect+merge sub-retvals
ret = args.inject(merged_attributes) do |attr, arg|
if attr.nil? || !attr.respond_to?(:[])
@@ -314,6 +354,7 @@ class Chef
#
# equivalent to: force_default!['foo']['bar'].delete('baz')
def rm_default(*args)
+ reset(args[0])
remove_from_precedence_level(force_default!(autovivify: false), *args)
end
@@ -321,6 +362,7 @@ class Chef
#
# equivalent to: normal!['foo']['bar'].delete('baz')
def rm_normal(*args)
+ reset(args[0])
remove_from_precedence_level(normal!(autovivify: false), *args)
end
@@ -328,6 +370,7 @@ class Chef
#
# equivalent to: force_override!['foo']['bar'].delete('baz')
def rm_override(*args)
+ reset(args[0])
remove_from_precedence_level(force_override!(autovivify: false), *args)
end
@@ -337,35 +380,51 @@ class Chef
# sets default attributes without merging
def default!(opts={})
+ # FIXME: do not flush whole cache
+ reset
MultiMash.new(self, @default, [], opts)
end
# sets normal attributes without merging
def normal!(opts={})
+ # FIXME: do not flush whole cache
+ reset
MultiMash.new(self, @normal, [], opts)
end
# sets override attributes without merging
def override!(opts={})
+ # FIXME: do not flush whole cache
+ reset
MultiMash.new(self, @override, [], opts)
end
# clears from all default precedence levels and then sets force_default
def force_default!(opts={})
+ # FIXME: do not flush whole cache
+ reset
MultiMash.new(self, @force_default, [@default, @env_default, @role_default], opts)
end
# clears from all override precedence levels and then sets force_override
def force_override!(opts={})
+ # FIXME: do not flush whole cache
+ reset
MultiMash.new(self, @force_override, [@override, @env_override, @role_override], opts)
end
#
- # Accessing merged attributes
+ # Accessing merged attributes.
+ #
+ # Note that merged_attributes('foo', 'bar', 'baz') can be called to compute only the
+ # deep merge of node['foo']['bar']['baz'], but in practice we currently always compute
+ # all of node['foo'] even if the user only requires node['foo']['bar']['baz'].
#
def merged_attributes(*path)
- immutablize(merge_all(path))
+ # immutablize(
+ merge_all(path)
+ # )
end
def combined_override(*path)
@@ -377,7 +436,13 @@ class Chef
end
def [](key)
- merged_attributes(key)
+ if deep_merge_cache.has_key?(key)
+ # return the cache of the deep merged values by top-level key
+ deep_merge_cache[key]
+ else
+ # save all the work of computing node[key]
+ deep_merge_cache[key] = merged_attributes(key)
+ end
end
def []=(key, value)
@@ -480,7 +545,9 @@ class Chef
safe_dup(component)
end
- components.inject(nil) do |merged, component|
+ return nil if components.compact.empty?
+
+ components.inject(ImmutableMash.new({})) do |merged, component|
Chef::Mixin::DeepMerge.hash_only_merge!(merged, component)
end
end
diff --git a/lib/chef/node/attribute_collections.rb b/lib/chef/node/attribute_collections.rb
index 3b19a14d1c..333f4864c6 100644
--- a/lib/chef/node/attribute_collections.rb
+++ b/lib/chef/node/attribute_collections.rb
@@ -63,6 +63,7 @@ class Chef
MUTATOR_METHODS.each do |mutator|
class_eval(<<-METHOD_DEFN, __FILE__, __LINE__)
def #{mutator}(*args, &block)
+ root.reset_cache(root.top_level_breadcrumb)
super
end
METHOD_DEFN
@@ -127,6 +128,7 @@ class Chef
MUTATOR_METHODS.each do |mutator|
class_eval(<<-METHOD_DEFN, __FILE__, __LINE__)
def #{mutator}(*args, &block)
+ root.reset_cache(root.top_level_breadcrumb)
super
end
METHOD_DEFN
@@ -138,6 +140,7 @@ class Chef
end
def [](key)
+ root.top_level_breadcrumb ||= key
value = super
if !key?(key)
value = self.class.new(root)
@@ -148,9 +151,11 @@ class Chef
end
def []=(key, value)
+ root.top_level_breadcrumb ||= key
if set_unless? && key?(key)
self[key]
else
+ root.reset_cache(root.top_level_breadcrumb)
super
end
end
diff --git a/lib/chef/node/immutable_collections.rb b/lib/chef/node/immutable_collections.rb
index af04ef26d4..56b8fed3b7 100644
--- a/lib/chef/node/immutable_collections.rb
+++ b/lib/chef/node/immutable_collections.rb
@@ -155,6 +155,10 @@ class Chef
end
end
+ def public_method_that_only_deep_merge_should_use(key, value)
+ internal_set(key, immutablize(value))
+ end
+
alias :attribute? :has_key?
# Redefine all of the methods that mutate a Hash to raise an error when called.
diff --git a/lib/chef/provider/deploy.rb b/lib/chef/provider/deploy.rb
index b30f7ed17e..19e7c01ab1 100644
--- a/lib/chef/provider/deploy.rb
+++ b/lib/chef/provider/deploy.rb
@@ -18,7 +18,6 @@
require "chef/mixin/command"
require "chef/mixin/from_file"
-require "chef/monkey_patches/fileutils"
require "chef/provider/git"
require "chef/provider/subversion"
require "chef/dsl/recipe"
@@ -126,7 +125,7 @@ class Chef
# * Move release_path directory before deploy and move it back when error occurs
# * Rollback to previous commit
# * Do nothing - because deploy is force, it will be retried in short time
- # Because last is simpliest, keep it
+ # Because last is simplest, keep it
deploy
end
diff --git a/lib/chef/provider/package/rubygems.rb b/lib/chef/provider/package/rubygems.rb
index 6304a7ef63..1f33cc5a9b 100644
--- a/lib/chef/provider/package/rubygems.rb
+++ b/lib/chef/provider/package/rubygems.rb
@@ -17,6 +17,7 @@
# limitations under the License.
#
+require 'uri'
require 'chef/provider/package'
require 'chef/mixin/command'
require 'chef/resource/package'
@@ -130,7 +131,7 @@ class Chef
##
# Determines the candidate version for a gem from a .gem file on disk
- # and checks if it matches the version contraints in +gem_dependency+
+ # and checks if it matches the version constraints in +gem_dependency+
# === Returns
# Gem::Version a singular gem version object is returned if the gem
# is available
@@ -536,7 +537,7 @@ class Chef
else
src = @new_resource.source && " --source=#{@new_resource.source} --source=https://rubygems.org"
end
- if version
+ if !version.nil? && version.length > 0
shell_out!("#{gem_binary_path} install #{name} -q --no-rdoc --no-ri -v \"#{version}\"#{src}#{opts}", :env=>nil)
else
shell_out!("#{gem_binary_path} install \"#{name}\" -q --no-rdoc --no-ri #{src}#{opts}", :env=>nil)
diff --git a/lib/chef/provider/package/yum-dump.py b/lib/chef/provider/package/yum-dump.py
index 8b09dedbf0..c9f6a1fcea 100644
--- a/lib/chef/provider/package/yum-dump.py
+++ b/lib/chef/provider/package/yum-dump.py
@@ -23,7 +23,7 @@
# and dump the results to stdout.
#
# yum-dump invokes yum similarly to the command line interface which makes it
-# subject to most of the configuration paramaters in yum.conf. yum-dump will
+# subject to most of the configuration parameters in yum.conf. yum-dump will
# also load yum plugins in the same manor as yum - these can affect the output.
#
# Can be run as non root, but that won't update the cache.
@@ -70,7 +70,7 @@ def setup(yb, options):
else:
yb.doConfigSetup(errorlevel=0, debuglevel=0)
except yum.Errors.ConfigError, e:
- # supresses an ignored exception at exit
+ # suppresses an ignored exception at exit
yb.preconf = None
print >> sys.stderr, "yum-dump Config Error: %s" % e
return 1
diff --git a/lib/chef/provider/remote_directory.rb b/lib/chef/provider/remote_directory.rb
index 9a7416e318..eaccce46cf 100644
--- a/lib/chef/provider/remote_directory.rb
+++ b/lib/chef/provider/remote_directory.rb
@@ -44,7 +44,7 @@ class Chef
# Transfer files
files_to_transfer.each do |cookbook_file_relative_path|
create_cookbook_file(cookbook_file_relative_path)
- # parent directories and file being transfered are removed from the purge list
+ # parent directories and file being transferred are removed from the purge list
Pathname.new(Chef::Util::PathHelper.cleanpath(::File.join(@new_resource.path, cookbook_file_relative_path))).descend do |d|
files_to_purge.delete(d.to_s)
end
diff --git a/lib/chef/provider/service/upstart.rb b/lib/chef/provider/service/upstart.rb
index 3a3ddb2385..8d4aa41035 100644
--- a/lib/chef/provider/service/upstart.rb
+++ b/lib/chef/provider/service/upstart.rb
@@ -41,7 +41,7 @@ class Chef
# In chef, when we ask a service to start, we expect it to have started before performing the next step
# since we have top down dependencies. Which is to say we may follow witha resource next that requires
# that service to be running. According to [2] we can trust that sending a 'goal' such as start will not
- # return until that 'goal' is reached, or some error has occured.
+ # return until that 'goal' is reached, or some error has occurred.
#
# [1] http://upstart.ubuntu.com/wiki/JobStates
# [2] http://www.netsplit.com/2008/04/27/upstart-05-events/
diff --git a/lib/chef/provider/user/dscl.rb b/lib/chef/provider/user/dscl.rb
index 84f5145c52..39746f0018 100644
--- a/lib/chef/provider/user/dscl.rb
+++ b/lib/chef/provider/user/dscl.rb
@@ -39,7 +39,7 @@ class Chef
# > 10.7 => password shadow calculation format SALTED-SHA512-PBKDF2
# => stored in: /var/db/dslocal/nodes/Default/users/#{name}.plist
# => shadow binary length 128 bytes
- # => Salt / Iterations are stored seperately in the same file
+ # => Salt / Iterations are stored separately in the same file
#
# This provider only supports Mac OSX versions 10.7 and above
class Dscl < Chef::Provider::User
diff --git a/lib/chef/provider_resolver.rb b/lib/chef/provider_resolver.rb
index 247102f191..d83a3e0468 100644
--- a/lib/chef/provider_resolver.rb
+++ b/lib/chef/provider_resolver.rb
@@ -34,7 +34,7 @@ class Chef
# return a deterministically sorted list of Chef::Provider subclasses
def providers
- @providers ||= Chef::Provider.descendants.sort {|a,b| a.to_s <=> b.to_s }
+ @providers ||= Chef::Provider.descendants
end
def resolve
@@ -48,7 +48,7 @@ class Chef
@enabled_handlers ||=
providers.select do |klass|
klass.provides?(node, resource)
- end
+ end.sort {|a,b| a.to_s <=> b.to_s }
end
# this cut looks at if the provider can handle the specific resource and action
diff --git a/lib/chef/recipe.rb b/lib/chef/recipe.rb
index b4046e4f16..621d93099b 100644
--- a/lib/chef/recipe.rb
+++ b/lib/chef/recipe.rb
@@ -84,7 +84,7 @@ class Chef
run_context.resource_collection.find(*args)
end
- # This was moved to Chef::Node#tag, redirecting here for compatability
+ # This was moved to Chef::Node#tag, redirecting here for compatibility
def tag(*tags)
run_context.node.tag(*tags)
end
diff --git a/lib/chef/resource/remote_file.rb b/lib/chef/resource/remote_file.rb
index 46516fd3fb..7ba98b9d3b 100644
--- a/lib/chef/resource/remote_file.rb
+++ b/lib/chef/resource/remote_file.rb
@@ -17,6 +17,7 @@
# limitations under the License.
#
+require 'uri'
require 'chef/resource/file'
require 'chef/provider/remote_file'
require 'chef/mixin/securable'
diff --git a/lib/chef/resource_definition.rb b/lib/chef/resource_definition.rb
index 278114e209..9d6844129c 100644
--- a/lib/chef/resource_definition.rb
+++ b/lib/chef/resource_definition.rb
@@ -54,7 +54,7 @@ class Chef
end
# When we do the resource definition, we're really just setting new values for
- # the paramaters we prototyped at the top. This method missing is as simple as
+ # the parameters we prototyped at the top. This method missing is as simple as
# it gets.
def method_missing(symbol, *args)
@params[symbol] = args.length == 1 ? args[0] : args
diff --git a/lib/chef/run_list/run_list_expansion.rb b/lib/chef/run_list/run_list_expansion.rb
index 73665f39e7..46b45f1d9e 100644
--- a/lib/chef/run_list/run_list_expansion.rb
+++ b/lib/chef/run_list/run_list_expansion.rb
@@ -96,8 +96,8 @@ class Chef
end
def apply_role_attributes(role)
- @default_attrs = Chef::Mixin::DeepMerge.role_merge(@default_attrs, role.default_attributes)
- @override_attrs = Chef::Mixin::DeepMerge.role_merge(@override_attrs, role.override_attributes)
+ @default_attrs = Chef::Mixin::DeepMerge.merge(@default_attrs, role.default_attributes)
+ @override_attrs = Chef::Mixin::DeepMerge.merge(@override_attrs, role.override_attributes)
end
def applied_role?(role_name)
diff --git a/lib/chef/shef/ext.rb b/lib/chef/shef/ext.rb
deleted file mode 100644
index 8f03de2d04..0000000000
--- a/lib/chef/shef/ext.rb
+++ /dev/null
@@ -1,19 +0,0 @@
-#--
-# Author:: Joshua Timberman (<joshua@opscode.com>)
-# Copyright:: Copyright (c) 2012 Opscode, Inc.
-# License:: Apache License, Version 2.0
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-require 'chef/shell/ext'
diff --git a/lib/chef/util/file_edit.rb b/lib/chef/util/file_edit.rb
index 92cefb4bb4..4d2a9c03eb 100644
--- a/lib/chef/util/file_edit.rb
+++ b/lib/chef/util/file_edit.rb
@@ -47,7 +47,7 @@ class Chef
end
#search the file line by line and match each line with the given regex
- #if matched, replace the match (all occurances) with the replace parameter
+ #if matched, replace the match (all occurrences) with the replace parameter
def search_file_replace(regex, replace)
@changes = (editor.replace(regex, replace) > 0) || @changes
end
@@ -59,7 +59,7 @@ class Chef
end
#search the file line by line and match each line with the given regex
- #if matched, delete the match (all occurances) from the line
+ #if matched, delete the match (all occurrences) from the line
def search_file_delete(regex)
search_file_replace(regex, '')
end
diff --git a/lib/chef/workstation_config_loader.rb b/lib/chef/workstation_config_loader.rb
index 6715d4eec2..dd02ad9a66 100644
--- a/lib/chef/workstation_config_loader.rb
+++ b/lib/chef/workstation_config_loader.rb
@@ -25,7 +25,7 @@ class Chef
class WorkstationConfigLoader
# Path to a config file requested by user, (e.g., via command line option). Can be nil
- attr_reader :explicit_config_file
+ attr_accessor :explicit_config_file
# TODO: initialize this with a logger for Chef and Knife
def initialize(explicit_config_file, logger=nil)