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.
Files changed (60) hide show
  1. checksums.yaml +7 -0
  2. data/README.md +1 -1
  3. data/lib/chef/api_client/registration.rb +3 -1
  4. data/lib/chef/chef_fs/data_handler/group_data_handler.rb +4 -0
  5. data/lib/chef/config.rb +46 -38
  6. data/lib/chef/event_loggers/windows_eventlog.rb +5 -6
  7. data/lib/chef/exceptions.rb +13 -1
  8. data/lib/chef/file_content_management/tempfile.rb +33 -5
  9. data/lib/chef/knife.rb +11 -3
  10. data/lib/chef/knife/bootstrap.rb +8 -7
  11. data/lib/chef/mixin/deep_merge.rb +15 -54
  12. data/lib/chef/mixin/which.rb +37 -0
  13. data/lib/chef/node.rb +14 -25
  14. data/lib/chef/node/attribute.rb +227 -41
  15. data/lib/chef/node/attribute_collections.rb +117 -3
  16. data/lib/chef/node/immutable_collections.rb +6 -6
  17. data/lib/chef/platform/provider_priority_map.rb +3 -2
  18. data/lib/chef/platform/service_helpers.rb +37 -8
  19. data/lib/chef/provider/service/aixinit.rb +1 -1
  20. data/lib/chef/provider/service/arch.rb +1 -1
  21. data/lib/chef/provider/service/debian.rb +5 -1
  22. data/lib/chef/provider/service/init.rb +4 -0
  23. data/lib/chef/provider/service/insserv.rb +5 -1
  24. data/lib/chef/provider/service/invokercd.rb +5 -1
  25. data/lib/chef/provider/service/redhat.rb +5 -1
  26. data/lib/chef/provider/service/systemd.rb +50 -32
  27. data/lib/chef/provider/service/upstart.rb +5 -2
  28. data/lib/chef/provider_resolver.rb +30 -16
  29. data/lib/chef/resource.rb +2 -1
  30. data/lib/chef/resources.rb +7 -0
  31. data/lib/chef/run_context.rb +0 -5
  32. data/lib/chef/run_list/run_list_expansion.rb +2 -2
  33. data/lib/chef/shell.rb +2 -2
  34. data/lib/chef/util/selinux.rb +2 -10
  35. data/lib/chef/version.rb +1 -1
  36. data/lib/chef/workstation_config_loader.rb +1 -1
  37. data/spec/support/shared/unit/resource/static_provider_resolution.rb +1 -6
  38. data/spec/unit/api_client/registration_spec.rb +22 -0
  39. data/spec/unit/application/knife_spec.rb +6 -2
  40. data/spec/unit/chef_fs/data_handler/group_handler_spec.rb +63 -0
  41. data/spec/unit/config_spec.rb +5 -5
  42. data/spec/unit/knife/bootstrap_spec.rb +27 -1
  43. data/spec/unit/knife_spec.rb +5 -0
  44. data/spec/unit/mixin/deep_merge_spec.rb +0 -40
  45. data/spec/unit/node/attribute_spec.rb +37 -50
  46. data/spec/unit/node_spec.rb +321 -13
  47. data/spec/unit/provider/file/content_spec.rb +23 -2
  48. data/spec/unit/provider/service/systemd_service_spec.rb +173 -158
  49. data/spec/unit/provider_resolver_spec.rb +175 -10
  50. data/spec/unit/resource/timestamped_deploy_spec.rb +8 -29
  51. data/spec/unit/runner_spec.rb +3 -1
  52. metadata +147 -221
  53. data/spec/.DS_Store +0 -0
  54. data/spec/data/.DS_Store +0 -0
  55. data/spec/data/lwrp/.DS_Store +0 -0
  56. data/spec/data/lwrp/providers/.DS_Store +0 -0
  57. data/spec/data/lwrp/resources/.DS_Store +0 -0
  58. data/spec/data/lwrp_override/.DS_Store +0 -0
  59. data/spec/data/lwrp_override/providers/.DS_Store +0 -0
  60. data/spec/data/lwrp_override/resources/.DS_Store +0 -0
