chef 15.2.20 → 15.3.14

Sign up to get free protection for your applications and to get access to all the features.
Files changed (92) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +1 -2
  3. data/chef.gemspec +3 -2
  4. data/lib/chef/application.rb +1 -1
  5. data/lib/chef/application/base.rb +7 -0
  6. data/lib/chef/application/client.rb +6 -2
  7. data/lib/chef/application/solo.rb +7 -1
  8. data/lib/chef/cookbook/gem_installer.rb +7 -2
  9. data/lib/chef/exceptions.rb +12 -0
  10. data/lib/chef/knife/bootstrap.rb +8 -1
  11. data/lib/chef/knife/bootstrap/templates/chef-full.erb +1 -1
  12. data/lib/chef/knife/bootstrap/train_connector.rb +3 -3
  13. data/lib/chef/knife/cookbook_metadata_from_file.rb +1 -1
  14. data/lib/chef/node.rb +0 -2
  15. data/lib/chef/policy_builder/expand_node_object.rb +1 -1
  16. data/lib/chef/policy_builder/policyfile.rb +4 -3
  17. data/lib/chef/provider.rb +4 -2
  18. data/lib/chef/provider/ifconfig.rb +5 -3
  19. data/lib/chef/provider/package/chocolatey.rb +12 -22
  20. data/lib/chef/provider/user.rb +1 -1
  21. data/lib/chef/provider/user/dscl.rb +2 -2
  22. data/lib/chef/provider/user/mac.rb +628 -0
  23. data/lib/chef/providers.rb +1 -0
  24. data/lib/chef/resource.rb +28 -20
  25. data/lib/chef/resource/chocolatey_feature.rb +1 -1
  26. data/lib/chef/resource/chocolatey_package.rb +2 -2
  27. data/lib/chef/resource/cron_d.rb +1 -1
  28. data/lib/chef/resource/ohai.rb +1 -1
  29. data/lib/chef/resource/resource_notification.rb +17 -13
  30. data/lib/chef/resource/ruby_block.rb +1 -1
  31. data/lib/chef/resource/service.rb +1 -1
  32. data/lib/chef/resource/user.rb +1 -0
  33. data/lib/chef/resource/user/dscl_user.rb +1 -1
  34. data/lib/chef/resource/user/mac_user.rb +119 -0
  35. data/lib/chef/resource/windows_ad_join.rb +1 -1
  36. data/lib/chef/resource_collection.rb +6 -0
  37. data/lib/chef/resources.rb +1 -0
  38. data/lib/chef/run_context.rb +61 -27
  39. data/lib/chef/runner.rb +50 -12
  40. data/lib/chef/version.rb +1 -1
  41. data/spec/functional/resource/chocolatey_package_spec.rb +19 -1
  42. data/spec/functional/resource/user/mac_user_spec.rb +207 -0
  43. data/spec/integration/client/client_spec.rb +22 -0
  44. data/spec/integration/knife/raw_spec.rb +39 -19
  45. data/spec/integration/knife/redirection_spec.rb +22 -13
  46. data/spec/integration/knife/serve_spec.rb +1 -2
  47. data/spec/integration/recipes/unified_mode_spec.rb +876 -0
  48. data/spec/spec_helper.rb +1 -0
  49. data/spec/support/platform_helpers.rb +10 -0
  50. data/spec/support/shared/integration/integration_helper.rb +1 -2
  51. data/spec/unit/application/client_spec.rb +5 -6
  52. data/spec/unit/application/solo_spec.rb +3 -8
  53. data/spec/unit/application_spec.rb +1 -1
  54. data/spec/unit/cookbook/gem_installer_spec.rb +22 -1
  55. data/spec/unit/knife/bootstrap/train_connector_spec.rb +20 -7
  56. data/spec/unit/knife/bootstrap_spec.rb +13 -5
  57. data/spec/unit/provider/ifconfig_spec.rb +11 -0
  58. data/spec/unit/provider/package/chocolatey_spec.rb +34 -30
  59. data/spec/unit/provider/user/dscl_spec.rb +1 -0
  60. data/spec/unit/provider/user/mac_spec.rb +38 -0
  61. data/spec/unit/provider/user_spec.rb +38 -22
  62. data/tasks/docs.rb +14 -10
  63. metadata +25 -41
  64. data/lib/.DS_Store +0 -0
  65. data/lib/chef/.DS_Store +0 -0
  66. data/lib/chef/dsl/.DS_Store +0 -0
  67. data/lib/chef/knife/.DS_Store +0 -0
  68. data/lib/chef/mixin/.DS_Store +0 -0
  69. data/lib/chef/provider/.DS_Store +0 -0
  70. data/lib/chef/provider/package/.DS_Store +0 -0
  71. data/lib/chef/provider/package/freebsd/.DS_Store +0 -0
  72. data/lib/chef/resource/.DS_Store +0 -0
  73. data/lib/chef/resource/file/.DS_Store +0 -0
  74. data/spec/.DS_Store +0 -0
  75. data/spec/data/.DS_Store +0 -0
  76. data/spec/data/cookbooks/.DS_Store +0 -0
  77. data/spec/data/cookbooks/java/.DS_Store +0 -0
  78. data/spec/data/cookbooks/java/files/.DS_Store +0 -0
  79. data/spec/data/mac_users/.DS_Store +0 -0
  80. data/spec/data/nodes/Tim.local.json +0 -3
  81. data/spec/data/nodes/Tims-MBP.local.json +0 -3
  82. data/spec/data/run_context/.DS_Store +0 -0
  83. data/spec/data/run_context/cookbooks/.DS_Store +0 -0
  84. data/spec/functional/.DS_Store +0 -0
  85. data/spec/functional/resource/.DS_Store +0 -0
  86. data/spec/functional/util/.DS_Store +0 -0
  87. data/spec/integration/.DS_Store +0 -0
  88. data/spec/stress/.DS_Store +0 -0
  89. data/spec/support/.DS_Store +0 -0
  90. data/spec/support/shared/integration/app_server_support.rb +0 -39
  91. data/spec/unit/.DS_Store +0 -0
  92. data/tasks/.DS_Store +0 -0
