chef 12.0.0.rc.0-x86-mingw32 → 12.0.0-x86-mingw32
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/README.md +1 -1
- data/lib/chef/api_client/registration.rb +3 -1
- data/lib/chef/chef_fs/data_handler/group_data_handler.rb +4 -0
- data/lib/chef/config.rb +46 -38
- data/lib/chef/event_loggers/windows_eventlog.rb +5 -6
- data/lib/chef/exceptions.rb +13 -1
- data/lib/chef/file_content_management/tempfile.rb +33 -5
- data/lib/chef/knife.rb +11 -3
- data/lib/chef/knife/bootstrap.rb +8 -7
- data/lib/chef/mixin/deep_merge.rb +15 -54
- data/lib/chef/mixin/which.rb +37 -0
- data/lib/chef/node.rb +14 -25
- data/lib/chef/node/attribute.rb +227 -41
- data/lib/chef/node/attribute_collections.rb +117 -3
- data/lib/chef/node/immutable_collections.rb +6 -6
- data/lib/chef/platform/provider_priority_map.rb +3 -2
- data/lib/chef/platform/service_helpers.rb +37 -8
- data/lib/chef/provider/service/aixinit.rb +1 -1
- data/lib/chef/provider/service/arch.rb +1 -1
- data/lib/chef/provider/service/debian.rb +5 -1
- data/lib/chef/provider/service/init.rb +4 -0
- data/lib/chef/provider/service/insserv.rb +5 -1
- data/lib/chef/provider/service/invokercd.rb +5 -1
- data/lib/chef/provider/service/redhat.rb +5 -1
- data/lib/chef/provider/service/systemd.rb +50 -32
- data/lib/chef/provider/service/upstart.rb +5 -2
- data/lib/chef/provider_resolver.rb +30 -16
- data/lib/chef/resource.rb +2 -1
- data/lib/chef/resources.rb +7 -0
- data/lib/chef/run_context.rb +0 -5
- data/lib/chef/run_list/run_list_expansion.rb +2 -2
- data/lib/chef/shell.rb +2 -2
- data/lib/chef/util/selinux.rb +2 -10
- data/lib/chef/version.rb +1 -1
- data/lib/chef/workstation_config_loader.rb +1 -1
- data/spec/support/shared/unit/resource/static_provider_resolution.rb +1 -6
- data/spec/unit/api_client/registration_spec.rb +22 -0
- data/spec/unit/application/knife_spec.rb +6 -2
- data/spec/unit/chef_fs/data_handler/group_handler_spec.rb +63 -0
- data/spec/unit/config_spec.rb +5 -5
- data/spec/unit/knife/bootstrap_spec.rb +27 -1
- data/spec/unit/knife_spec.rb +5 -0
- data/spec/unit/mixin/deep_merge_spec.rb +0 -40
- data/spec/unit/node/attribute_spec.rb +37 -50
- data/spec/unit/node_spec.rb +321 -13
- data/spec/unit/provider/file/content_spec.rb +23 -2
- data/spec/unit/provider/service/systemd_service_spec.rb +173 -158
- data/spec/unit/provider_resolver_spec.rb +175 -10
- data/spec/unit/resource/timestamped_deploy_spec.rb +8 -29
- data/spec/unit/runner_spec.rb +3 -1
- metadata +147 -221
- data/spec/.DS_Store +0 -0
- data/spec/data/.DS_Store +0 -0
- data/spec/data/lwrp/.DS_Store +0 -0
- data/spec/data/lwrp/providers/.DS_Store +0 -0
- data/spec/data/lwrp/resources/.DS_Store +0 -0
- data/spec/data/lwrp_override/.DS_Store +0 -0
- data/spec/data/lwrp_override/providers/.DS_Store +0 -0
- data/spec/data/lwrp_override/resources/.DS_Store +0 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: a76a266f7ae25ab6678f701843c2812db14e51e4
|
4
|
+
data.tar.gz: 72f478ea0f0cb3af196be6b2ce15206c179b6743
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 8069c9031d37ec51fbf04f13d4b169937ab2a2f3629f5739b10596485aabbac4f9384c18aa002d7abde1df552dea6512ebffe7019daff0328312e42286071ae0
|
7
|
+
data.tar.gz: 9c4f4957858271f4473ebc4fcd64b0abe97bf07a634a77ae83527947199737a05f27291455d42f6ca164c469dc564185f84b0ee5e26c33b68a9e4a611fe4f8d9
|
data/README.md
CHANGED
@@ -153,7 +153,9 @@ class Chef
|
|
153
153
|
def file_flags
|
154
154
|
base_flags = File::CREAT|File::TRUNC|File::RDWR
|
155
155
|
# Windows doesn't have symlinks, so it doesn't have NOFOLLOW
|
156
|
-
|
156
|
+
if defined?(File::NOFOLLOW) && !Chef::Config[:follow_client_key_symlink]
|
157
|
+
base_flags |= File::NOFOLLOW
|
158
|
+
end
|
157
159
|
base_flags
|
158
160
|
end
|
159
161
|
end
|
data/lib/chef/config.rb
CHANGED
@@ -396,6 +396,12 @@ class Chef
|
|
396
396
|
# If chef-zero is enabled, this defaults to nil (no authentication).
|
397
397
|
default(:client_key) { chef_zero.enabled ? nil : platform_specific_path("/etc/chef/client.pem") }
|
398
398
|
|
399
|
+
# When registering the client, should we allow the client key location to
|
400
|
+
# be a symlink? eg: /etc/chef/client.pem -> /etc/chef/prod-client.pem
|
401
|
+
# If the path of the key goes through a directory like /tmp this should
|
402
|
+
# never be set to true or its possibly an easily exploitable security hole.
|
403
|
+
default :follow_client_key_symlink, false
|
404
|
+
|
399
405
|
# This secret is used to decrypt encrypted data bag items.
|
400
406
|
default(:encrypted_data_bag_secret) do
|
401
407
|
if File.exist?(platform_specific_path("/etc/chef/encrypted_data_bag_secret"))
|
@@ -491,7 +497,7 @@ class Chef
|
|
491
497
|
default :ssh_gateway, nil
|
492
498
|
default :bootstrap_version, nil
|
493
499
|
default :bootstrap_proxy, nil
|
494
|
-
default :bootstrap_template,
|
500
|
+
default :bootstrap_template, nil
|
495
501
|
default :secret, nil
|
496
502
|
default :secret_file, nil
|
497
503
|
default :identity_file, nil
|
@@ -554,10 +560,12 @@ class Chef
|
|
554
560
|
# used to update files.
|
555
561
|
default :file_atomic_update, true
|
556
562
|
|
557
|
-
#
|
558
|
-
#
|
559
|
-
#
|
560
|
-
|
563
|
+
# There are 3 possible values for this configuration setting.
|
564
|
+
# true => file staging is done in the destination directory
|
565
|
+
# false => file staging is done via tempfiles under ENV['TMP']
|
566
|
+
# :auto => file staging will try using destination directory if possible and
|
567
|
+
# will fall back to ENV['TMP'] if destination directory is not usable.
|
568
|
+
default :file_staging_uses_destdir, :auto
|
561
569
|
|
562
570
|
# Exit if another run is in progress and the chef-client is unable to
|
563
571
|
# get the lock before time expires. If nil, no timeout is enforced. (Exits
|
@@ -617,44 +625,44 @@ class Chef
|
|
617
625
|
#
|
618
626
|
# If there is no 'locale -a' then we return 'en_US.UTF-8' since that is the most commonly
|
619
627
|
# available English UTF-8 locale. However, all modern POSIXen should support 'locale -a'.
|
620
|
-
|
621
|
-
|
622
|
-
|
623
|
-
|
624
|
-
|
625
|
-
|
626
|
-
|
627
|
-
|
628
|
-
|
629
|
-
|
630
|
-
|
631
|
-
|
632
|
-
|
633
|
-
|
634
|
-
|
635
|
-
|
636
|
-
|
637
|
-
|
638
|
-
|
639
|
-
|
640
|
-
|
641
|
-
|
642
|
-
guessed_locale.gsub(/UTF-?8$/i, "UTF-8")
|
643
|
-
else
|
644
|
-
Chef::Log.warn "Please install an English UTF-8 locale for Chef to use, falling back to C locale and disabling UTF-8 support."
|
645
|
-
'C'
|
646
|
-
end
|
647
|
-
end
|
648
|
-
rescue
|
649
|
-
if Chef::Platform.windows?
|
650
|
-
Chef::Log.debug "Defaulting to locale en_US.UTF-8 on Windows, until it matters that we do something else."
|
628
|
+
def self.guess_internal_locale
|
629
|
+
# https://github.com/opscode/chef/issues/2181
|
630
|
+
# Some systems have the `locale -a` command, but the result has
|
631
|
+
# invalid characters for the default encoding.
|
632
|
+
#
|
633
|
+
# For example, on CentOS 6 with ENV['LANG'] = "en_US.UTF-8",
|
634
|
+
# `locale -a`.split fails with ArgumentError invalid UTF-8 encoding.
|
635
|
+
locales = shell_out_with_systems_locale!("locale -a").stdout.split
|
636
|
+
case
|
637
|
+
when locales.include?('C.UTF-8')
|
638
|
+
'C.UTF-8'
|
639
|
+
when locales.include?('en_US.UTF-8'), locales.include?('en_US.utf8')
|
640
|
+
'en_US.UTF-8'
|
641
|
+
when locales.include?('en.UTF-8')
|
642
|
+
'en.UTF-8'
|
643
|
+
else
|
644
|
+
# Will match en_ZZ.UTF-8, en_ZZ.utf-8, en_ZZ.UTF8, en_ZZ.utf8
|
645
|
+
guesses = locales.select { |l| l =~ /^en_.*UTF-?8$/i }
|
646
|
+
unless guesses.empty?
|
647
|
+
guessed_locale = guesses.first
|
648
|
+
# Transform into the form en_ZZ.UTF-8
|
649
|
+
guessed_locale.gsub(/UTF-?8$/i, "UTF-8")
|
651
650
|
else
|
652
|
-
Chef::Log.
|
651
|
+
Chef::Log.warn "Please install an English UTF-8 locale for Chef to use, falling back to C locale and disabling UTF-8 support."
|
652
|
+
'C'
|
653
653
|
end
|
654
|
-
'en_US.UTF-8'
|
655
654
|
end
|
655
|
+
rescue
|
656
|
+
if Chef::Platform.windows?
|
657
|
+
Chef::Log.debug "Defaulting to locale en_US.UTF-8 on Windows, until it matters that we do something else."
|
658
|
+
else
|
659
|
+
Chef::Log.debug "No usable locale -a command found, assuming you have en_US.UTF-8 installed."
|
660
|
+
end
|
661
|
+
'en_US.UTF-8'
|
656
662
|
end
|
657
663
|
|
664
|
+
default :internal_locale, guess_internal_locale
|
665
|
+
|
658
666
|
# Force UTF-8 Encoding, for when we fire up in the 'C' locale or other strange locales (e.g.
|
659
667
|
# japanese windows encodings). If we do not do this, then knife upload will fail when a cookbook's
|
660
668
|
# README.md has UTF-8 characters that do not encode in whatever surrounding encoding we have been
|
@@ -26,7 +26,6 @@ if Chef::Platform::windows? and not Chef::Platform::windows_server_2003?
|
|
26
26
|
end
|
27
27
|
|
28
28
|
require 'win32/eventlog'
|
29
|
-
include Win32
|
30
29
|
end
|
31
30
|
|
32
31
|
class Chef
|
@@ -51,12 +50,12 @@ class Chef
|
|
51
50
|
end
|
52
51
|
|
53
52
|
def initialize
|
54
|
-
@eventlog = EventLog::open('Application')
|
53
|
+
@eventlog = ::Win32::EventLog::open('Application')
|
55
54
|
end
|
56
55
|
|
57
56
|
def run_start(version)
|
58
57
|
@eventlog.report_event(
|
59
|
-
:event_type => EventLog::INFO_TYPE,
|
58
|
+
:event_type => ::Win32::EventLog::INFO_TYPE,
|
60
59
|
:source => SOURCE,
|
61
60
|
:event_id => RUN_START_EVENT_ID,
|
62
61
|
:data => [version]
|
@@ -66,7 +65,7 @@ class Chef
|
|
66
65
|
def run_started(run_status)
|
67
66
|
@run_status = run_status
|
68
67
|
@eventlog.report_event(
|
69
|
-
:event_type => EventLog::INFO_TYPE,
|
68
|
+
:event_type => ::Win32::EventLog::INFO_TYPE,
|
70
69
|
:source => SOURCE,
|
71
70
|
:event_id => RUN_STARTED_EVENT_ID,
|
72
71
|
:data => [run_status.run_id]
|
@@ -75,7 +74,7 @@ class Chef
|
|
75
74
|
|
76
75
|
def run_completed(node)
|
77
76
|
@eventlog.report_event(
|
78
|
-
:event_type => EventLog::INFO_TYPE,
|
77
|
+
:event_type => ::Win32::EventLog::INFO_TYPE,
|
79
78
|
:source => SOURCE,
|
80
79
|
:event_id => RUN_COMPLETED_EVENT_ID,
|
81
80
|
:data => [@run_status.run_id, @run_status.elapsed_time.to_s]
|
@@ -88,7 +87,7 @@ class Chef
|
|
88
87
|
#Exception backtrace: %5
|
89
88
|
def run_failed(e)
|
90
89
|
@eventlog.report_event(
|
91
|
-
:event_type => EventLog::ERROR_TYPE,
|
90
|
+
:event_type => ::Win32::EventLog::ERROR_TYPE,
|
92
91
|
:source => SOURCE,
|
93
92
|
:event_id => RUN_FAILED_EVENT_ID,
|
94
93
|
:data => [@run_status.run_id,
|
data/lib/chef/exceptions.rb
CHANGED
@@ -126,6 +126,13 @@ class Chef
|
|
126
126
|
|
127
127
|
class CannotDetermineHomebrewOwner < Package; end
|
128
128
|
|
129
|
+
# Can not create staging file during file deployment
|
130
|
+
class FileContentStagingError < RuntimeError
|
131
|
+
def initialize(errors)
|
132
|
+
super "Staging tempfile can not be created during file deployment.\n Errors: #{errors.join('\n')}!"
|
133
|
+
end
|
134
|
+
end
|
135
|
+
|
129
136
|
# A different version of a cookbook was added to a
|
130
137
|
# VersionedRecipeList than the one already there.
|
131
138
|
class CookbookVersionConflict < ArgumentError ; end
|
@@ -155,7 +162,12 @@ class Chef
|
|
155
162
|
# Node::Attribute computes the merged version of of attributes
|
156
163
|
# and makes it read-only. Attempting to modify a read-only
|
157
164
|
# attribute will cause this error.
|
158
|
-
class ImmutableAttributeModification < NoMethodError
|
165
|
+
class ImmutableAttributeModification < NoMethodError
|
166
|
+
def initialize
|
167
|
+
super "Node attributes are read-only when you do not specify which precedence level to set. " +
|
168
|
+
%Q(To set an attribute use code like `node.default["key"] = "value"')
|
169
|
+
end
|
170
|
+
end
|
159
171
|
|
160
172
|
# Merged node attributes are invalidated when the component
|
161
173
|
# attributes are updated. Attempting to read from a stale copy
|
@@ -35,7 +35,22 @@ class Chef
|
|
35
35
|
private
|
36
36
|
|
37
37
|
def tempfile_open
|
38
|
-
tf =
|
38
|
+
tf = nil
|
39
|
+
errors = [ ]
|
40
|
+
|
41
|
+
tempfile_dirnames.each do |tempfile_dirname|
|
42
|
+
begin
|
43
|
+
tf = ::Tempfile.open(tempfile_basename, tempfile_dirname)
|
44
|
+
break
|
45
|
+
rescue SystemCallError => e
|
46
|
+
message = "Creating temp file under '#{tempfile_dirname}' failed with: '#{e.message}'"
|
47
|
+
Chef::Log.debug(message)
|
48
|
+
errors << message
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
raise Chef::Exceptions::FileContentStagingError(errors) if tf.nil?
|
53
|
+
|
39
54
|
# We always process the tempfile in binmode so that we
|
40
55
|
# preserve the line endings of the content.
|
41
56
|
tf.binmode
|
@@ -53,16 +68,29 @@ class Chef
|
|
53
68
|
basename
|
54
69
|
end
|
55
70
|
|
56
|
-
|
71
|
+
# Returns the possible directories for the tempfile to be created in.
|
72
|
+
def tempfile_dirnames
|
57
73
|
# in why-run mode we need to create a Tempfile to compare against, which we will never
|
58
74
|
# wind up deploying, but our enclosing directory for the destdir may not exist yet, so
|
59
75
|
# instead we can reliably always create a Tempfile to compare against in Dir::tmpdir
|
60
|
-
if Chef::Config[:
|
61
|
-
|
76
|
+
if Chef::Config[:why_run]
|
77
|
+
[ Dir.tmpdir ]
|
62
78
|
else
|
63
|
-
|
79
|
+
case Chef::Config[:file_staging_uses_destdir]
|
80
|
+
when :auto
|
81
|
+
# In auto mode we try the destination directory first and fallback to ENV['TMP'] if
|
82
|
+
# that doesn't work.
|
83
|
+
[ ::File.dirname(@new_resource.path), Dir.tmpdir ]
|
84
|
+
when true
|
85
|
+
[ ::File.dirname(@new_resource.path) ]
|
86
|
+
when false
|
87
|
+
[ Dir.tmpdir ]
|
88
|
+
else
|
89
|
+
raise Chef::Exceptions::ConfigurationError, "Unknown setting '#{Chef::Config[:file_staging_uses_destdir]}' for Chef::Config[:file_staging_uses_destdir]. Possible values are :auto, true or false."
|
90
|
+
end
|
64
91
|
end
|
65
92
|
end
|
93
|
+
|
66
94
|
end
|
67
95
|
end
|
68
96
|
end
|
data/lib/chef/knife.rb
CHANGED
@@ -72,6 +72,11 @@ class Chef
|
|
72
72
|
ui.msg(msg)
|
73
73
|
end
|
74
74
|
|
75
|
+
def self.reset_config_loader!
|
76
|
+
@@chef_config_dir = nil
|
77
|
+
@config_loader = nil
|
78
|
+
end
|
79
|
+
|
75
80
|
def self.reset_subcommands!
|
76
81
|
@@subcommands = {}
|
77
82
|
@subcommands_by_category = nil
|
@@ -162,12 +167,15 @@ class Chef
|
|
162
167
|
# Shared with subclasses
|
163
168
|
@@chef_config_dir = nil
|
164
169
|
|
170
|
+
def self.config_loader
|
171
|
+
@config_loader ||= WorkstationConfigLoader.new(nil, Chef::Log)
|
172
|
+
end
|
173
|
+
|
165
174
|
def self.load_config(explicit_config_file)
|
166
|
-
config_loader =
|
175
|
+
config_loader.explicit_config_file = explicit_config_file
|
167
176
|
config_loader.load
|
168
177
|
|
169
178
|
ui.warn("No knife configuration file found") if config_loader.no_config_found?
|
170
|
-
@@chef_config_dir = config_loader.chef_config_dir
|
171
179
|
|
172
180
|
config_loader
|
173
181
|
rescue Exceptions::ConfigurationError => e
|
@@ -176,7 +184,7 @@ class Chef
|
|
176
184
|
end
|
177
185
|
|
178
186
|
def self.chef_config_dir
|
179
|
-
@@chef_config_dir
|
187
|
+
@@chef_config_dir ||= config_loader.chef_config_dir
|
180
188
|
end
|
181
189
|
|
182
190
|
# Run knife for the given +args+ (ARGV), adding +options+ to the list of
|
data/lib/chef/knife/bootstrap.rb
CHANGED
@@ -194,13 +194,15 @@ class Chef
|
|
194
194
|
:description => "Verify the SSL cert for HTTPS requests to the Chef server API.",
|
195
195
|
:boolean => true
|
196
196
|
|
197
|
+
def default_bootstrap_template
|
198
|
+
"chef-full"
|
199
|
+
end
|
200
|
+
|
197
201
|
def bootstrap_template
|
198
|
-
#
|
199
|
-
#
|
200
|
-
#
|
201
|
-
|
202
|
-
# if no option is specified.
|
203
|
-
config[:bootstrap_template] || config[:distro] || config[:template_file] || Chef::Config[:knife][:bootstrap_template]
|
202
|
+
# The order here is important. We want to check if we have the new Chef 12 option is set first.
|
203
|
+
# Knife cloud plugins unfortunately all set a default option for the :distro so it should be at
|
204
|
+
# the end.
|
205
|
+
config[:bootstrap_template] || config[:template_file] || config[:distro] || default_bootstrap_template
|
204
206
|
end
|
205
207
|
|
206
208
|
def find_template
|
@@ -210,7 +212,6 @@ class Chef
|
|
210
212
|
if File.exists?(template)
|
211
213
|
Chef::Log.debug("Using the specified bootstrap template: #{File.dirname(template)}")
|
212
214
|
return template
|
213
|
-
|
214
215
|
end
|
215
216
|
|
216
217
|
# Otherwise search the template directories until we find the right one
|
@@ -27,16 +27,6 @@ class Chef
|
|
27
27
|
# http://trac.misuse.org/science/wiki/DeepMerge
|
28
28
|
module DeepMerge
|
29
29
|
|
30
|
-
class InvalidSubtractiveMerge < ArgumentError; end
|
31
|
-
|
32
|
-
OLD_KNOCKOUT_PREFIX = "!merge:".freeze
|
33
|
-
|
34
|
-
# Regex to match the "knockout prefix" that was used to indicate
|
35
|
-
# subtractive merging in Chef 10.x and previous. Subtractive merging is
|
36
|
-
# removed as of Chef 11, but we detect attempted use of it and raise an
|
37
|
-
# error (see: raise_if_knockout_used!)
|
38
|
-
OLD_KNOCKOUT_MATCH = %r[!merge].freeze
|
39
|
-
|
40
30
|
extend self
|
41
31
|
|
42
32
|
def merge(first, second)
|
@@ -46,15 +36,6 @@ class Chef
|
|
46
36
|
DeepMerge.deep_merge(second, first)
|
47
37
|
end
|
48
38
|
|
49
|
-
# Inherited roles use the knockout_prefix array subtraction functionality
|
50
|
-
# This is likely to go away in Chef >= 0.11
|
51
|
-
def role_merge(first, second)
|
52
|
-
first = Mash.new(first) unless first.kind_of?(Mash)
|
53
|
-
second = Mash.new(second) unless second.kind_of?(Mash)
|
54
|
-
|
55
|
-
DeepMerge.deep_merge(second, first)
|
56
|
-
end
|
57
|
-
|
58
39
|
class InvalidParameter < StandardError; end
|
59
40
|
|
60
41
|
# Deep Merge core documentation.
|
@@ -77,22 +58,15 @@ class Chef
|
|
77
58
|
dest = source; return dest
|
78
59
|
end
|
79
60
|
|
80
|
-
raise_if_knockout_used!(source)
|
81
|
-
raise_if_knockout_used!(dest)
|
82
61
|
case source
|
83
62
|
when nil
|
84
63
|
dest
|
85
64
|
when Hash
|
86
65
|
if dest.kind_of?(Hash)
|
87
66
|
source.each do |src_key, src_value|
|
88
|
-
if dest
|
89
|
-
|
90
|
-
dest[src_key] = nil
|
91
|
-
else
|
92
|
-
dest[src_key] = deep_merge!(src_value, dest[src_key])
|
93
|
-
end
|
67
|
+
if dest[src_key]
|
68
|
+
dest[src_key] = deep_merge!(src_value, dest[src_key])
|
94
69
|
else # dest[src_key] doesn't exist so we take whatever source has
|
95
|
-
raise_if_knockout_used!(src_value)
|
96
70
|
dest[src_key] = src_value
|
97
71
|
end
|
98
72
|
end
|
@@ -131,11 +105,19 @@ class Chef
|
|
131
105
|
# If there are two Hashes, recursively merge.
|
132
106
|
if merge_onto.kind_of?(Hash) && merge_with.kind_of?(Hash)
|
133
107
|
merge_with.each do |key, merge_with_value|
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
108
|
+
value =
|
109
|
+
if merge_onto.has_key?(key)
|
110
|
+
hash_only_merge(merge_onto[key], merge_with_value)
|
111
|
+
else
|
112
|
+
merge_with_value
|
113
|
+
end
|
114
|
+
|
115
|
+
if merge_onto.respond_to?(:public_method_that_only_deep_merge_should_use)
|
116
|
+
# we can't call ImmutableMash#[]= because its immutable, but we need to mutate it to build it in-place
|
117
|
+
merge_onto.public_method_that_only_deep_merge_should_use(key, value)
|
118
|
+
else
|
119
|
+
merge_onto[key] = value
|
120
|
+
end
|
139
121
|
end
|
140
122
|
merge_onto
|
141
123
|
|
@@ -149,27 +131,6 @@ class Chef
|
|
149
131
|
end
|
150
132
|
end
|
151
133
|
|
152
|
-
# Checks for attempted use of subtractive merge, which was removed for
|
153
|
-
# Chef 11.0. If subtractive merge use is detected, will raise an
|
154
|
-
# InvalidSubtractiveMerge exception.
|
155
|
-
def raise_if_knockout_used!(obj)
|
156
|
-
if uses_knockout?(obj)
|
157
|
-
raise InvalidSubtractiveMerge, "subtractive merge with !merge is no longer supported"
|
158
|
-
end
|
159
|
-
end
|
160
|
-
|
161
|
-
# Checks for attempted use of subtractive merge in +obj+.
|
162
|
-
def uses_knockout?(obj)
|
163
|
-
case obj
|
164
|
-
when String
|
165
|
-
obj =~ OLD_KNOCKOUT_MATCH
|
166
|
-
when Array
|
167
|
-
obj.any? {|element| element.respond_to?(:gsub) && element =~ OLD_KNOCKOUT_MATCH }
|
168
|
-
else
|
169
|
-
false
|
170
|
-
end
|
171
|
-
end
|
172
|
-
|
173
134
|
def deep_merge(source, dest)
|
174
135
|
deep_merge!(safe_dup(source), safe_dup(dest))
|
175
136
|
end
|