@@ -0,0 +1,37 @@
1
+ #--
2
+ # Author:: Lamont Granquist <lamont@getchef.io>
3
+ # Copyright:: Copyright (c) 2010 Opscode, Inc.
4
+ # License:: Apache License, Version 2.0
5
+ #
6
+ # Licensed under the Apache License, Version 2.0 (the "License");
7
+ # you may not use this file except in compliance with the License.
8
+ # You may obtain a copy of the License at
9
+ #
10
+ # http://www.apache.org/licenses/LICENSE-2.0
11
+ #
12
+ # Unless required by applicable law or agreed to in writing, software
13
+ # distributed under the License is distributed on an "AS IS" BASIS,
14
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
+ # See the License for the specific language governing permissions and
16
+ # limitations under the License.
17
+
18
+ class Chef
19
+ module Mixin
20
+ module Which
21
+ def which(cmd, opts = {})
22
+ extra_path =
23
+ if opts[:extra_path].nil?
24
+ [ '/bin', '/usr/bin', '/sbin', '/usr/sbin' ]
25
+ else
26
+ [ opts[:extra_path] ].flatten
27
+ end
28
+ paths = ENV['PATH'].split(File::PATH_SEPARATOR) + extra_path
29
+ paths.each do |path|
30
+ filename = File.join(path, cmd)
31
+ return filename if File.executable?(filename)
32
+ end
33
+ false
34
+ end
35
+ end
36
+ end
37
+ end
@@ -42,6 +42,8 @@ class Chef
42
42
  extend Forwardable
43
43
 
44
44
  def_delegators :attributes, :keys, :each_key, :each_value, :key?, :has_key?
45
+ def_delegators :attributes, :rm, :rm_default, :rm_normal, :rm_override
46
+ def_delegators :attributes, :default!, :normal!, :override!, :force_default!, :force_override!
45
47
 
46
48
  attr_accessor :recipe_list, :run_state, :override_runlist
47
49
 
@@ -125,6 +127,7 @@ class Chef
125
127
  # Set a normal attribute of this node, but auto-vivify any Mashes that
126
128
  # might be missing
127
129
  def normal
130
+ attributes.top_level_breadcrumb = nil
128
131
  attributes.set_unless_value_present = false
129
132
  attributes.normal
130
133
  end
@@ -134,28 +137,25 @@ class Chef
134
137
  # Set a normal attribute of this node, auto-vivifying any mashes that are
135
138
  # missing, but if the final value already exists, don't set it
136
139
  def normal_unless
140
+ attributes.top_level_breadcrumb = nil
137
141
  attributes.set_unless_value_present = true
138
142
  attributes.normal
139
143
  end
144
+
140
145
  alias_method :set_unless, :normal_unless
141
146
 
142
147
  # Set a default of this node, but auto-vivify any Mashes that might
143
148
  # be missing
144
149
  def default
150
+ attributes.top_level_breadcrumb = nil
145
151
  attributes.set_unless_value_present = false
146
152
  attributes.default
147
153
  end
148
154
 
149
- # Set a force default attribute. Intermediate mashes will be created by
150
- # auto-vivify if necessary.
151
- def default!
152
- attributes.set_unless_value_present = false
153
- attributes.default!
154
- end
155
-
156
155
  # Set a default attribute of this node, auto-vivifying any mashes that are
157
156
  # missing, but if the final value already exists, don't set it
158
157
  def default_unless
158
+ attributes.top_level_breadcrumb = nil
159
159
  attributes.set_unless_value_present = true
160
160
  attributes.default
161
161
  end
@@ -163,49 +163,38 @@ class Chef
163
163
  # Set an override attribute of this node, but auto-vivify any Mashes that
164
164
  # might be missing
165
165
  def override
166
+ attributes.top_level_breadcrumb = nil
166
167
  attributes.set_unless_value_present = false
167
168
  attributes.override
168
169
  end
169
170
 
170
- # Set a force override attribute. Intermediate mashes will be created by
171
- # auto-vivify if needed.
172
- def override!
173
- attributes.set_unless_value_present = false
174
- attributes.override!
175
- end
176
-
177
171
  # Set an override attribute of this node, auto-vivifying any mashes that
178
172
  # are missing, but if the final value already exists, don't set it
179
173
  def override_unless
174
+ attributes.top_level_breadcrumb = nil
180
175
  attributes.set_unless_value_present = true
181
176
  attributes.override
182
177
  end
183
178
 
184
- def override_attrs
185
- attributes.override
186
- end
179
+ alias :override_attrs :override
180
+ alias :default_attrs :default
181
+ alias :normal_attrs :normal
187
182
 
188
183
  def override_attrs=(new_values)
189
184
  attributes.override = new_values
190
185
  end
191
186
 
192
- def default_attrs
193
- attributes.default
194
- end
195
-
196
187
  def default_attrs=(new_values)
197
188
  attributes.default = new_values
198
189
  end
199
190
 
200
- def normal_attrs
201
- attributes.normal
202
- end
203
-
204
191
  def normal_attrs=(new_values)