@@ -31,7 +31,7 @@ class Chef
31
31
  introduced "14.0"
32
32
 
33
33
  property :domain_name, String,
34
- description: "The FQDN of the Active Directory domain to join if it differs from the resource block's name.",
34
+ description: "An optional property to set the FQDN of the Active Directory domain to join if it differs from the resource block's name.",
35
35
  validation_message: "The 'domain_name' property must be a FQDN.",
36
36
  regex: /.\../, # anything.anything
37
37
  name_property: true
@@ -32,6 +32,8 @@ class Chef
32
32
  include ResourceCollectionSerialization
33
33
  extend Forwardable
34
34
 
35
+ attr_accessor :unified_mode
36
+
35
37
  attr_reader :resource_set, :resource_list
36
38
  attr_accessor :run_context
37
39
 
@@ -41,6 +43,7 @@ class Chef
41
43
  @run_context = run_context
42
44
  @resource_set = ResourceSet.new
43
45
  @resource_list = ResourceList.new
46
+ @unified_mode = false
44
47
  end
45
48
 
46
49
  # @param resource [Chef::Resource] The resource to insert
@@ -57,6 +60,9 @@ class Chef
57
60
  else
58
61
  resource_set.insert_as(resource)
59
62
  end
63
+ if unified_mode
64
+ run_context.runner.run_all_actions(resource)
65
+ end
60
66
  end
61
67
 
62
68
  def delete(key)
@@ -116,6 +116,7 @@ require_relative "resource/user"
116
116
  require_relative "resource/user/aix_user"
117
117
  require_relative "resource/user/dscl_user"
118
118
  require_relative "resource/user/linux_user"
119
+ require_relative "resource/user/mac_user"
119
120
  require_relative "resource/user/pw_user"
120
121
  require_relative "resource/user/solaris_user"
121
122
  require_relative "resource/user/windows_user"
@@ -26,12 +26,16 @@ require_relative "recipe"
26
26
  require_relative "run_context/cookbook_compiler"
27
27
  require_relative "event_dispatch/events_output_stream"
28
28
  require_relative "train_transport"
29
+ require_relative "exceptions"
29
30
  require "forwardable" unless defined?(Forwardable)
31
+ require "set" unless defined?(Set)
30
32
 
31
33
  class Chef
32
34
 
33
35
  # Value object that loads and tracks the context of a Chef run
