chef 12.15.19 → 12.16.42
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile +0 -1
- data/VERSION +1 -1
- data/acceptance/.shared/kitchen_acceptance/.kitchen.ec2.yml +3 -1
- data/acceptance/Gemfile.lock +14 -14
- data/acceptance/data-collector/test/integration/default/serverspec/default_spec.rb +3 -11
- data/distro/common/html/knife_bootstrap.html +1 -1
- data/distro/common/man/man1/README.md +2 -2
- data/distro/common/man/man1/knife-client.1 +1 -1
- data/lib/chef/application.rb +7 -15
- data/lib/chef/application/client.rb +2 -2
- data/lib/chef/application/solo.rb +1 -1
- data/lib/chef/chef_class.rb +1 -0
- data/lib/chef/chef_fs/file_system/chef_server/cookbook_file.rb +3 -7
- data/lib/chef/chef_fs/file_system/chef_server/versioned_cookbook_dir.rb +1 -1
- data/lib/chef/data_collector.rb +83 -9
- data/lib/chef/data_collector/messages.rb +2 -1
- data/lib/chef/dsl/core.rb +1 -1
- data/lib/chef/dsl/declare_resource.rb +10 -4
- data/lib/chef/dsl/method_missing.rb +1 -1
- data/lib/chef/dsl/recipe.rb +1 -1
- data/lib/chef/dsl/universal.rb +1 -1
- data/lib/chef/event_dispatch/base.rb +3 -0
- data/lib/chef/http.rb +3 -4
- data/lib/chef/knife.rb +20 -2
- data/lib/chef/knife/core/generic_presenter.rb +18 -4
- data/lib/chef/knife/node_show.rb +0 -5
- data/lib/chef/knife/osc_user_show.rb +0 -1
- data/lib/chef/knife/ssl_fetch.rb +9 -5
- data/lib/chef/mixin/powershell_out.rb +1 -1
- data/lib/chef/mixin/shell_out.rb +1 -1
- data/lib/chef/node.rb +1 -5
- data/lib/chef/node/attribute.rb +70 -98
- data/lib/chef/node/attribute_collections.rb +28 -19
- data/lib/chef/node/common_api.rb +0 -6
- data/lib/chef/node/immutable_collections.rb +16 -79
- data/lib/chef/node/mixin/deep_merge_cache.rb +61 -0
- data/lib/chef/node/mixin/immutablize_array.rb +67 -0
- data/lib/chef/node/mixin/immutablize_hash.rb +54 -0
- data/lib/chef/node/mixin/state_tracking.rb +93 -0
- data/lib/chef/property.rb +4 -4
- data/lib/chef/provider/cron.rb +1 -1
- data/lib/chef/provider/group/suse.rb +23 -4
- data/lib/chef/provider/package.rb +43 -5
- data/lib/chef/provider/package/apt.rb +20 -0
- data/lib/chef/provider/package/windows/exe.rb +4 -3
- data/lib/chef/provider/package/windows/msi.rb +4 -3
- data/lib/chef/provider/package/yum.rb +20 -0
- data/lib/chef/provider/package/zypper.rb +20 -0
- data/lib/chef/provider/ruby_block.rb +1 -1
- data/lib/chef/provider/service/upstart.rb +25 -9
- data/lib/chef/provider/user.rb +4 -6
- data/lib/chef/provider/user/dscl.rb +8 -3
- data/lib/chef/provider/user/solaris.rb +5 -12
- data/lib/chef/resource.rb +19 -0
- data/lib/chef/resource/file.rb +1 -1
- data/lib/chef/resource/package.rb +1 -1
- data/lib/chef/resource/scm.rb +1 -7
- data/lib/chef/resource/yum_repository.rb +1 -1
- data/lib/chef/rest.rb +1 -0
- data/lib/chef/run_context.rb +12 -0
- data/lib/chef/version.rb +1 -1
- data/spec/data/trusted_certs/example_no_cn.crt +36 -0
- data/spec/functional/resource/group_spec.rb +1 -0
- data/spec/functional/resource/user/useradd_spec.rb +4 -2
- data/spec/integration/knife/data_bag_create_spec.rb +0 -3
- data/spec/integration/knife/environment_show_spec.rb +24 -4
- data/spec/integration/knife/node_environment_set_spec.rb +4 -1
- data/spec/integration/recipes/accumulator_spec.rb +232 -0
- data/spec/integration/recipes/resource_action_spec.rb +1 -1
- data/spec/spec_helper.rb +2 -2
- data/spec/support/shared/context/client.rb +12 -3
- data/spec/support/shared/integration/app_server_support.rb +1 -1
- data/spec/support/shared/integration/knife_support.rb +4 -1
- data/spec/unit/data_collector/messages_spec.rb +2 -0
- data/spec/unit/data_collector_spec.rb +158 -21
- data/spec/unit/http_spec.rb +1 -1
- data/spec/unit/knife/core/gem_glob_loader_spec.rb +1 -1
- data/spec/unit/knife/core/ui_spec.rb +10 -0
- data/spec/unit/knife/ssl_fetch_spec.rb +38 -0
- data/spec/unit/knife_spec.rb +31 -0
- data/spec/unit/mixin/powershell_out_spec.rb +25 -1
- data/spec/unit/node/attribute_spec.rb +46 -1
- data/spec/unit/node/vivid_mash_spec.rb +27 -89
- data/spec/unit/node_spec.rb +134 -3
- data/spec/unit/provider/deploy_spec.rb +1 -1
- data/spec/unit/provider/group/suse_spec.rb +90 -0
- data/spec/unit/provider/package/apt_spec.rb +22 -0
- data/spec/unit/provider/package/windows/msi_spec.rb +13 -4
- data/spec/unit/provider/package/windows_spec.rb +3 -3
- data/spec/unit/provider/package/yum_spec.rb +18 -0
- data/spec/unit/provider/package/zypper_spec.rb +64 -0
- data/spec/unit/provider/package_spec.rb +58 -0
- data/spec/unit/provider/remote_file/content_spec.rb +1 -1
- data/spec/unit/provider/service/upstart_service_spec.rb +13 -6
- data/spec/unit/provider/user/solaris_spec.rb +36 -9
- data/spec/unit/provider/user_spec.rb +6 -0
- data/spec/unit/resource/apt_repository_spec.rb +1 -1
- metadata +12 -5
@@ -0,0 +1,54 @@
|
|
1
|
+
#--
|
2
|
+
# Copyright:: Copyright 2016, Chef Software, Inc.
|
3
|
+
# License:: Apache License, Version 2.0
|
4
|
+
#
|
5
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
6
|
+
# you may not use this file except in compliance with the License.
|
7
|
+
# You may obtain a copy of the License at
|
8
|
+
#
|
9
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
10
|
+
#
|
11
|
+
# Unless required by applicable law or agreed to in writing, software
|
12
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
13
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
14
|
+
# See the License for the specific language governing permissions and
|
15
|
+
# limitations under the License.
|
16
|
+
#
|
17
|
+
|
18
|
+
class Chef
|
19
|
+
class Node
|
20
|
+
module Mixin
|
21
|
+
module ImmutablizeHash
|
22
|
+
DISALLOWED_MUTATOR_METHODS = [
|
23
|
+
:[]=,
|
24
|
+
:clear,
|
25
|
+
:collect!,
|
26
|
+
:default=,
|
27
|
+
:default_proc=,
|
28
|
+
:delete,
|
29
|
+
:delete_if,
|
30
|
+
:keep_if,
|
31
|
+
:map!,
|
32
|
+
:merge!,
|
33
|
+
:update,
|
34
|
+
:reject!,
|
35
|
+
:replace,
|
36
|
+
:select!,
|
37
|
+
:shift,
|
38
|
+
:write,
|
39
|
+
:write!,
|
40
|
+
:unlink,
|
41
|
+
:unlink!,
|
42
|
+
]
|
43
|
+
|
44
|
+
# Redefine all of the methods that mutate a Hash to raise an error when called.
|
45
|
+
# This is the magic that makes this object "Immutable"
|
46
|
+
DISALLOWED_MUTATOR_METHODS.each do |mutator_method_name|
|
47
|
+
define_method(mutator_method_name) do |*args, &block|
|
48
|
+
raise Exceptions::ImmutableAttributeModification
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
@@ -0,0 +1,93 @@
|
|
1
|
+
#--
|
2
|
+
# Copyright:: Copyright 2016, Chef Software, Inc.
|
3
|
+
# License:: Apache License, Version 2.0
|
4
|
+
#
|
5
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
6
|
+
# you may not use this file except in compliance with the License.
|
7
|
+
# You may obtain a copy of the License at
|
8
|
+
#
|
9
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
10
|
+
#
|
11
|
+
# Unless required by applicable law or agreed to in writing, software
|
12
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
13
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
14
|
+
# See the License for the specific language governing permissions and
|
15
|
+
# limitations under the License.
|
16
|
+
#
|
17
|
+
|
18
|
+
class Chef
|
19
|
+
class Node
|
20
|
+
module Mixin
|
21
|
+
module StateTracking
|
22
|
+
attr_reader :__path__
|
23
|
+
attr_reader :__root__
|
24
|
+
attr_reader :__node__
|
25
|
+
attr_reader :__precedence__
|
26
|
+
|
27
|
+
def initialize(data = nil, root = self, node = nil, precedence = nil)
|
28
|
+
# __path__ and __root__ must be nil when we call super so it knows
|
29
|
+
# to avoid resetting the cache on construction
|
30
|
+
data.nil? ? super() : super(data)
|
31
|
+
@__path__ = []
|
32
|
+
@__root__ = root
|
33
|
+
@__node__ = node
|
34
|
+
@__precedence__ = precedence
|
35
|
+
end
|
36
|
+
|
37
|
+
def [](key)
|
38
|
+
ret = super
|
39
|
+
next_path = [ __path__, convert_key(key) ].flatten.compact
|
40
|
+
copy_state_to(ret, next_path)
|
41
|
+
end
|
42
|
+
|
43
|
+
def []=(key, value)
|
44
|
+
ret = super
|
45
|
+
next_path = [ __path__, convert_key(key) ].flatten.compact
|
46
|
+
send_attribute_changed_event(next_path, value)
|
47
|
+
copy_state_to(ret, next_path)
|
48
|
+
end
|
49
|
+
|
50
|
+
protected
|
51
|
+
|
52
|
+
def __path__=(path)
|
53
|
+
@__path__ = path
|
54
|
+
end
|
55
|
+
|
56
|
+
def __root__=(root)
|
57
|
+
@__root__ = root
|
58
|
+
end
|
59
|
+
|
60
|
+
def __precedence__=(precedence)
|
61
|
+
@__precedence__ = precedence
|
62
|
+
end
|
63
|
+
|
64
|
+
def __node__=(node)
|
65
|
+
@__node__ = node
|
66
|
+
end
|
67
|
+
|
68
|
+
private
|
69
|
+
|
70
|
+
def send_attribute_changed_event(next_path, value)
|
71
|
+
if __node__ && __node__.run_context && __node__.run_context.events
|
72
|
+
__node__.run_context.events.attribute_changed(__precedence__, next_path, value)
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
def send_reset_cache(path = nil, key = nil)
|
77
|
+
next_path = [ path, key ].flatten.compact
|
78
|
+
__root__.reset_cache(next_path.first) if !__root__.nil? && __root__.respond_to?(:reset_cache) && !next_path.nil?
|
79
|
+
end
|
80
|
+
|
81
|
+
def copy_state_to(ret, next_path)
|
82
|
+
if ret.is_a?(StateTracking)
|
83
|
+
ret.__path__ = next_path
|
84
|
+
ret.__root__ = __root__
|
85
|
+
ret.__node__ = __node__
|
86
|
+
ret.__precedence__ = __precedence__
|
87
|
+
end
|
88
|
+
ret
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
data/lib/chef/property.rb
CHANGED
@@ -522,22 +522,22 @@ class Chef
|
|
522
522
|
# stack trace if you use `define_method`.
|
523
523
|
declared_in.class_eval <<-EOM, __FILE__, __LINE__ + 1
|
524
524
|
def #{name}(value=NOT_PASSED)
|
525
|
-
raise "Property
|
525
|
+
raise "Property `#{name}` of `\#{self}` was incorrectly passed a block. Possible property-resource collision. To call a resource named `#{name}` either rename the property or else use `declare_resource(:#{name}, ...)`" if block_given?
|
526
526
|
self.class.properties[#{name.inspect}].call(self, value)
|
527
527
|
end
|
528
528
|
def #{name}=(value)
|
529
|
-
raise "Property
|
529
|
+
raise "Property `#{name}` of `\#{self}` was incorrectly passed a block. Possible property-resource collision. To call a resource named `#{name}` either rename the property or else use `declare_resource(:#{name}, ...)`" if block_given?
|
530
530
|
self.class.properties[#{name.inspect}].set(self, value)
|
531
531
|
end
|
532
532
|
EOM
|
533
533
|
rescue SyntaxError
|
534
534
|
# If the name is not a valid ruby name, we use define_method.
|
535
535
|
declared_in.define_method(name) do |value = NOT_PASSED, &block|
|
536
|
-
raise "Property
|
536
|
+
raise "Property `#{name}` of `#{self}` was incorrectly passed a block! Possible property-resource collision. To call a resource named `#{name}` either rename the property or else use `declare_resource(:#{name}, ...)`" if block
|
537
537
|
self.class.properties[name].call(self, value)
|
538
538
|
end
|
539
539
|
declared_in.define_method("#{name}=") do |value, &block|
|
540
|
-
raise "Property
|
540
|
+
raise "Property `#{name}` of `#{self}` was incorrectly passed a block! Possible property-resource collision. To call a resource named `#{name}` either rename the property or else use `declare_resource(:#{name}, ...)`" if block
|
541
541
|
self.class.properties[name].set(self, value)
|
542
542
|
end
|
543
543
|
end
|
data/lib/chef/provider/cron.rb
CHANGED
@@ -199,7 +199,7 @@ class Chef
|
|
199
199
|
|
200
200
|
def set_environment_var(attr_name, attr_value)
|
201
201
|
if %w{MAILTO PATH SHELL HOME}.include?(attr_name)
|
202
|
-
@current_resource.send(attr_name.downcase.to_sym, attr_value)
|
202
|
+
@current_resource.send(attr_name.downcase.to_sym, attr_value.gsub(/^"|"$/, ""))
|
203
203
|
else
|
204
204
|
@current_resource.environment(@current_resource.environment.merge(attr_name => attr_value))
|
205
205
|
end
|
@@ -17,6 +17,7 @@
|
|
17
17
|
#
|
18
18
|
|
19
19
|
require "chef/provider/group/groupadd"
|
20
|
+
require "etc"
|
20
21
|
|
21
22
|
class Chef
|
22
23
|
class Provider
|
@@ -36,24 +37,42 @@ class Chef
|
|
36
37
|
a.failure_message Chef::Exceptions::Group, "Could not find binary /usr/sbin/groupmod for #{@new_resource.name}"
|
37
38
|
# No whyrun alternative: this component should be available in the base install of any given system that uses it
|
38
39
|
end
|
40
|
+
|
41
|
+
requirements.assert(:create, :manage, :modify) do |a|
|
42
|
+
a.assertion do
|
43
|
+
begin
|
44
|
+
to_add(@new_resource.members).all? { |member| Etc.getpwnam(member) }
|
45
|
+
rescue
|
46
|
+
false
|
47
|
+
end
|
48
|
+
end
|
49
|
+
a.failure_message Chef::Exceptions::Group, "Could not add users #{to_add(@new_resource.members).join(", ")} to #{@new_resource.group_name}: one of these users does not exist"
|
50
|
+
a.whyrun "Could not find one of these users: #{to_add(@new_resource.members).join(", ")}. Assuming it will be created by a prior step"
|
51
|
+
end
|
39
52
|
end
|
40
53
|
|
41
54
|
def set_members(members)
|
42
|
-
|
43
|
-
to_delete.each do |member|
|
55
|
+
to_remove(members).each do |member|
|
44
56
|
remove_member(member)
|
45
57
|
end
|
46
58
|
|
47
|
-
to_add
|
48
|
-
to_add.each do |member|
|
59
|
+
to_add(members).each do |member|
|
49
60
|
add_member(member)
|
50
61
|
end
|
51
62
|
end
|
52
63
|
|
64
|
+
def to_add(members)
|
65
|
+
members - @current_resource.members
|
66
|
+
end
|
67
|
+
|
53
68
|
def add_member(member)
|
54
69
|
shell_out!("groupmod -A #{member} #{@new_resource.group_name}")
|
55
70
|
end
|
56
71
|
|
72
|
+
def to_remove(members)
|
73
|
+
@current_resource.members - members
|
74
|
+
end
|
75
|
+
|
57
76
|
def remove_member(member)
|
58
77
|
shell_out!("groupmod -R #{member} #{@new_resource.group_name}")
|
59
78
|
end
|
@@ -31,6 +31,8 @@ class Chef
|
|
31
31
|
include Chef::Mixin::ShellOut
|
32
32
|
extend Chef::Mixin::SubclassDirective
|
33
33
|
|
34
|
+
use_inline_resources
|
35
|
+
|
34
36
|
# subclasses declare this if they want all their arguments as arrays of packages and names
|
35
37
|
subclass_directive :use_multipackage_api
|
36
38
|
# subclasses declare this if they want sources (filenames) pulled from their package names
|
@@ -81,7 +83,7 @@ class Chef
|
|
81
83
|
end
|
82
84
|
end
|
83
85
|
|
84
|
-
|
86
|
+
action :install do
|
85
87
|
unless target_version_array.any?
|
86
88
|
Chef::Log.debug("#{@new_resource} is already installed - nothing to do")
|
87
89
|
return
|
@@ -116,7 +118,7 @@ class Chef
|
|
116
118
|
|
117
119
|
private :install_description
|
118
120
|
|
119
|
-
|
121
|
+
action :upgrade do
|
120
122
|
if !target_version_array.any?
|
121
123
|
Chef::Log.debug("#{@new_resource} no versions to upgrade - nothing to do")
|
122
124
|
return
|
@@ -146,7 +148,7 @@ class Chef
|
|
146
148
|
|
147
149
|
private :upgrade_description
|
148
150
|
|
149
|
-
|
151
|
+
action :remove do
|
150
152
|
if removing_package?
|
151
153
|
description = @new_resource.version ? "version #{@new_resource.version} of " : ""
|
152
154
|
converge_by("remove #{description}package #{@current_resource.package_name}") do
|
@@ -181,7 +183,7 @@ class Chef
|
|
181
183
|
end
|
182
184
|
end
|
183
185
|
|
184
|
-
|
186
|
+
action :purge do
|
185
187
|
if removing_package?
|
186
188
|
description = @new_resource.version ? "version #{@new_resource.version} of" : ""
|
187
189
|
converge_by("purge #{description} package #{@current_resource.package_name}") do
|
@@ -193,7 +195,7 @@ class Chef
|
|
193
195
|
end
|
194
196
|
end
|
195
197
|
|
196
|
-
|
198
|
+
action :reconfig do
|
197
199
|
if @current_resource.version == nil
|
198
200
|
Chef::Log.debug("#{@new_resource} is NOT installed - nothing to do")
|
199
201
|
return
|
@@ -218,6 +220,34 @@ class Chef
|
|
218
220
|
end
|
219
221
|
end
|
220
222
|
|
223
|
+
def action_lock
|
224
|
+
if package_locked(@new_resource.name, @new_resource.version) == false
|
225
|
+
description = @new_resource.version ? "version #{@new_resource.version} of " : ""
|
226
|
+
converge_by("lock #{description}package #{@current_resource.package_name}") do
|
227
|
+
multipackage_api_adapter(@current_resource.package_name, @new_resource.version) do |name, version|
|
228
|
+
lock_package(name, version)
|
229
|
+
Chef::Log.info("#{@new_resource} locked")
|
230
|
+
end
|
231
|
+
end
|
232
|
+
else
|
233
|
+
Chef::Log.debug("#{new_resource} is already locked")
|
234
|
+
end
|
235
|
+
end
|
236
|
+
|
237
|
+
def action_unlock
|
238
|
+
if package_locked(@new_resource.name, @new_resource.version) == true
|
239
|
+
description = @new_resource.version ? "version #{@new_resource.version} of " : ""
|
240
|
+
converge_by("unlock #{description}package #{@current_resource.package_name}") do
|
241
|
+
multipackage_api_adapter(@current_resource.package_name, @new_resource.version) do |name, version|
|
242
|
+
unlock_package(name, version)
|
243
|
+
Chef::Log.info("#{@new_resource} unlocked")
|
244
|
+
end
|
245
|
+
end
|
246
|
+
else
|
247
|
+
Chef::Log.debug("#{new_resource} is already unlocked")
|
248
|
+
end
|
249
|
+
end
|
250
|
+
|
221
251
|
# @todo use composition rather than inheritance
|
222
252
|
|
223
253
|
def multipackage_api_adapter(name, version)
|
@@ -252,6 +282,14 @@ class Chef
|
|
252
282
|
raise( Chef::Exceptions::UnsupportedAction, "#{self} does not support :reconfig" )
|
253
283
|
end
|
254
284
|
|
285
|
+
def lock_package(name, version)
|
286
|
+
raise( Chef::Exceptions::UnsupportedAction, "#{self} does not support :lock" )
|
287
|
+
end
|
288
|
+
|
289
|
+
def unlock_package(name, version)
|
290
|
+
raise( Chef::Exceptions::UnsupportedAction, "#{self} does not support :unlock" )
|
291
|
+
end
|
292
|
+
|
255
293
|
# used by subclasses. deprecated. use #a_to_s instead.
|
256
294
|
def expand_options(options)
|
257
295
|
options ? " #{options}" : ""
|
@@ -70,6 +70,18 @@ class Chef
|
|
70
70
|
@candidate_version ||= get_candidate_versions
|
71
71
|
end
|
72
72
|
|
73
|
+
def package_locked(name, version)
|
74
|
+
islocked = false
|
75
|
+
locked = shell_out_with_timeout!("apt-mark showhold")
|
76
|
+
locked.stdout.each_line do |line|
|
77
|
+
line_package = line.strip
|
78
|
+
if line_package == name
|
79
|
+
islocked = true
|
80
|
+
end
|
81
|
+
end
|
82
|
+
return islocked
|
83
|
+
end
|
84
|
+
|
73
85
|
def install_package(name, version)
|
74
86
|
package_name = name.zip(version).map do |n, v|
|
75
87
|
package_data[n][:virtual] ? n : "#{n}=#{v}"
|
@@ -105,6 +117,14 @@ class Chef
|
|
105
117
|
run_noninteractive("dpkg-reconfigure", name)
|
106
118
|
end
|
107
119
|
|
120
|
+
def lock_package(name, version)
|
121
|
+
run_noninteractive("apt-mark", new_resource.options, "hold", name)
|
122
|
+
end
|
123
|
+
|
124
|
+
def unlock_package(name, version)
|
125
|
+
run_noninteractive("apt-mark", new_resource.options, "unhold", name)
|
126
|
+
end
|
127
|
+
|
108
128
|
private
|
109
129
|
|
110
130
|
# Runs command via shell_out with magic environment to disable
|
@@ -89,9 +89,10 @@ class Chef
|
|
89
89
|
end
|
90
90
|
|
91
91
|
def current_installed_version
|
92
|
-
@current_installed_version ||=
|
93
|
-
uninstall_entries.
|
94
|
-
|
92
|
+
@current_installed_version ||=
|
93
|
+
if uninstall_entries.count != 0
|
94
|
+
uninstall_entries.map { |entry| entry.display_version }.uniq
|
95
|
+
end
|
95
96
|
end
|
96
97
|
|
97
98
|
# http://unattended.sourceforge.net/installers.php
|
@@ -50,7 +50,7 @@ class Chef
|
|
50
50
|
Chef::Log.debug("#{new_resource} checking package status and version for #{product_code}")
|
51
51
|
get_installed_version(product_code)
|
52
52
|
else
|
53
|
-
uninstall_entries.count
|
53
|
+
if uninstall_entries.count != 0
|
54
54
|
uninstall_entries.map { |entry| entry.display_version }.uniq
|
55
55
|
end
|
56
56
|
end
|
@@ -79,9 +79,10 @@ class Chef
|
|
79
79
|
uninstall_version = new_resource.version || installed_version
|
80
80
|
uninstall_entries.select { |entry| [uninstall_version].flatten.include?(entry.display_version) }
|
81
81
|
.map { |version| version.uninstall_string }.uniq.each do |uninstall_string|
|
82
|
-
|
82
|
+
uninstall_string = "msiexec /x #{uninstall_string.match(/{.*}/)}"
|
83
83
|
uninstall_string += expand_options(new_resource.options)
|
84
|
-
uninstall_string += " /
|
84
|
+
uninstall_string += " /q" unless uninstall_string.downcase =~ / \/q/
|
85
|
+
Chef::Log.debug("#{new_resource} removing MSI package version using '#{uninstall_string}'")
|
85
86
|
shell_out!(uninstall_string, { :timeout => new_resource.timeout, :returns => new_resource.returns })
|
86
87
|
end
|
87
88
|
end
|
@@ -123,6 +123,18 @@ class Chef
|
|
123
123
|
end
|
124
124
|
end
|
125
125
|
|
126
|
+
def package_locked(name, version)
|
127
|
+
islocked = false
|
128
|
+
locked = shell_out_with_timeout!("yum versionlock")
|
129
|
+
locked.stdout.each_line do |line|
|
130
|
+
line_package = line.sub(/-[^-]*-[^-]*$/, "").split(":").last.strip
|
131
|
+
if line_package == name
|
132
|
+
islocked = true
|
133
|
+
end
|
134
|
+
end
|
135
|
+
return islocked
|
136
|
+
end
|
137
|
+
|
126
138
|
# Standard Provider methods for Parent
|
127
139
|
#
|
128
140
|
|
@@ -369,6 +381,14 @@ class Chef
|
|
369
381
|
remove_package(name, version)
|
370
382
|
end
|
371
383
|
|
384
|
+
def lock_package(name, version)
|
385
|
+
yum_command("-d0 -e0 -y#{expand_options(@new_resource.options)} versionlock add #{name}")
|
386
|
+
end
|
387
|
+
|
388
|
+
def unlock_package(name, version)
|
389
|
+
yum_command("-d0 -e0 -y#{expand_options(@new_resource.options)} versionlock delete #{name}")
|
390
|
+
end
|
391
|
+
|
372
392
|
private
|
373
393
|
|
374
394
|
def parse_arch(package_name)
|
@@ -75,6 +75,18 @@ class Chef
|
|
75
75
|
end
|
76
76
|
end
|
77
77
|
|
78
|
+
def package_locked(name, version)
|
79
|
+
islocked = false
|
80
|
+
locked = shell_out_with_timeout!("zypper locks")
|
81
|
+
locked.stdout.each_line do |line|
|
82
|
+
line_package = line.split("|").shift(2).last.strip
|
83
|
+
if line_package == name
|
84
|
+
islocked = true
|
85
|
+
end
|
86
|
+
end
|
87
|
+
return islocked
|
88
|
+
end
|
89
|
+
|
78
90
|
def load_current_resource
|
79
91
|
@current_resource = Chef::Resource::ZypperPackage.new(new_resource.name)
|
80
92
|
current_resource.package_name(new_resource.package_name)
|
@@ -107,6 +119,14 @@ class Chef
|
|
107
119
|
zypper_package("remove --clean-deps", name, version)
|
108
120
|
end
|
109
121
|
|
122
|
+
def lock_package(name, version)
|
123
|
+
zypper_package("addlock", name, version)
|
124
|
+
end
|
125
|
+
|
126
|
+
def unlock_package(name, version)
|
127
|
+
zypper_package("removelock", name, version)
|
128
|
+
end
|
129
|
+
|
110
130
|
private
|
111
131
|
|
112
132
|
def zip(names, versions)
|