chef 15.2.20-universal-mingw32 → 15.3.14-universal-mingw32
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +1 -2
- data/chef.gemspec +3 -2
- data/lib/chef/application.rb +1 -1
- data/lib/chef/application/base.rb +7 -0
- data/lib/chef/application/client.rb +6 -2
- data/lib/chef/application/solo.rb +7 -1
- data/lib/chef/cookbook/gem_installer.rb +7 -2
- data/lib/chef/exceptions.rb +12 -0
- data/lib/chef/knife/bootstrap.rb +8 -1
- data/lib/chef/knife/bootstrap/templates/chef-full.erb +1 -1
- data/lib/chef/knife/bootstrap/train_connector.rb +3 -3
- data/lib/chef/knife/cookbook_metadata_from_file.rb +1 -1
- data/lib/chef/node.rb +0 -2
- data/lib/chef/policy_builder/expand_node_object.rb +1 -1
- data/lib/chef/policy_builder/policyfile.rb +4 -3
- data/lib/chef/provider.rb +4 -2
- data/lib/chef/provider/ifconfig.rb +5 -3
- data/lib/chef/provider/package/chocolatey.rb +12 -22
- data/lib/chef/provider/user.rb +1 -1
- data/lib/chef/provider/user/dscl.rb +2 -2
- data/lib/chef/provider/user/mac.rb +628 -0
- data/lib/chef/providers.rb +1 -0
- data/lib/chef/resource.rb +28 -20
- data/lib/chef/resource/chocolatey_feature.rb +1 -1
- data/lib/chef/resource/chocolatey_package.rb +2 -2
- data/lib/chef/resource/cron_d.rb +1 -1
- data/lib/chef/resource/ohai.rb +1 -1
- data/lib/chef/resource/resource_notification.rb +17 -13
- data/lib/chef/resource/ruby_block.rb +1 -1
- data/lib/chef/resource/service.rb +1 -1
- data/lib/chef/resource/user.rb +1 -0
- data/lib/chef/resource/user/dscl_user.rb +1 -1
- data/lib/chef/resource/user/mac_user.rb +119 -0
- data/lib/chef/resource/windows_ad_join.rb +1 -1
- data/lib/chef/resource_collection.rb +6 -0
- data/lib/chef/resources.rb +1 -0
- data/lib/chef/run_context.rb +61 -27
- data/lib/chef/runner.rb +50 -12
- data/lib/chef/version.rb +1 -1
- data/spec/functional/resource/chocolatey_package_spec.rb +19 -1
- data/spec/functional/resource/user/mac_user_spec.rb +207 -0
- data/spec/integration/client/client_spec.rb +22 -0
- data/spec/integration/knife/raw_spec.rb +39 -19
- data/spec/integration/knife/redirection_spec.rb +22 -13
- data/spec/integration/knife/serve_spec.rb +1 -2
- data/spec/integration/recipes/unified_mode_spec.rb +876 -0
- data/spec/spec_helper.rb +1 -0
- data/spec/support/platform_helpers.rb +10 -0
- data/spec/support/shared/integration/integration_helper.rb +1 -2
- data/spec/unit/application/client_spec.rb +5 -6
- data/spec/unit/application/solo_spec.rb +3 -8
- data/spec/unit/application_spec.rb +1 -1
- data/spec/unit/cookbook/gem_installer_spec.rb +22 -1
- data/spec/unit/knife/bootstrap/train_connector_spec.rb +20 -7
- data/spec/unit/knife/bootstrap_spec.rb +13 -5
- data/spec/unit/provider/ifconfig_spec.rb +11 -0
- data/spec/unit/provider/package/chocolatey_spec.rb +34 -30
- data/spec/unit/provider/user/dscl_spec.rb +1 -0
- data/spec/unit/provider/user/mac_spec.rb +38 -0
- data/spec/unit/provider/user_spec.rb +38 -22
- data/tasks/docs.rb +14 -10
- metadata +25 -13
- data/spec/support/shared/integration/app_server_support.rb +0 -39
@@ -31,7 +31,7 @@ class Chef
|
|
31
31
|
introduced "14.0"
|
32
32
|
|
33
33
|
property :domain_name, String,
|
34
|
-
description: "
|
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)
|
data/lib/chef/resources.rb
CHANGED
@@ -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"
|
data/lib/chef/run_context.rb
CHANGED
@@ -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
|
-
|
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
|
-
|
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 =
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
data/lib/chef/runner.rb
CHANGED
@@ -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
|
-
|
78
|
-
|
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
|
-
|
83
|
-
|
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
|
89
|
-
#
|
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
|
-
|
97
|
-
|
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
|
-
#
|
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
|
data/lib/chef/version.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
#
|
2
2
|
# Author:: Matt Wrock (<matt@mattwrock.com>)
|
3
|
-
# Copyright:: Copyright (c) 2016 Chef Software
|
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
|