34
36
  class RunContext
37
+ extend Forwardable
38
+
35
39
  #
36
40
  # Global state
37
41
  #
@@ -62,7 +66,7 @@ class Chef
62
66
  #
63
67
  # @return [Chef::CookbookCollection]
64
68
  #
65
- attr_accessor :cookbook_collection
69
+ attr_reader :cookbook_collection
66
70
 
67
71
  #
68
72
  # Resource Definitions for this run. Populated when the files in
@@ -72,14 +76,12 @@ class Chef
72
76
  #
73
77
  attr_reader :definitions
74
78
 
75
- #
76
79
  # Event dispatcher for this run.
77
80
  #
78
81
  # @return [Chef::EventDispatch::Dispatcher]
79
82
  #
80
83
  attr_accessor :events
81
84
 
82
- #
83
85
  # Hash of factoids for a reboot request.
84
86
  #
85
87
  # @return [Hash]
@@ -90,7 +92,6 @@ class Chef
90
92
  # Scoped state
91
93
  #
92
94
 
93
- #
94
95
  # The parent run context.
95
96
  #
96
97
  # @return [Chef::RunContext] The parent run context, or `nil` if this is the
@@ -98,7 +99,6 @@ class Chef
98
99
  #
99
100
  attr_reader :parent_run_context
100
101
 
101
- #
102
102
  # The root run context.
103
103
  #
104
104
  # @return [Chef::RunContext] The root run context.
@@ -109,7 +109,6 @@ class Chef
109
109
  rc
110
110
  end
111
111
 
112
- #
113
112
  # The collection of resources intended to be converged (and able to be
114
113
  # notified).
115
114
  #
@@ -119,8 +118,12 @@ class Chef
119
118
  #
120
119
  attr_reader :resource_collection
121
120
 
122
- attr_accessor :action_collection
121
+ # Handle to the global action_collection of executed actions for reporting / data_collector /etc
122
+ #
123
+ # @return [Chef::ActionCollection
123
124
  #
125
+ attr_accessor :action_collection
126
+
124
127
  # Pointer back to the Chef::Runner that created this
125
128
  #
126
129
  attr_accessor :runner
@@ -129,7 +132,6 @@ class Chef
129
132
  # Notification handling
130
133
  #
131
134
 
132
- #
133
135
  # A Hash containing the before notifications triggered by resources
134
136
  # during the converge phase of the chef run.
135
137
  #
@@ -138,7 +140,6 @@ class Chef
138
140
  #
139
141
  attr_reader :before_notification_collection
140
142
 
141
- #
142
143
  # A Hash containing the immediate notifications triggered by resources
143
144
  # during the converge phase of the chef run.
144
145
  #
@@ -147,7 +148,6 @@ class Chef
147
148
  #
148
149
  attr_reader :immediate_notification_collection
149
150
 
150
- #
151
151
  # A Hash containing the delayed (end of run) notifications triggered by
152
152
  # resources during the converge phase of the chef run.
153
153
  #
@@ -156,7 +156,6 @@ class Chef
156
156
  #
157
157
  attr_reader :delayed_notification_collection
158
158
 
159
- #
160
159
  # An Array containing the delayed (end of run) notifications triggered by
161
160
  # resources during the converge phase of the chef run.
162
161
  #
@@ -164,7 +163,16 @@ class Chef
164
163
  #
165
164
  attr_reader :delayed_actions
166
165
 
166
+ # A Set keyed by the string name, of all the resources that are updated. We do not
167
+ # track actions or individual resource objects, since this matches the behavior of
168
+ # the notification collections which are keyed by Strings.
169
+ #
170
+ attr_reader :updated_resources
171
+
172
+ # @return [Boolean] If the resource_collection is in unified_mode (no separate converge phase)
167
173
  #
174
+ def_delegator :resource_collection, :unified_mode
175
+
168
176
  # A child of the root Chef::Log logging object.
169
177
  #
170
178
  # @return Mixlib::Log::Child A child logger
@@ -180,17 +188,16 @@ class Chef
180
188
  # @param events [EventDispatch::Dispatcher] The event dispatcher for this
181
189
  # run.
182
190
  #
