chef 12.5.1 → 12.6.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile +6 -1
- data/README.md +6 -4
- data/Rakefile +1 -4
- data/chef-windows.gemspec +21 -0
- data/chef.gemspec +58 -0
- data/lib/chef/api_client/registration.rb +9 -4
- data/lib/chef/application.rb +3 -84
- data/lib/chef/application/apply.rb +9 -2
- data/lib/chef/application/client.rb +8 -3
- data/lib/chef/application/solo.rb +7 -1
- data/lib/chef/application/windows_service.rb +21 -6
- data/lib/chef/application/windows_service_manager.rb +2 -3
- data/lib/chef/audit/runner.rb +1 -0
- data/lib/chef/chef_class.rb +1 -11
- data/lib/chef/chef_fs/chef_fs_data_store.rb +181 -2
- data/lib/chef/chef_fs/file_system/cookbook_subdir.rb +5 -0
- data/lib/chef/chef_fs/file_system/file_system_entry.rb +11 -7
- data/lib/chef/client.rb +28 -1
- data/lib/chef/cookbook/cookbook_collection.rb +14 -1
- data/lib/chef/cookbook/cookbook_version_loader.rb +1 -1
- data/lib/chef/cookbook/metadata.rb +115 -9
- data/lib/chef/cookbook/remote_file_vendor.rb +1 -1
- data/lib/chef/cookbook_version.rb +6 -2
- data/lib/chef/data_bag.rb +1 -1
- data/lib/chef/data_bag_item.rb +1 -1
- data/lib/chef/digester.rb +5 -1
- data/lib/chef/dsl/chef_provisioning.rb +57 -0
- data/lib/chef/dsl/cheffish.rb +64 -0
- data/lib/chef/dsl/declare_resource.rb +108 -0
- data/lib/chef/dsl/platform_introspection.rb +3 -3
- data/lib/chef/dsl/recipe.rb +3 -73
- data/lib/chef/dsl/resources.rb +27 -1
- data/lib/chef/event_dispatch/base.rb +3 -0
- data/lib/chef/event_dispatch/dispatcher.rb +5 -0
- data/lib/chef/event_dispatch/events_output_stream.rb +8 -0
- data/lib/chef/exceptions.rb +21 -1
- data/lib/chef/file_access_control/unix.rb +12 -12
- data/lib/chef/file_content_management/deploy/cp.rb +2 -2
- data/lib/chef/file_content_management/deploy/mv_unix.rb +4 -4
- data/lib/chef/file_content_management/deploy/mv_windows.rb +1 -1
- data/lib/chef/formatters/base.rb +7 -0
- data/lib/chef/formatters/error_inspectors/compile_error_inspector.rb +2 -2
- data/lib/chef/formatters/indentable_output_stream.rb +5 -0
- data/lib/chef/http.rb +19 -3
- data/lib/chef/http/decompressor.rb +2 -2
- data/lib/chef/json_compat.rb +1 -0
- data/lib/chef/knife.rb +16 -2
- data/lib/chef/knife/bootstrap.rb +55 -10
- data/lib/chef/knife/cookbook_site_install.rb +5 -1
- data/lib/chef/knife/core/bootstrap_context.rb +2 -1
- data/lib/chef/knife/core/node_presenter.rb +1 -1
- data/lib/chef/knife/ssh.rb +30 -16
- data/lib/chef/knife/ssl_check.rb +4 -2
- data/lib/chef/knife/ssl_fetch.rb +3 -2
- data/lib/chef/knife/status.rb +14 -1
- data/lib/chef/log.rb +14 -0
- data/lib/chef/mixin/get_source_from_package.rb +7 -2
- data/lib/chef/mixin/properties.rb +302 -0
- data/lib/chef/mixin/proxified_socket.rb +38 -0
- data/lib/chef/mixin/subclass_directive.rb +37 -0
- data/lib/chef/node.rb +13 -5
- data/lib/chef/platform/query_helpers.rb +14 -3
- data/lib/chef/platform/service_helpers.rb +20 -38
- data/lib/chef/policy_builder/expand_node_object.rb +3 -0
- data/lib/chef/policy_builder/policyfile.rb +1 -0
- data/lib/chef/property.rb +51 -12
- data/lib/chef/provider.rb +40 -35
- data/lib/chef/provider/deploy.rb +1 -1
- data/lib/chef/provider/dsc_resource.rb +54 -20
- data/lib/chef/provider/execute.rb +25 -4
- data/lib/chef/provider/group.rb +1 -1
- data/lib/chef/provider/lwrp_base.rb +1 -0
- data/lib/chef/provider/package.rb +76 -30
- data/lib/chef/provider/package/dpkg.rb +152 -69
- data/lib/chef/provider/package/openbsd.rb +6 -8
- data/lib/chef/provider/package/solaris.rb +2 -0
- data/lib/chef/provider/package/windows.rb +95 -14
- data/lib/chef/provider/package/windows/exe.rb +129 -0
- data/lib/chef/provider/package/windows/msi.rb +37 -13
- data/lib/chef/provider/package/windows/registry_uninstall_entry.rb +89 -0
- data/lib/chef/provider/package/yum.rb +13 -3
- data/lib/chef/provider/powershell_script.rb +3 -0
- data/lib/chef/provider/remote_file/cache_control_data.rb +37 -4
- data/lib/chef/provider/remote_file/http.rb +1 -1
- data/lib/chef/provider/script.rb +1 -0
- data/lib/chef/provider/service.rb +13 -10
- data/lib/chef/provider/service/solaris.rb +43 -17
- data/lib/chef/provider/service/upstart.rb +3 -3
- data/lib/chef/provider/user.rb +1 -1
- data/lib/chef/provider/user/dscl.rb +111 -100
- data/lib/chef/provider/user/windows.rb +5 -3
- data/lib/chef/recipe.rb +3 -5
- data/lib/chef/resource.rb +77 -320
- data/lib/chef/resource/action_class.rb +4 -0
- data/lib/chef/resource/dpkg_package.rb +4 -3
- data/lib/chef/resource/dsc_resource.rb +40 -2
- data/lib/chef/resource/execute.rb +9 -1
- data/lib/chef/resource/ksh.rb +32 -0
- data/lib/chef/resource/lwrp_base.rb +6 -10
- data/lib/chef/resource/package.rb +8 -9
- data/lib/chef/resource/registry_key.rb +1 -1
- data/lib/chef/resource/resource_notification.rb +14 -1
- data/lib/chef/resource/script.rb +1 -1
- data/lib/chef/resource/windows_package.rb +1 -1
- data/lib/chef/resource_builder.rb +14 -7
- data/lib/chef/resource_reporter.rb +6 -0
- data/lib/chef/resources.rb +1 -7
- data/lib/chef/rest.rb +1 -1
- data/lib/chef/run_context.rb +45 -2
- data/lib/chef/run_list/run_list_expansion.rb +47 -0
- data/lib/chef/runner.rb +25 -0
- data/lib/chef/search/query.rb +16 -2
- data/lib/chef/util/diff.rb +2 -2
- data/lib/chef/util/powershell/ps_credential.rb +2 -3
- data/lib/chef/version.rb +1 -1
- data/lib/chef/win32/api/file.rb +51 -1
- data/lib/chef/win32/file.rb +5 -0
- data/lib/chef/win32/file/version_info.rb +93 -0
- data/lib/chef/win32/mutex.rb +1 -1
- data/spec/data/apt/chef-integration-test2-1.0/debian/changelog +5 -0
- data/spec/data/apt/chef-integration-test2-1.0/debian/chef-integration-test2.debhelper.log +45 -0
- data/spec/data/apt/chef-integration-test2-1.0/debian/chef-integration-test2.substvars +1 -0
- data/spec/data/apt/chef-integration-test2-1.0/debian/chef-integration-test2/DEBIAN/conffiles +1 -0
- data/spec/data/apt/chef-integration-test2-1.0/debian/chef-integration-test2/DEBIAN/control +10 -0
- data/spec/data/apt/chef-integration-test2-1.0/debian/chef-integration-test2/DEBIAN/md5sums +1 -0
- data/spec/data/apt/chef-integration-test2-1.0/debian/compat +1 -0
- data/spec/data/apt/chef-integration-test2-1.0/debian/conffiles +1 -0
- data/spec/data/apt/chef-integration-test2-1.0/debian/control +13 -0
- data/spec/data/apt/chef-integration-test2-1.0/debian/copyright +34 -0
- data/spec/data/apt/chef-integration-test2-1.0/debian/files +1 -0
- data/spec/data/apt/chef-integration-test2-1.0/debian/rules +13 -0
- data/spec/data/apt/chef-integration-test2-1.0/debian/source/format +1 -0
- data/spec/data/apt/chef-integration-test2_1.0-1.debian.tar.gz +0 -0
- data/spec/data/apt/chef-integration-test2_1.0-1.dsc +18 -0
- data/spec/data/apt/chef-integration-test2_1.0-1_amd64.build +91 -0
- data/spec/data/apt/chef-integration-test2_1.0-1_amd64.changes +31 -0
- data/spec/data/apt/chef-integration-test2_1.0-1_amd64.deb +0 -0
- data/spec/data/apt/chef-integration-test2_1.0.orig.tar.gz +0 -0
- data/spec/functional/application_spec.rb +1 -1
- data/spec/functional/audit/runner_spec.rb +4 -0
- data/spec/functional/knife/ssh_spec.rb +5 -5
- data/spec/functional/notifications_spec.rb +74 -4
- data/spec/functional/resource/aix_service_spec.rb +2 -2
- data/spec/functional/resource/dpkg_package_spec.rb +339 -0
- data/spec/functional/resource/ifconfig_spec.rb +3 -1
- data/spec/functional/resource/mount_spec.rb +5 -2
- data/spec/functional/resource/package_spec.rb +1 -1
- data/spec/functional/resource/user/windows_spec.rb +8 -0
- data/spec/functional/resource/windows_package_spec.rb +177 -0
- data/spec/functional/win32/version_info_spec.rb +50 -0
- data/spec/integration/client/client_spec.rb +80 -0
- data/spec/integration/knife/download_spec.rb +9 -0
- data/spec/integration/knife/upload_spec.rb +28 -1
- data/spec/integration/recipes/lwrp_inline_resources_spec.rb +93 -23
- data/spec/integration/recipes/resource_action_spec.rb +211 -116
- data/spec/integration/recipes/resource_converge_if_changed_spec.rb +72 -0
- data/spec/integration/solo/solo_spec.rb +34 -0
- data/spec/spec_helper.rb +11 -1
- data/spec/support/platform_helpers.rb +8 -0
- data/spec/support/shared/integration/integration_helper.rb +6 -0
- data/spec/support/shared/unit/execute_resource.rb +5 -0
- data/spec/support/shared/unit/platform_introspector.rb +7 -0
- data/spec/tiny_server.rb +6 -2
- data/spec/unit/api_client/registration_spec.rb +5 -4
- data/spec/unit/application_spec.rb +1 -181
- data/spec/unit/chef_fs/file_system/cookbook_subdir_spec.rb +34 -0
- data/spec/unit/cookbook/metadata_spec.rb +122 -2
- data/spec/unit/http_spec.rb +102 -0
- data/spec/unit/knife/bootstrap_spec.rb +55 -13
- data/spec/unit/knife/core/bootstrap_context_spec.rb +10 -3
- data/spec/unit/knife/ssl_check_spec.rb +7 -3
- data/spec/unit/knife/ssl_fetch_spec.rb +2 -2
- data/spec/unit/knife/status_spec.rb +13 -13
- data/spec/unit/knife_spec.rb +26 -2
- data/spec/unit/lwrp_spec.rb +1 -1
- data/spec/unit/mixin/properties_spec.rb +97 -0
- data/spec/unit/mixin/proxified_socket_spec.rb +94 -0
- data/spec/unit/mixin/subclass_directive_spec.rb +45 -0
- data/spec/unit/node_spec.rb +9 -1
- data/spec/unit/policy_builder/policyfile_spec.rb +2 -0
- data/spec/unit/property/validation_spec.rb +14 -12
- data/spec/unit/property_spec.rb +56 -0
- data/spec/unit/provider/deploy_spec.rb +1 -1
- data/spec/unit/provider/dsc_resource_spec.rb +63 -24
- data/spec/unit/provider/execute_spec.rb +95 -28
- data/spec/unit/provider/package/dpkg_spec.rb +185 -96
- data/spec/unit/provider/package/windows/exe_spec.rb +251 -0
- data/spec/unit/provider/package/windows/msi_spec.rb +94 -10
- data/spec/unit/provider/package/windows_spec.rb +227 -26
- data/spec/unit/provider/package/yum_spec.rb +6 -0
- data/spec/unit/provider/package_spec.rb +495 -366
- data/spec/unit/provider/remote_file/cache_control_data_spec.rb +62 -36
- data/spec/unit/provider/script_spec.rb +2 -2
- data/spec/unit/provider/service/solaris_smf_service_spec.rb +110 -39
- data/spec/unit/provider/service/upstart_service_spec.rb +19 -0
- data/spec/unit/provider/user/dscl_spec.rb +14 -0
- data/spec/unit/provider/user/windows_spec.rb +2 -2
- data/spec/unit/provider/user_spec.rb +9 -0
- data/spec/unit/provider_resolver_spec.rb +6 -30
- data/spec/unit/recipe_spec.rb +46 -20
- data/spec/unit/resource/chef_gem_spec.rb +1 -1
- data/spec/unit/resource/dsc_resource_spec.rb +14 -3
- data/spec/unit/resource/ksh_spec.rb +40 -0
- data/spec/unit/resource/registry_key_spec.rb +2 -2
- data/spec/unit/resource/resource_notification_spec.rb +44 -45
- data/spec/unit/resource_reporter_spec.rb +7 -0
- data/spec/unit/resource_spec.rb +268 -253
- data/spec/unit/rest_spec.rb +2 -2
- data/spec/unit/run_list/run_list_expansion_spec.rb +18 -3
- data/spec/unit/search/query_spec.rb +19 -1
- data/spec/unit/util/powershell/ps_credential_spec.rb +8 -1
- data/spec/unit/windows_service_spec.rb +83 -38
- data/tasks/external_tests.rb +19 -9
- data/tasks/rspec.rb +1 -1
- metadata +64 -15
- data/spec/support/pedant/Gemfile +0 -3
- data/spec/support/pedant/pedant_config.rb +0 -129
- data/spec/support/pedant/run_pedant.rb +0 -63
- data/spec/support/pedant/stickywicket.pem +0 -27
- data/spec/unit/provider/package_spec.rbe +0 -0
@@ -17,124 +17,207 @@
|
|
17
17
|
#
|
18
18
|
|
19
19
|
require 'chef/provider/package'
|
20
|
-
require 'chef/mixin/command'
|
21
20
|
require 'chef/resource/package'
|
22
|
-
require 'chef/mixin/get_source_from_package'
|
23
21
|
|
24
22
|
class Chef
|
25
23
|
class Provider
|
26
24
|
class Package
|
27
25
|
class Dpkg < Chef::Provider::Package
|
26
|
+
DPKG_REMOVED = /^Status: deinstall ok config-files/
|
28
27
|
DPKG_INSTALLED = /^Status: install ok installed/
|
29
28
|
DPKG_VERSION = /^Version: (.+)$/
|
30
29
|
|
31
30
|
provides :dpkg_package, os: "linux"
|
32
31
|
|
33
|
-
|
32
|
+
use_multipackage_api
|
33
|
+
use_package_name_for_source
|
34
34
|
|
35
35
|
def define_resource_requirements
|
36
36
|
super
|
37
|
-
|
38
|
-
|
39
|
-
a.
|
37
|
+
|
38
|
+
requirements.assert(:install, :upgrade) do |a|
|
39
|
+
a.assertion { !resolved_source_array.compact.empty? }
|
40
|
+
a.failure_message Chef::Exceptions::Package, "#{new_resource} the source property is required for action :install or :upgrade"
|
40
41
|
end
|
41
42
|
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
a.
|
46
|
-
a.failure_message Chef::Exceptions::Package, "Package #{@new_resource.name} not found: #{@new_resource.source}"
|
47
|
-
a.whyrun "Assuming it would have been previously downloaded."
|
43
|
+
requirements.assert(:install, :upgrade) do |a|
|
44
|
+
a.assertion { source_files_exist? }
|
45
|
+
a.failure_message Chef::Exceptions::Package, "#{new_resource} source file(s) do not exist: #{missing_sources}"
|
46
|
+
a.whyrun "Assuming they would have been previously created."
|
48
47
|
end
|
49
48
|
end
|
50
49
|
|
51
50
|
def load_current_resource
|
52
|
-
@
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
if
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
end
|
51
|
+
@current_resource = Chef::Resource::Package.new(new_resource.name)
|
52
|
+
current_resource.package_name(new_resource.package_name)
|
53
|
+
|
54
|
+
if source_files_exist?
|
55
|
+
@candidate_version = get_candidate_version
|
56
|
+
current_resource.package_name(get_package_name)
|
57
|
+
# if the source file exists then our package_name is right
|
58
|
+
current_resource.version(get_current_version_from(current_package_name_array))
|
59
|
+
elsif !installing?
|
60
|
+
# we can't do this if we're installing with no source, because our package_name
|
61
|
+
# is probably not right.
|
62
|
+
#
|
63
|
+
# if we're removing or purging we don't use source, and our package_name must
|
64
|
+
# be right so we can do this.
|
65
|
+
#
|
66
|
+
# we don't error here on the dpkg command since we'll handle the exception or
|
67
|
+
# the why-run message in define_resource_requirements.
|
68
|
+
current_resource.version(get_current_version_from(current_package_name_array))
|
71
69
|
end
|
72
70
|
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
71
|
+
current_resource
|
72
|
+
end
|
73
|
+
|
74
|
+
def install_package(name, version)
|
75
|
+
sources = name.map { |n| name_sources[n] }
|
76
|
+
Chef::Log.info("#{new_resource} installing package(s): #{name.join(' ')}")
|
77
|
+
run_noninteractive("dpkg -i", new_resource.options, *sources)
|
78
|
+
end
|
79
|
+
|
80
|
+
def remove_package(name, version)
|
81
|
+
Chef::Log.info("#{new_resource} removing package(s): #{name.join(' ')}")
|
82
|
+
run_noninteractive("dpkg -r", new_resource.options, *name)
|
83
|
+
end
|
84
|
+
|
85
|
+
def purge_package(name, version)
|
86
|
+
Chef::Log.info("#{new_resource} purging packages(s): #{name.join(' ')}")
|
87
|
+
run_noninteractive("dpkg -P", new_resource.options, *name)
|
88
|
+
end
|
89
|
+
|
90
|
+
def upgrade_package(name, version)
|
91
|
+
install_package(name, version)
|
92
|
+
end
|
93
|
+
|
94
|
+
def preseed_package(preseed_file)
|
95
|
+
Chef::Log.info("#{new_resource} pre-seeding package installation instructions")
|
96
|
+
run_noninteractive("debconf-set-selections", *preseed_file)
|
97
|
+
end
|
98
|
+
|
99
|
+
def reconfig_package(name, version)
|
100
|
+
Chef::Log.info("#{new_resource} reconfiguring")
|
101
|
+
run_noninteractive("dpkg-reconfigure", *name)
|
102
|
+
end
|
103
|
+
|
104
|
+
# Override the superclass check. Multiple sources are required here.
|
105
|
+
def check_resource_semantics!
|
106
|
+
end
|
107
|
+
|
108
|
+
private
|
109
|
+
|
110
|
+
def read_current_version_of_package(package_name)
|
111
|
+
Chef::Log.debug("#{new_resource} checking install state of #{package_name}")
|
112
|
+
status = shell_out_with_timeout!("dpkg -s #{package_name}", returns: [0, 1])
|
113
|
+
package_installed = false
|
77
114
|
status.stdout.each_line do |line|
|
78
115
|
case line
|
116
|
+
when DPKG_REMOVED
|
117
|
+
# if we are 'purging' then we consider 'removed' to be 'installed'
|
118
|
+
package_installed = true if action == :purge
|
79
119
|
when DPKG_INSTALLED
|
80
120
|
package_installed = true
|
81
121
|
when DPKG_VERSION
|
82
122
|
if package_installed
|
83
|
-
Chef::Log.debug("#{
|
84
|
-
|
123
|
+
Chef::Log.debug("#{new_resource} current version is #{$1}")
|
124
|
+
return $1
|
85
125
|
end
|
86
126
|
end
|
87
127
|
end
|
128
|
+
return nil
|
129
|
+
end
|
88
130
|
|
89
|
-
|
90
|
-
|
131
|
+
def get_current_version_from(array)
|
132
|
+
array.map do |name|
|
133
|
+
read_current_version_of_package(name)
|
91
134
|
end
|
135
|
+
end
|
92
136
|
|
93
|
-
|
137
|
+
# Runs command via shell_out_with_timeout with magic environment to disable
|
138
|
+
# interactive prompts.
|
139
|
+
def run_noninteractive(*command)
|
140
|
+
shell_out_with_timeout!(a_to_s(*command), :env => { "DEBIAN_FRONTEND" => "noninteractive" })
|
94
141
|
end
|
95
142
|
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
143
|
+
# Returns true if all sources exist. Returns false if any do not, or if no
|
144
|
+
# sources were specified.
|
145
|
+
#
|
146
|
+
# @return [Boolean] True if all sources exist
|
147
|
+
def source_files_exist?
|
148
|
+
resolved_source_array.all? {|s| s && ::File.exist?(s) }
|
101
149
|
end
|
102
150
|
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
)
|
151
|
+
# Helper to return all the nanes of the missing sources for error messages.
|
152
|
+
#
|
153
|
+
# @return [Array<String>] Array of missing sources
|
154
|
+
def missing_sources
|
155
|
+
resolved_source_array.select {|s| s.nil? || !::File.exist?(s) }
|
108
156
|
end
|
109
157
|
|
110
|
-
def
|
111
|
-
|
112
|
-
run_noninteractive(
|
113
|
-
"dpkg -P#{expand_options(@new_resource.options)} #{@new_resource.package_name}"
|
114
|
-
)
|
158
|
+
def current_package_name_array
|
159
|
+
[ current_resource.package_name ].flatten
|
115
160
|
end
|
116
161
|
|
117
|
-
|
118
|
-
|
162
|
+
# Helper to construct Hash of names-to-sources.
|
163
|
+
#
|
164
|
+
# @return [Hash] Mapping of package names to sources
|
165
|
+
def name_sources
|
166
|
+
@name_sources =
|
167
|
+
begin
|
168
|
+
Hash[*package_name_array.zip(resolved_source_array).flatten]
|
169
|
+
end
|
119
170
|
end
|
120
171
|
|
121
|
-
|
122
|
-
|
123
|
-
|
172
|
+
# Helper to construct Hash of names-to-package-information.
|
173
|
+
#
|
174
|
+
# @return [Hash] Mapping of package names to package information
|
175
|
+
def name_pkginfo
|
176
|
+
@name_pkginfo ||=
|
177
|
+
begin
|
178
|
+
pkginfos = resolved_source_array.map do |src|
|
179
|
+
Chef::Log.debug("#{new_resource} checking #{src} dpkg status")
|
180
|
+
status = shell_out_with_timeout!("dpkg-deb -W #{src}")
|
181
|
+
status.stdout
|
182
|
+
end
|
183
|
+
Hash[*package_name_array.zip(pkginfos).flatten]
|
184
|
+
end
|
124
185
|
end
|
125
186
|
|
126
|
-
def
|
127
|
-
|
128
|
-
|
187
|
+
def name_candidate_version
|
188
|
+
@name_candidate_version ||=
|
189
|
+
begin
|
190
|
+
Hash[name_pkginfo.map {|k, v| [k, v ? v.split("\t")[1].strip : nil] }]
|
191
|
+
end
|
129
192
|
end
|
130
193
|
|
131
|
-
|
132
|
-
|
133
|
-
|
194
|
+
def name_package_name
|
195
|
+
@name_package_name ||=
|
196
|
+
begin
|
197
|
+
Hash[name_pkginfo.map {|k, v| [k, v ? v.split("\t")[0] : nil] }]
|
198
|
+
end
|
199
|
+
end
|
200
|
+
|
201
|
+
# Return candidate version array from pkg-deb -W against the source file(s).
|
202
|
+
#
|
203
|
+
# @return [Array] Array of candidate versions read from the source files
|
204
|
+
def get_candidate_version
|
205
|
+
package_name_array.map { |name| name_candidate_version[name] }
|
206
|
+
end
|
207
|
+
|
208
|
+
# Return package names from the candidate source file(s).
|
209
|
+
#
|
210
|
+
# @return [Array] Array of actual package names read from the source files
|
211
|
+
def get_package_name
|
212
|
+
package_name_array.map { |name| name_package_name[name] }
|
213
|
+
end
|
214
|
+
|
215
|
+
# Since upgrade just calls install, this is a helper to determine
|
216
|
+
# if our action means that we'll be calling install_package.
|
134
217
|
#
|
135
|
-
#
|
136
|
-
def
|
137
|
-
|
218
|
+
# @return [Boolean] true if we're doing :install or :upgrade
|
219
|
+
def installing?
|
220
|
+
[:install, :upgrade].include?(action)
|
138
221
|
end
|
139
222
|
|
140
223
|
end
|
@@ -72,18 +72,16 @@ class Chef
|
|
72
72
|
if parts = name.match(/^(.+?)--(.+)/) # use double-dash for stems with flavors, see man page for pkg_add
|
73
73
|
name = parts[1]
|
74
74
|
end
|
75
|
-
shell_out_with_timeout!("pkg_add -r #{name}#{version_string}", :env => {"PKG_PATH" => pkg_path}).status
|
75
|
+
shell_out_with_timeout!("pkg_add -r #{name}#{version_string(version)}", :env => {"PKG_PATH" => pkg_path}).status
|
76
76
|
Chef::Log.debug("#{new_resource.package_name} installed")
|
77
77
|
end
|
78
78
|
end
|
79
79
|
|
80
80
|
def remove_package(name, version)
|
81
|
-
version_string = ''
|
82
|
-
version_string += "-#{version}" if version
|
83
81
|
if parts = name.match(/^(.+?)--(.+)/)
|
84
82
|
name = parts[1]
|
85
83
|
end
|
86
|
-
shell_out_with_timeout!("pkg_delete #{name}#{version_string}", :env => nil).status
|
84
|
+
shell_out_with_timeout!("pkg_delete #{name}#{version_string(version)}", :env => nil).status
|
87
85
|
end
|
88
86
|
|
89
87
|
private
|
@@ -103,7 +101,7 @@ class Chef
|
|
103
101
|
def candidate_version
|
104
102
|
@candidate_version ||= begin
|
105
103
|
results = []
|
106
|
-
shell_out_with_timeout!("pkg_info -I \"#{new_resource.package_name}#{version_string}\"", :env => nil, :returns => [0,1]).stdout.each_line do |line|
|
104
|
+
shell_out_with_timeout!("pkg_info -I \"#{new_resource.package_name}#{version_string(new_resource.version)}\"", :env => nil, :returns => [0,1]).stdout.each_line do |line|
|
107
105
|
if parts = new_resource.package_name.match(/^(.+?)--(.+)/)
|
108
106
|
results << line[/^#{Regexp.escape(parts[1])}-(.+?)\s/, 1]
|
109
107
|
else
|
@@ -111,7 +109,7 @@ class Chef
|
|
111
109
|
end
|
112
110
|
end
|
113
111
|
results = results.reject(&:nil?)
|
114
|
-
Chef::Log.debug("
|
112
|
+
Chef::Log.debug("Candidate versions of '#{new_resource.package_name}' are '#{results}'")
|
115
113
|
case results.length
|
116
114
|
when 0
|
117
115
|
[]
|
@@ -123,9 +121,9 @@ class Chef
|
|
123
121
|
end
|
124
122
|
end
|
125
123
|
|
126
|
-
def version_string
|
124
|
+
def version_string(version)
|
127
125
|
ver = ''
|
128
|
-
ver += "-#{
|
126
|
+
ver += "-#{version}" if version
|
129
127
|
end
|
130
128
|
|
131
129
|
def pkg_path
|
@@ -32,11 +32,7 @@ class Chef
|
|
32
32
|
provides :package, os: "windows"
|
33
33
|
provides :windows_package, os: "windows"
|
34
34
|
|
35
|
-
|
36
|
-
# source attributes, or search for text strings in the installer file
|
37
|
-
# binary to determine the installer type for the user. Since the file
|
38
|
-
# must be on disk to do so, we have to make this choice in the provider.
|
39
|
-
require 'chef/provider/package/windows/msi.rb'
|
35
|
+
require 'chef/provider/package/windows/registry_uninstall_entry.rb'
|
40
36
|
|
41
37
|
# load_current_resource is run in Chef::Provider#run_action when not in whyrun_mode?
|
42
38
|
def load_current_resource
|
@@ -56,24 +52,64 @@ class Chef
|
|
56
52
|
@package_provider ||= begin
|
57
53
|
case installer_type
|
58
54
|
when :msi
|
59
|
-
Chef::
|
55
|
+
Chef::Log.debug("#{@new_resource} is MSI")
|
56
|
+
require 'chef/provider/package/windows/msi'
|
57
|
+
Chef::Provider::Package::Windows::MSI.new(resource_for_provider, uninstall_registry_entries)
|
60
58
|
else
|
61
|
-
|
59
|
+
Chef::Log.debug("#{@new_resource} is EXE with type '#{installer_type}'")
|
60
|
+
require 'chef/provider/package/windows/exe'
|
61
|
+
Chef::Provider::Package::Windows::Exe.new(resource_for_provider, installer_type, uninstall_registry_entries)
|
62
62
|
end
|
63
63
|
end
|
64
64
|
end
|
65
65
|
|
66
66
|
def installer_type
|
67
|
+
# Depending on the installer, we may need to examine installer_type or
|
68
|
+
# source attributes, or search for text strings in the installer file
|
69
|
+
# binary to determine the installer type for the user. Since the file
|
70
|
+
# must be on disk to do so, we have to make this choice in the provider.
|
67
71
|
@installer_type ||= begin
|
68
72
|
if @new_resource.installer_type
|
69
73
|
@new_resource.installer_type
|
70
|
-
|
71
|
-
|
74
|
+
elsif source_location.nil?
|
75
|
+
inferred_registry_type
|
76
|
+
else
|
77
|
+
basename = ::File.basename(source_location)
|
78
|
+
file_extension = basename.split(".").last.downcase
|
72
79
|
|
73
80
|
if file_extension == "msi"
|
74
81
|
:msi
|
75
82
|
else
|
76
|
-
|
83
|
+
# search the binary file for installer type
|
84
|
+
::Kernel.open(::File.expand_path(source_location), 'rb') do |io|
|
85
|
+
filesize = io.size
|
86
|
+
bufsize = 4096 # read 4K buffers
|
87
|
+
overlap = 16 # bytes to overlap between buffer reads
|
88
|
+
|
89
|
+
until io.eof
|
90
|
+
contents = io.read(bufsize)
|
91
|
+
|
92
|
+
case contents
|
93
|
+
when /inno/i # Inno Setup
|
94
|
+
return :inno
|
95
|
+
when /wise/i # Wise InstallMaster
|
96
|
+
return :wise
|
97
|
+
when /nullsoft/i # Nullsoft Scriptable Install System
|
98
|
+
return :nsis
|
99
|
+
end
|
100
|
+
|
101
|
+
if (io.tell() < filesize)
|
102
|
+
io.seek(io.tell() - overlap)
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
# if file is named 'setup.exe' assume installshield
|
108
|
+
if basename == 'setup.exe'
|
109
|
+
:installshield
|
110
|
+
else
|
111
|
+
fail Chef::Exceptions::CannotDetermineWindowsInstallerType, "Installer type for Windows Package '#{@new_resource.name}' not specified and cannot be determined from file extension '#{file_extension}'"
|
112
|
+
end
|
77
113
|
end
|
78
114
|
end
|
79
115
|
end
|
@@ -93,11 +129,11 @@ class Chef
|
|
93
129
|
# Chef::Provider::Package action_install + action_remove call install_package + remove_package
|
94
130
|
# Pass those calls to the correct sub-provider
|
95
131
|
def install_package(name, version)
|
96
|
-
package_provider.install_package
|
132
|
+
package_provider.install_package
|
97
133
|
end
|
98
134
|
|
99
135
|
def remove_package(name, version)
|
100
|
-
package_provider.remove_package
|
136
|
+
package_provider.remove_package
|
101
137
|
end
|
102
138
|
|
103
139
|
# @return [Array] new_version(s) as an array
|
@@ -106,15 +142,59 @@ class Chef
|
|
106
142
|
[new_resource.version]
|
107
143
|
end
|
108
144
|
|
145
|
+
# @return [String] candidate_version
|
146
|
+
def candidate_version
|
147
|
+
@candidate_version ||= (@new_resource.version || 'latest')
|
148
|
+
end
|
149
|
+
|
150
|
+
# @return [Array] current_version(s) as an array
|
151
|
+
# this package provider does not support package arrays
|
152
|
+
# However, There may be multiple versions for a single
|
153
|
+
# package so the first element may be a nested array
|
154
|
+
def current_version_array
|
155
|
+
[ current_resource.version ]
|
156
|
+
end
|
157
|
+
|
158
|
+
# @param current_version<String> one or more versions currently installed
|
159
|
+
# @param new_version<String> version of the new resource
|
160
|
+
#
|
161
|
+
# @return [Boolean] true if new_version is equal to or included in current_version
|
162
|
+
def target_version_already_installed?(current_version, new_version)
|
163
|
+
Chef::Log.debug("Checking if #{@new_resource} version '#{new_version}' is already installed. #{current_version} is currently installed")
|
164
|
+
if current_version.is_a?(Array)
|
165
|
+
current_version.include?(new_version)
|
166
|
+
else
|
167
|
+
new_version == current_version
|
168
|
+
end
|
169
|
+
end
|
170
|
+
|
171
|
+
def have_any_matching_version?
|
172
|
+
target_version_already_installed?(current_resource.version, new_resource.version)
|
173
|
+
end
|
174
|
+
|
109
175
|
private
|
110
176
|
|
177
|
+
def uninstall_registry_entries
|
178
|
+
@uninstall_registry_entries ||= Chef::Provider::Package::Windows::RegistryUninstallEntry.find_entries(new_resource.name)
|
179
|
+
end
|
180
|
+
|
181
|
+
def inferred_registry_type
|
182
|
+
uninstall_registry_entries.each do |entry|
|
183
|
+
return :inno if entry.key.end_with?("_is1")
|
184
|
+
return :msi if entry.uninstall_string.downcase.start_with?("msiexec.exe ")
|
185
|
+
return :nsis if entry.uninstall_string.downcase.end_with?("uninst.exe\"")
|
186
|
+
end
|
187
|
+
nil
|
188
|
+
end
|
189
|
+
|
111
190
|
def downloadable_file_missing?
|
112
191
|
uri_scheme?(new_resource.source) && !::File.exists?(source_location)
|
113
192
|
end
|
114
193
|
|
115
194
|
def resource_for_provider
|
116
195
|
@resource_for_provider = Chef::Resource::WindowsPackage.new(new_resource.name).tap do |r|
|
117
|
-
r.source(Chef::Util::PathHelper.validate_path(source_location))
|
196
|
+
r.source(Chef::Util::PathHelper.validate_path(source_location)) unless source_location.nil?
|
197
|
+
r.version(new_resource.version)
|
118
198
|
r.timeout(new_resource.timeout)
|
119
199
|
r.returns(new_resource.returns)
|
120
200
|
r.options(new_resource.options)
|
@@ -151,7 +231,8 @@ class Chef
|
|
151
231
|
if uri_scheme?(new_resource.source)
|
152
232
|
source_resource.path
|
153
233
|
else
|
154
|
-
Chef::Util::PathHelper.cleanpath(new_resource.source)
|
234
|
+
new_source = Chef::Util::PathHelper.cleanpath(new_resource.source)
|
235
|
+
::File.exist?(new_source) ? new_source : nil
|
155
236
|
end
|
156
237
|
end
|
157
238
|
|