205
192
  attributes.normal = new_values
206
193
  end
207
194
 
208
195
  def automatic_attrs
196
+ attributes.top_level_breadcrumb = nil
197
+ attributes.set_unless_value_present = false
209
198
  attributes.automatic
210
199
  end
211
200
 
@@ -58,7 +58,6 @@ class Chef
58
58
  :@force_default
59
59
  ]
60
60
 
61
-
62
61
  OVERRIDE_COMPONENTS = [
63
62
  :@override,
64
63
  :@role_override,
@@ -146,7 +145,6 @@ class Chef
146
145
  METHOD_DEFN
147
146
  end
148
147
 
149
-
150
148
  # return the cookbook level default attribute component
151
149
  attr_reader :default
152
150
 
@@ -159,11 +157,6 @@ class Chef
159
157
  # return the force_default level attribute component
160
158
  attr_reader :force_default
161
159
 
162
- # default! is the "advertised" method for force_default, but is
163
- # implemented as an alias because instance variables can't (easily) have
164
- # +!+ characters.
165
- alias :default! :force_default
166
-
167
160
  # return the "normal" level attribute component
168
161
  attr_reader :normal
169
162
 
@@ -179,14 +172,22 @@ class Chef
179
172
  # return the force override level attribute component
180
173
  attr_reader :force_override
181
174
 
182
- # +override!+ is the "advertised" method for +force_override+ but is
183
- # implemented as an alias because instance variables can't easily have
184
- # +!+ characters.
185
- alias :override! :force_override
186
-
187
175
  # return the automatic level attribute component
188
176
  attr_reader :automatic
189
177
 
178
+ # This is used to track the top level key as we descend through method chaining into
179
+ # a precedence level (e.g. node.default['foo']['bar']['baz']= results in 'foo' here). We
180
+ # need this so that when we hit the end of a method chain which results in a mutator method
181
+ # that we can invalidate the whole top-level deep merge cache for the top-level key. It is
182
+ # the responsibility of the accessor on the Chef::Node object to reset this to nil, and then
183
+ # the first VividMash#[] call can ||= and set this to the first key we encounter.
184
+ attr_accessor :top_level_breadcrumb
185
+
186
+ # Cache of deep merged values by top-level key. This is a simple hash which has keys that are the
187
+ # top-level keys of the node object, and we save the computed deep-merge for that key here. There is
188
+ # no cache of subtrees.
189
+ attr_accessor :deep_merge_cache
190
+
190
191
  def initialize(normal, default, override, automatic)
191
192
  @set_unless_present = false
192
193
 
@@ -207,6 +208,8 @@ class Chef
207
208
  @merged_attributes = nil
208
209
  @combined_override = nil
209
210
  @combined_default = nil
211
+ @top_level_breadcrumb = nil
212
+ @deep_merge_cache = {}
210
213
  end
211
214
 
212
215
  # Debug what's going on with an attribute. +args+ is a path spec to the
@@ -242,13 +245,16 @@ class Chef
242
245
  @set_unless_present = setting
243
246
  end
244
247
 
245
- # Clears merged_attributes, which will cause it to be recomputed on the
246
- # next access.
247
- def reset_cache
248
- @merged_attributes = nil
249
- @combined_default = nil
250
- @combined_override = nil
251
- @set_unless_present = false
248
+ # Invalidate a key in the deep_merge_cache. If called with nil, or no arg, this will invalidate
249
+ # the entire deep_merge cache. In the case of the user doing node.default['foo']['bar']['baz']=
250
+ # that eventually results in a call to reset_cache('foo') here. A node.default=hash_thing call
251
+ # must invalidate the entire cache and re-deep-merge the entire node object.
252
+ def reset_cache(path = nil)
253
+ if path.nil?
254
+ @deep_merge_cache = {}
255
+ else
256
+ deep_merge_cache.delete(path)
257
+ end
252
258
  end
253
259
 
254
260
  alias :reset :reset_cache
@@ -311,30 +317,136 @@ class Chef
311
317
  @automatic = VividMash.new(self, new_data)
312
318
  end
313
319
 
314
- def merged_attributes
315
- @merged_attributes ||= begin
316
- components = [merge_defaults, @normal, merge_overrides, @automatic]
317
- resolved_attrs = components.inject(Mash.new) do |merged, component|
318
- Chef::Mixin::DeepMerge.hash_only_merge(merged, component)
319
- end
320
- immutablize(resolved_attrs)
321
- end
320
+ #
321
+ # Deleting attributes
322
+ #
323
+
324
+ # clears attributes from all precedence levels
325
+ def rm(*args)
326
+ reset(args[0])
327
+ # just easier to compute our retval, rather than collect+merge sub-retvals
328
+ ret = args.inject(merged_attributes) do |attr, arg|
329
+ if attr.nil? || !attr.respond_to?(:[])
330
+ nil
331
+ else
332
+ begin
333
+ attr[arg]
334
+ rescue TypeError
335
+ raise TypeError, "Wrong type in index of attribute (did you use a Hash index on an Array?)"
336
+ end
337
+ end
338
+ end
339
+ rm_default(*args)
340
+ rm_normal(*args)
341
+ rm_override(*args)
342
+ ret
343
+ end
344
+
345
+ # does <level>['foo']['bar'].delete('baz')
346
+ def remove_from_precedence_level(level, *args, key)
347
+ multimash = level.element(*args)
348
+ multimash.nil? ? nil : multimash.delete(key)
349
+ end
350
+
351
+ private :remove_from_precedence_level
352
+
353
+ # clears attributes from all default precedence levels
354
+ #
355
+ # equivalent to: force_default!['foo']['bar'].delete('baz')
356
+ def rm_default(*args)
357
+ reset(args[0])
358
+ remove_from_precedence_level(force_default!(autovivify: false), *args)
359
+ end
360
+
361
+ # clears attributes from normal precedence
362
+ #
363
+ # equivalent to: normal!['foo']['bar'].delete('baz')
364
+ def rm_normal(*args)
365
+ reset(args[0])
366
+ remove_from_precedence_level(normal!(autovivify: false), *args)
367
+ end
368
+
369
+ # clears attributes from all override precedence levels
370
+ #
371
+ # equivalent to: force_override!['foo']['bar'].delete('baz')
372
+ def rm_override(*args)
373
+ reset(args[0])
374
+ remove_from_precedence_level(force_override!(autovivify: false), *args)
375
+ end
376
+
377
+ #
378
+ # Replacing attributes without merging
379
+ #
380
+
381
+ # sets default attributes without merging
382
+ def default!(opts={})
383
+ # FIXME: do not flush whole cache
384
+ reset
385
+ MultiMash.new(self, @default, [], opts)
386
+ end
387
+
388
+ # sets normal attributes without merging
389
+ def normal!(opts={})
390
+ # FIXME: do not flush whole cache
391
+ reset
392
+ MultiMash.new(self, @normal, [], opts)
393
+ end
394
+
395
+ # sets override attributes without merging
396
+ def override!(opts={})
397
+ # FIXME: do not flush whole cache
398
+ reset
399
+ MultiMash.new(self, @override, [], opts)
322
400
  end
323
401
 
324
- def combined_override
325
- @combined_override ||= immutablize(merge_overrides)
402
+ # clears from all default precedence levels and then sets force_default
403
+ def force_default!(opts={})
404
+ # FIXME: do not flush whole cache
405
+ reset
406
+ MultiMash.new(self, @force_default, [@default, @env_default, @role_default], opts)
326
407
  end
327
408
 
328
- def combined_default
329
- @combined_default ||= immutablize(merge_defaults)
409
+ # clears from all override precedence levels and then sets force_override
410
+ def force_override!(opts={})
411
+ # FIXME: do not flush whole cache
412
+ reset
413
+ MultiMash.new(self, @force_override, [@override, @env_override, @role_override], opts)
414
+ end
415
+
416
+ #
417
+ # Accessing merged attributes.
418
+ #
419
+ # Note that merged_attributes('foo', 'bar', 'baz') can be called to compute only the
420
+ # deep merge of node['foo']['bar']['baz'], but in practice we currently always compute
421
+ # all of node['foo'] even if the user only requires node['foo']['bar']['baz'].
422
+ #
423
+
424
+ def merged_attributes(*path)
425
+ # immutablize(
426
+ merge_all(path)
427
+ # )
428
+ end
429
+
430
+ def combined_override(*path)
431
+ immutablize(merge_overrides(path))
432
+ end
433
+
434
+ def combined_default(*path)
435
+ immutablize(merge_defaults(path))
330
436
  end
331
437
 
332
438
  def [](key)
333
- merged_attributes[key]
439
+ if deep_merge_cache.has_key?(key)
440
+ # return the cache of the deep merged values by top-level key
441
+ deep_merge_cache[key]
442
+ else
443
+ # save all the work of computing node[key]
444
+ deep_merge_cache[key] = merged_attributes(key)
445
+ end
334
446
  end
335
447
 
336
448
  def []=(key, value)
337
- merged_attributes[key] = value
449
+ raise Exceptions::ImmutableAttributeModification
338
450
  end
339
451
 
340
452
  def has_key?(key)
@@ -377,20 +489,94 @@ class Chef
377
489
 
378
490
  private
379
491
 
380
- def merge_defaults
381
- DEFAULT_COMPONENTS.inject(Mash.new) do |merged, component_ivar|
382
- component_value = instance_variable_get(component_ivar)
383
- Chef::Mixin::DeepMerge.merge(merged, component_value)
492
+ # Helper method for merge_all/merge_defaults/merge_overrides.
493
+ #
494
+ # apply_path(thing, [ "foo", "bar", "baz" ]) = thing["foo"]["bar"]["baz"]
495
+ #
496
+ # The path value can be nil in which case the whole component is returned.
497
+ #
498
+ # It returns nil (does not raise an exception) if it walks off the end of an Mash/Hash/Array, it does not
499
+ # raise any TypeError if it attempts to apply a hash key to an Integer/String/TrueClass, and just returns
500
+ # nil in that case.
501
+ #
502
+ def apply_path(component, path)
503
+ path ||= []
504
+ path.inject(component) do |val, path_arg|
505
+ if val.respond_to?(:[])
506
+ # Have an Array-like or Hash-like thing
507
+ if !val.respond_to?(:has_key?)
508
+ # Have an Array-like thing
509
+ val[path_arg]
510
+ elsif val.has_key?(path_arg)
511
+ # Hash-like thing (must check has_key? first to protect against Autovivification)
512
+ val[path_arg]
513
+ else
514
+ nil
515
+ end
516
+ else
517
+ nil
518
+ end
519
+ end
520
+ end
521
+
522
+ # For elements like Fixnums, true, nil...
523
+ def safe_dup(e)
524
+ e.dup
525
+ rescue TypeError
526
+ e
527
+ end
528
+
529
+ # Deep merge all attribute levels using hash-only merging between different precidence
530
+ # levels (so override arrays completely replace arrays set at any default level).
531
+ #
532
+ # The path allows for selectively deep-merging a subtree of the node object.
533
+ #
534
+ # @param path [Array] Array of args to method chain to descend into the node object
535
+ # @return [attr] Deep Merged values (may be VividMash, Hash, Array, etc) from the node object
536
+ def merge_all(path)
537
+ components = [
538
+ merge_defaults(path),
539
+ apply_path(@normal, path),
540
+ merge_overrides(path),
541
+ apply_path(@automatic, path),
542
+ ]
543
+
544
+ components.map! do |component|
545
+ safe_dup(component)
546
+ end
547
+
548
+ return nil if components.compact.empty?
549
+
550
+ components.inject(ImmutableMash.new({})) do |merged, component|
551
+ Chef::Mixin::DeepMerge.hash_only_merge!(merged, component)
384
552
  end
385
553
  end
386
554
 
387
- def merge_overrides
388
- OVERRIDE_COMPONENTS.inject(Mash.new) do |merged, component_ivar|
389
- component_value = instance_variable_get(component_ivar)
390
- Chef::Mixin::DeepMerge.merge(merged, component_value)
555
+ # Deep merge the default attribute levels with array merging.
556
+ #
557
+ # The path allows for selectively deep-merging a subtree of the node object.
558
+ #
559
+ # @param path [Array] Array of args to method chain to descend into the node object
560
+ # @return [attr] Deep Merged values (may be VividMash, Hash, Array, etc) from the node object
561
+ def merge_defaults(path)
562
+ DEFAULT_COMPONENTS.inject(nil) do |merged, component_ivar|
563
+ component_value = apply_path(instance_variable_get(component_ivar), path)
564
+ Chef::Mixin::DeepMerge.deep_merge(component_value, merged)
391
565
  end
392
566
  end
393
567
 
568
+ # Deep merge the override attribute levels with array merging.
569
+ #
570
+ # The path allows for selectively deep-merging a subtree of the node object.
571
+ #
572
+ # @param path [Array] Array of args to method chain to descend into the node object
573
+ # @return [attr] Deep Merged values (may be VividMash, Hash, Array, etc) from the node object
574
+ def merge_overrides(path)
575
+ OVERRIDE_COMPONENTS.inject(nil) do |merged, component_ivar|
576
+ component_value = apply_path(instance_variable_get(component_ivar), path)
577
+ Chef::Mixin::DeepMerge.deep_merge(component_value, merged)
578
+ end
579
+ end
394
580
 
395
581
  end
396
582