183
- def initialize(node = nil, cookbook_collection = {}, events = nil, logger = nil)
191
+ def initialize(node = nil, cookbook_collection = nil, events = nil, logger = nil)
184
192
  @events = events
185
193
  @logger = logger || Chef::Log.with_child
186
- @cookbook_collection = cookbook_collection
187
194
  self.node = node if node
195
+ self.cookbook_collection = cookbook_collection if cookbook_collection
188
196
  @definitions = {}
189
197
  @loaded_recipes_hash = {}
190
198
  @loaded_attributes_hash = {}
191
199
  @reboot_info = {}
192
200
  @cookbook_compiler = nil
193
- @delayed_actions = []
194
201
 
195
202
  initialize_child_state
196
203
  end
@@ -198,6 +205,10 @@ class Chef
198
205
  def node=(node)
199
206
  @node = node
200
207
  node.run_context = self
208
+ end
209
+
210
+ def cookbook_collection=(cookbook_collection)
211
+ @cookbook_collection = cookbook_collection
201
212
  node.set_cookbook_attribute
202
213
  end
203
214
 
@@ -221,6 +232,7 @@ class Chef
221
232
  @immediate_notification_collection = Hash.new { |h, k| h[k] = [] }
222
233
  @delayed_notification_collection = Hash.new { |h, k| h[k] = [] }
223
234
  @delayed_actions = []
235
+ @updated_resources = Set.new
224
236
  end
225
237
 
226
238
  #
@@ -232,6 +244,10 @@ class Chef
232
244
  # Note for the future, notification.notifying_resource may be an instance
233
245
  # of Chef::Resource::UnresolvedSubscribes when calling {Resource#subscribes}
234
246
  # with a string value.
247
+ if unified_mode && updated_resources.include?(notification.notifying_resource.declared_key)
248
+ raise Chef::Exceptions::UnifiedModeBeforeSubscriptionEarlierResource.new(notification)
249
+ end
250
+
235
251
  before_notification_collection[notification.notifying_resource.declared_key] << notification
236
252
  end
237
253
 
@@ -256,11 +272,13 @@ class Chef
256
272
  # Note for the future, notification.notifying_resource may be an instance
257
273
  # of Chef::Resource::UnresolvedSubscribes when calling {Resource#subscribes}
258
274
  # with a string value.
275
+ if unified_mode && updated_resources.include?(notification.notifying_resource.declared_key)
276
+ add_delayed_action(notification)
277
+ end
259
278
  delayed_notification_collection[notification.notifying_resource.declared_key] << notification
260
279
  end
261
280
 
262
- #
263
- # Adds a delayed action to the +delayed_actions+.
281
+ # Adds a delayed action to the delayed_actions collection
264
282
  #
265
283
  def add_delayed_action(notification)
266
284
  if delayed_actions.any? { |existing_notification| existing_notification.duplicates?(notification) }
@@ -271,32 +289,45 @@ class Chef
271
289
  end
272
290
  end
273
291
 
274
- #
275
292
  # Get the list of before notifications sent by the given resource.
276
293
  #
277
294
  # @return [Array[Notification]]
278
295
  #
279
296
  def before_notifications(resource)
280
- before_notification_collection[resource.declared_key]
297
+ key = resource.is_a?(String) ? resource : resource.declared_key
298
+ before_notification_collection[key]
281
299
  end
282
300
 
283
- #
284
301
  # Get the list of immediate notifications sent by the given resource.
285
302
  #
286
303
  # @return [Array[Notification]]
287
304
  #
288
305
  def immediate_notifications(resource)
289
- immediate_notification_collection[resource.declared_key]
306
+ key = resource.is_a?(String) ? resource : resource.declared_key
307
+ immediate_notification_collection[key]
290
308
  end
291
309
 
310
+ # Get the list of immeidate notifications pending to the given resource
292
311
  #
312
+ # @return [Array[Notification]]
313
+ #
314
+ def reverse_immediate_notifications(resource)
315
+ immediate_notification_collection.map do |k, v|
316
+ v.select do |n|
317
+ (n.resource.is_a?(String) && n.resource == resource.declared_key) ||
318
+ n.resource == resource
319
+ end
320
+ end.flatten
321
+ end
322
+
293
323
  # Get the list of delayed (end of run) notifications sent by the given
294
324
  # resource.
295
325
  #
296
326
  # @return [Array[Notification]]
297
327
  #
298
328
  def delayed_notifications(resource)
299
- delayed_notification_collection[resource.declared_key]
329
+ key = resource.is_a?(String) ? resource : resource.declared_key
330
+ delayed_notification_collection[key]
300
331
  end
301
332
 
302
333
  #
@@ -666,9 +697,9 @@ class Chef
666
697
  rest=
667
698
  rest_clean
668
699
  rest_clean=
669
- unreachable_cookbook?
670
700
  transport
671
701
  transport_connection
702
+ unreachable_cookbook?
672
703
  }
673
704
 
674
705
  def initialize(parent_run_context)
@@ -681,8 +712,10 @@ class Chef
681
712
  end
682
713
 
683
714
  CHILD_STATE = %w{
684
- create_child
685
715
  add_delayed_action
716
+ before_notification_collection
717
+ before_notifications
718
+ create_child
686
719
  delayed_actions
687
720
  delayed_notification_collection
688
721
  delayed_notification_collection=
@@ -690,21 +723,22 @@ class Chef
690
723
  immediate_notification_collection
691
724
  immediate_notification_collection=
692
725
  immediate_notifications
693
- before_notification_collection
694
- before_notifications
695
726
  include_recipe
696
727
  initialize_child_state
697
728
  load_recipe
698
729
  load_recipe_file
699
730
  notifies_before
700
- notifies_immediately
701
731
  notifies_delayed
732
+ notifies_immediately
702
733
  parent_run_context
703
- root_run_context
704
734
  resource_collection
705
735
  resource_collection=
736
+ reverse_immediate_notifications
737
+ root_run_context
706
738
  runner
707
739
  runner=
740
+ unified_mode
741
+ updated_resources
708
742
  }.map(&:to_sym)
709
743
 
710
744
  # Verify that we didn't miss any methods
@@ -34,7 +34,7 @@ class Chef
34
34
 
35
35
  def initialize(run_context)
36
36
  @run_context = run_context
37
- run_context.runner = self
37
+ @run_context.runner = self
38
38
  end
39
39
 
40
40
  def delayed_actions
@@ -45,6 +45,10 @@ class Chef
45
45
  @run_context.events
46
46
  end
47
47
 
48
+ def updated_resources
49
+ @run_context.updated_resources
50
+ end
51
+
48
52
  # Determine the appropriate provider for the given resource, then
49
53
  # execute it.
50
54
  def run_action(resource, action, notification_type = nil, notifying_resource = nil)
@@ -73,33 +77,66 @@ class Chef
73
77
  # associated with the resource, but only if it was updated *this time*
74
78
  # we ran an action on it.
75
79
  if resource.updated_by_last_action?
80
+ updated_resources.add(resource.declared_key) # track updated resources for unified_mode
76
81
  run_context.immediate_notifications(resource).each do |notification|
77
- Chef::Log.info("#{resource} sending #{notification.action} action to #{notification.resource} (immediate)")
78
- run_action(notification.resource, notification.action, :immediate, resource)
82
+ if notification.resource.is_a?(String) && run_context.unified_mode
83
+ Chef::Log.debug("immediate notification from #{resource} to #{notification.resource} is delayed until declaration due to unified_mode")
84
+ else
85
+ Chef::Log.info("#{resource} sending #{notification.action} action to #{notification.resource} (immediate)")
86
+ run_action(notification.resource, notification.action, :immediate, resource)
87
+ end
79
88
  end
80
89
 
81
90
  run_context.delayed_notifications(resource).each do |notification|
82
- # send the notification to the run_context of the receiving resource
83
- notification.resource.run_context.add_delayed_action(notification)
91
+ if notification.resource.is_a?(String)
92
+ # for string resources that have not be declared yet in unified mode we only support notifying the current run_context
93
+ run_context.add_delayed_action(notification)
94
+ else
95
+ # send the notification to the run_context of the receiving resource
96
+ notification.resource.run_context.add_delayed_action(notification)
97
+ end
98
+ end
99
+ end
100
+ end
101
+
102
+ # Runs all of the actions on a given resource. This fires notifications and marks
103
+ # the resource as having been executed by the runner.
104
+ #
105
+ # @param resource [Chef::Resource] the resource to run
106
+ #
107
+ def run_all_actions(resource)
108
+ Array(resource.action).each { |action| run_action(resource, action) }
109
+ if run_context.unified_mode
110
+ run_context.reverse_immediate_notifications(resource).each do |n|
111
+ if updated_resources.include?(n.notifying_resource.declared_key)
112
+ n.resolve_resource_reference(run_context.resource_collection)
113
+ Chef::Log.info("#{resource} sent #{n.action} action to #{n.resource} (immediate at declaration time)")
114
+ run_action(n.resource, n.action, :immediate, n.notifying_resource)
115
+ end
84
116
  end
85
117
  end
118
+ ensure
119
+ resource.executed_by_runner = true
86
120
  end
87
121
 
88
- # Iterates over the +resource_collection+ in the +run_context+ calling
89
- # +run_action+ for each resource in turn.
122
+ # Iterates over the resource_collection in the run_context calling
123
+ # run_action for each resource in turn.
124
+ #
90
125
  def converge
91
126
  # Resolve all lazy/forward references in notifications
92
127
  run_context.resource_collection.each(&:resolve_notification_references)
93
128
 
94
129
  # Execute each resource.
95
130
  run_context.resource_collection.execute_each_resource do |resource|
96
- begin
97
- Array(resource.action).each { |action| run_action(resource, action) }
98
- ensure
99
- resource.executed_by_runner = true
131
+ unless run_context.resource_collection.unified_mode
132
+ run_all_actions(resource)
100
133
  end
101
134
  end
102
135
 
136
+ if run_context.resource_collection.unified_mode
137
+ run_context.resource_collection.each { |r| r.resolve_notification_references(true) }
138
+ end
139
+
103
140
  rescue Exception => e
104
141
  Chef::Log.info "Running queued delayed notifications before re-raising exception"
105
142
  run_delayed_notifications(e)
@@ -126,7 +163,8 @@ class Chef
126
163
  def run_delayed_notification(notification)
127
164
  Chef::Log.info( "#{notification.notifying_resource} sending #{notification.action}"\
128
165
  " action to #{notification.resource} (delayed)")
129
- # Struct of resource/action to call
166
+ # notifications may have lazy strings in them to resolve
167
+ notification.resolve_resource_reference(run_context.resource_collection)
130
168
  run_action(notification.resource, notification.action, :delayed)
131
169
  true
132
170
  rescue Exception => e
@@ -23,7 +23,7 @@ require_relative "version_string"
23
23
 
24
24
  class Chef
25
25
  CHEF_ROOT = File.expand_path("../..", __FILE__)
26
- VERSION = Chef::VersionString.new("15.2.20")
26
+ VERSION = Chef::VersionString.new("15.3.14")
27
27
  end
28
28
 
29
29
  #
@@ -1,6 +1,6 @@
1
1
  #
2
2
  # Author:: Matt Wrock (<matt@mattwrock.com>)
3
- # Copyright:: Copyright (c) 2016 Chef Software, Inc.
3
+ # Copyright:: Copyright (c) 2016-2019, Chef Software Inc.
4
4
  # License:: Apache License, Version 2.0
5
5
  #
6
6
  # Licensed under the Apache License, Version 2.0 (the "License");
@@ -75,6 +75,24 @@ describe Chef::Resource::ChocolateyPackage, :windows_only, :choco_installed do
75
75
  subject.package_name "blah"
76
76
  expect { subject.run_action(:install) }.to raise_error Chef::Exceptions::Package
77
77
  end
78
+
79
+ it "installs with an option as a string" do
80
+ subject.options "--force --confirm"
81
+ subject.run_action(:install)
82
+ expect(package_list.call).to eq("#{package_name}|2.0")
83
+ end
84
+
85
+ it "installs with multiple options as a string" do
86
+ subject.options "--force --confirm"
87
+ subject.run_action(:install)
88
+ expect(package_list.call).to eq("#{package_name}|2.0")
89
+ end
90
+
91
+ it "installs with multiple options as an array" do
92
+ subject.options [ "--force", "--confirm" ]
93
+ subject.run_action(:install)
94
+ expect(package_list.call).to eq("#{package_name}|2.0")
95
+ end
78
96
  end
79
97
 
80
98
  context "upgrading a package" do