chef 12.5.1 → 12.6.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (221) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +6 -1
  3. data/README.md +6 -4
  4. data/Rakefile +1 -4
  5. data/chef-windows.gemspec +21 -0
  6. data/chef.gemspec +58 -0
  7. data/lib/chef/api_client/registration.rb +9 -4
  8. data/lib/chef/application.rb +3 -84
  9. data/lib/chef/application/apply.rb +9 -2
  10. data/lib/chef/application/client.rb +8 -3
  11. data/lib/chef/application/solo.rb +7 -1
  12. data/lib/chef/application/windows_service.rb +21 -6
  13. data/lib/chef/application/windows_service_manager.rb +2 -3
  14. data/lib/chef/audit/runner.rb +1 -0
  15. data/lib/chef/chef_class.rb +1 -11
  16. data/lib/chef/chef_fs/chef_fs_data_store.rb +181 -2
  17. data/lib/chef/chef_fs/file_system/cookbook_subdir.rb +5 -0
  18. data/lib/chef/chef_fs/file_system/file_system_entry.rb +11 -7
  19. data/lib/chef/client.rb +28 -1
  20. data/lib/chef/cookbook/cookbook_collection.rb +14 -1
  21. data/lib/chef/cookbook/cookbook_version_loader.rb +1 -1
  22. data/lib/chef/cookbook/metadata.rb +115 -9
  23. data/lib/chef/cookbook/remote_file_vendor.rb +1 -1
  24. data/lib/chef/cookbook_version.rb +6 -2
  25. data/lib/chef/data_bag.rb +1 -1
  26. data/lib/chef/data_bag_item.rb +1 -1
  27. data/lib/chef/digester.rb +5 -1
  28. data/lib/chef/dsl/chef_provisioning.rb +57 -0
  29. data/lib/chef/dsl/cheffish.rb +64 -0
  30. data/lib/chef/dsl/declare_resource.rb +108 -0
  31. data/lib/chef/dsl/platform_introspection.rb +3 -3
  32. data/lib/chef/dsl/recipe.rb +3 -73
  33. data/lib/chef/dsl/resources.rb +27 -1
  34. data/lib/chef/event_dispatch/base.rb +3 -0
  35. data/lib/chef/event_dispatch/dispatcher.rb +5 -0
  36. data/lib/chef/event_dispatch/events_output_stream.rb +8 -0
  37. data/lib/chef/exceptions.rb +21 -1
  38. data/lib/chef/file_access_control/unix.rb +12 -12
  39. data/lib/chef/file_content_management/deploy/cp.rb +2 -2
  40. data/lib/chef/file_content_management/deploy/mv_unix.rb +4 -4
  41. data/lib/chef/file_content_management/deploy/mv_windows.rb +1 -1
  42. data/lib/chef/formatters/base.rb +7 -0
  43. data/lib/chef/formatters/error_inspectors/compile_error_inspector.rb +2 -2
  44. data/lib/chef/formatters/indentable_output_stream.rb +5 -0
  45. data/lib/chef/http.rb +19 -3
  46. data/lib/chef/http/decompressor.rb +2 -2
  47. data/lib/chef/json_compat.rb +1 -0
  48. data/lib/chef/knife.rb +16 -2
  49. data/lib/chef/knife/bootstrap.rb +55 -10
  50. data/lib/chef/knife/cookbook_site_install.rb +5 -1
  51. data/lib/chef/knife/core/bootstrap_context.rb +2 -1
  52. data/lib/chef/knife/core/node_presenter.rb +1 -1
  53. data/lib/chef/knife/ssh.rb +30 -16
  54. data/lib/chef/knife/ssl_check.rb +4 -2
  55. data/lib/chef/knife/ssl_fetch.rb +3 -2
  56. data/lib/chef/knife/status.rb +14 -1
  57. data/lib/chef/log.rb +14 -0
  58. data/lib/chef/mixin/get_source_from_package.rb +7 -2
  59. data/lib/chef/mixin/properties.rb +302 -0
  60. data/lib/chef/mixin/proxified_socket.rb +38 -0
  61. data/lib/chef/mixin/subclass_directive.rb +37 -0
  62. data/lib/chef/node.rb +13 -5
  63. data/lib/chef/platform/query_helpers.rb +14 -3
  64. data/lib/chef/platform/service_helpers.rb +20 -38
  65. data/lib/chef/policy_builder/expand_node_object.rb +3 -0
  66. data/lib/chef/policy_builder/policyfile.rb +1 -0
  67. data/lib/chef/property.rb +51 -12
  68. data/lib/chef/provider.rb +40 -35
  69. data/lib/chef/provider/deploy.rb +1 -1
  70. data/lib/chef/provider/dsc_resource.rb +54 -20
  71. data/lib/chef/provider/execute.rb +25 -4
  72. data/lib/chef/provider/group.rb +1 -1
  73. data/lib/chef/provider/lwrp_base.rb +1 -0
  74. data/lib/chef/provider/package.rb +76 -30
  75. data/lib/chef/provider/package/dpkg.rb +152 -69
  76. data/lib/chef/provider/package/openbsd.rb +6 -8
  77. data/lib/chef/provider/package/solaris.rb +2 -0
  78. data/lib/chef/provider/package/windows.rb +95 -14
  79. data/lib/chef/provider/package/windows/exe.rb +129 -0
  80. data/lib/chef/provider/package/windows/msi.rb +37 -13
  81. data/lib/chef/provider/package/windows/registry_uninstall_entry.rb +89 -0
  82. data/lib/chef/provider/package/yum.rb +13 -3
  83. data/lib/chef/provider/powershell_script.rb +3 -0
  84. data/lib/chef/provider/remote_file/cache_control_data.rb +37 -4
  85. data/lib/chef/provider/remote_file/http.rb +1 -1
  86. data/lib/chef/provider/script.rb +1 -0
  87. data/lib/chef/provider/service.rb +13 -10
  88. data/lib/chef/provider/service/solaris.rb +43 -17
  89. data/lib/chef/provider/service/upstart.rb +3 -3
  90. data/lib/chef/provider/user.rb +1 -1
  91. data/lib/chef/provider/user/dscl.rb +111 -100
  92. data/lib/chef/provider/user/windows.rb +5 -3
  93. data/lib/chef/recipe.rb +3 -5
  94. data/lib/chef/resource.rb +77 -320
  95. data/lib/chef/resource/action_class.rb +4 -0
  96. data/lib/chef/resource/dpkg_package.rb +4 -3
  97. data/lib/chef/resource/dsc_resource.rb +40 -2
  98. data/lib/chef/resource/execute.rb +9 -1
  99. data/lib/chef/resource/ksh.rb +32 -0
  100. data/lib/chef/resource/lwrp_base.rb +6 -10
  101. data/lib/chef/resource/package.rb +8 -9
  102. data/lib/chef/resource/registry_key.rb +1 -1
  103. data/lib/chef/resource/resource_notification.rb +14 -1
  104. data/lib/chef/resource/script.rb +1 -1
  105. data/lib/chef/resource/windows_package.rb +1 -1
  106. data/lib/chef/resource_builder.rb +14 -7
  107. data/lib/chef/resource_reporter.rb +6 -0
  108. data/lib/chef/resources.rb +1 -7
  109. data/lib/chef/rest.rb +1 -1
  110. data/lib/chef/run_context.rb +45 -2
  111. data/lib/chef/run_list/run_list_expansion.rb +47 -0
  112. data/lib/chef/runner.rb +25 -0
  113. data/lib/chef/search/query.rb +16 -2
  114. data/lib/chef/util/diff.rb +2 -2
  115. data/lib/chef/util/powershell/ps_credential.rb +2 -3
  116. data/lib/chef/version.rb +1 -1
  117. data/lib/chef/win32/api/file.rb +51 -1
  118. data/lib/chef/win32/file.rb +5 -0
  119. data/lib/chef/win32/file/version_info.rb +93 -0
  120. data/lib/chef/win32/mutex.rb +1 -1
  121. data/spec/data/apt/chef-integration-test2-1.0/debian/changelog +5 -0
  122. data/spec/data/apt/chef-integration-test2-1.0/debian/chef-integration-test2.debhelper.log +45 -0
  123. data/spec/data/apt/chef-integration-test2-1.0/debian/chef-integration-test2.substvars +1 -0
  124. data/spec/data/apt/chef-integration-test2-1.0/debian/chef-integration-test2/DEBIAN/conffiles +1 -0
  125. data/spec/data/apt/chef-integration-test2-1.0/debian/chef-integration-test2/DEBIAN/control +10 -0
  126. data/spec/data/apt/chef-integration-test2-1.0/debian/chef-integration-test2/DEBIAN/md5sums +1 -0
  127. data/spec/data/apt/chef-integration-test2-1.0/debian/compat +1 -0
  128. data/spec/data/apt/chef-integration-test2-1.0/debian/conffiles +1 -0
  129. data/spec/data/apt/chef-integration-test2-1.0/debian/control +13 -0
  130. data/spec/data/apt/chef-integration-test2-1.0/debian/copyright +34 -0
  131. data/spec/data/apt/chef-integration-test2-1.0/debian/files +1 -0
  132. data/spec/data/apt/chef-integration-test2-1.0/debian/rules +13 -0
  133. data/spec/data/apt/chef-integration-test2-1.0/debian/source/format +1 -0
  134. data/spec/data/apt/chef-integration-test2_1.0-1.debian.tar.gz +0 -0
  135. data/spec/data/apt/chef-integration-test2_1.0-1.dsc +18 -0
  136. data/spec/data/apt/chef-integration-test2_1.0-1_amd64.build +91 -0
  137. data/spec/data/apt/chef-integration-test2_1.0-1_amd64.changes +31 -0
  138. data/spec/data/apt/chef-integration-test2_1.0-1_amd64.deb +0 -0
  139. data/spec/data/apt/chef-integration-test2_1.0.orig.tar.gz +0 -0
  140. data/spec/functional/application_spec.rb +1 -1
  141. data/spec/functional/audit/runner_spec.rb +4 -0
  142. data/spec/functional/knife/ssh_spec.rb +5 -5
  143. data/spec/functional/notifications_spec.rb +74 -4
  144. data/spec/functional/resource/aix_service_spec.rb +2 -2
  145. data/spec/functional/resource/dpkg_package_spec.rb +339 -0
  146. data/spec/functional/resource/ifconfig_spec.rb +3 -1
  147. data/spec/functional/resource/mount_spec.rb +5 -2
  148. data/spec/functional/resource/package_spec.rb +1 -1
  149. data/spec/functional/resource/user/windows_spec.rb +8 -0
  150. data/spec/functional/resource/windows_package_spec.rb +177 -0
  151. data/spec/functional/win32/version_info_spec.rb +50 -0
  152. data/spec/integration/client/client_spec.rb +80 -0
  153. data/spec/integration/knife/download_spec.rb +9 -0
  154. data/spec/integration/knife/upload_spec.rb +28 -1
  155. data/spec/integration/recipes/lwrp_inline_resources_spec.rb +93 -23
  156. data/spec/integration/recipes/resource_action_spec.rb +211 -116
  157. data/spec/integration/recipes/resource_converge_if_changed_spec.rb +72 -0
  158. data/spec/integration/solo/solo_spec.rb +34 -0
  159. data/spec/spec_helper.rb +11 -1
  160. data/spec/support/platform_helpers.rb +8 -0
  161. data/spec/support/shared/integration/integration_helper.rb +6 -0
  162. data/spec/support/shared/unit/execute_resource.rb +5 -0
  163. data/spec/support/shared/unit/platform_introspector.rb +7 -0
  164. data/spec/tiny_server.rb +6 -2
  165. data/spec/unit/api_client/registration_spec.rb +5 -4
  166. data/spec/unit/application_spec.rb +1 -181
  167. data/spec/unit/chef_fs/file_system/cookbook_subdir_spec.rb +34 -0
  168. data/spec/unit/cookbook/metadata_spec.rb +122 -2
  169. data/spec/unit/http_spec.rb +102 -0
  170. data/spec/unit/knife/bootstrap_spec.rb +55 -13
  171. data/spec/unit/knife/core/bootstrap_context_spec.rb +10 -3
  172. data/spec/unit/knife/ssl_check_spec.rb +7 -3
  173. data/spec/unit/knife/ssl_fetch_spec.rb +2 -2
  174. data/spec/unit/knife/status_spec.rb +13 -13
  175. data/spec/unit/knife_spec.rb +26 -2
  176. data/spec/unit/lwrp_spec.rb +1 -1
  177. data/spec/unit/mixin/properties_spec.rb +97 -0
  178. data/spec/unit/mixin/proxified_socket_spec.rb +94 -0
  179. data/spec/unit/mixin/subclass_directive_spec.rb +45 -0
  180. data/spec/unit/node_spec.rb +9 -1
  181. data/spec/unit/policy_builder/policyfile_spec.rb +2 -0
  182. data/spec/unit/property/validation_spec.rb +14 -12
  183. data/spec/unit/property_spec.rb +56 -0
  184. data/spec/unit/provider/deploy_spec.rb +1 -1
  185. data/spec/unit/provider/dsc_resource_spec.rb +63 -24
  186. data/spec/unit/provider/execute_spec.rb +95 -28
  187. data/spec/unit/provider/package/dpkg_spec.rb +185 -96
  188. data/spec/unit/provider/package/windows/exe_spec.rb +251 -0
  189. data/spec/unit/provider/package/windows/msi_spec.rb +94 -10
  190. data/spec/unit/provider/package/windows_spec.rb +227 -26
  191. data/spec/unit/provider/package/yum_spec.rb +6 -0
  192. data/spec/unit/provider/package_spec.rb +495 -366
  193. data/spec/unit/provider/remote_file/cache_control_data_spec.rb +62 -36
  194. data/spec/unit/provider/script_spec.rb +2 -2
  195. data/spec/unit/provider/service/solaris_smf_service_spec.rb +110 -39
  196. data/spec/unit/provider/service/upstart_service_spec.rb +19 -0
  197. data/spec/unit/provider/user/dscl_spec.rb +14 -0
  198. data/spec/unit/provider/user/windows_spec.rb +2 -2
  199. data/spec/unit/provider/user_spec.rb +9 -0
  200. data/spec/unit/provider_resolver_spec.rb +6 -30
  201. data/spec/unit/recipe_spec.rb +46 -20
  202. data/spec/unit/resource/chef_gem_spec.rb +1 -1
  203. data/spec/unit/resource/dsc_resource_spec.rb +14 -3
  204. data/spec/unit/resource/ksh_spec.rb +40 -0
  205. data/spec/unit/resource/registry_key_spec.rb +2 -2
  206. data/spec/unit/resource/resource_notification_spec.rb +44 -45
  207. data/spec/unit/resource_reporter_spec.rb +7 -0
  208. data/spec/unit/resource_spec.rb +268 -253
  209. data/spec/unit/rest_spec.rb +2 -2
  210. data/spec/unit/run_list/run_list_expansion_spec.rb +18 -3
  211. data/spec/unit/search/query_spec.rb +19 -1
  212. data/spec/unit/util/powershell/ps_credential_spec.rb +8 -1
  213. data/spec/unit/windows_service_spec.rb +83 -38
  214. data/tasks/external_tests.rb +19 -9
  215. data/tasks/rspec.rb +1 -1
  216. metadata +64 -15
  217. data/spec/support/pedant/Gemfile +0 -3
  218. data/spec/support/pedant/pedant_config.rb +0 -129
  219. data/spec/support/pedant/run_pedant.rb +0 -63
  220. data/spec/support/pedant/stickywicket.pem +0 -27
  221. data/spec/unit/provider/package_spec.rbe +0 -0
@@ -0,0 +1,129 @@
1
+ #
2
+ # Author:: Seth Chisamore (<schisamo@chef.io>)
3
+ # Author:: Matt Wrock <matt@mattwrock.com>
4
+ # Copyright:: Copyright (c) 2011, 2015 Chef Software, Inc.
5
+ # License:: Apache License, Version 2.0
6
+ #
7
+ # Licensed under the Apache License, Version 2.0 (the "License");
8
+ # you may not use this file except in compliance with the License.
9
+ # You may obtain a copy of the License at
10
+ #
11
+ # http://www.apache.org/licenses/LICENSE-2.0
12
+ #
13
+ # Unless required by applicable law or agreed to in writing, software
14
+ # distributed under the License is distributed on an "AS IS" BASIS,
15
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16
+ # See the License for the specific language governing permissions and
17
+ # limitations under the License.
18
+ #
19
+
20
+ require 'chef/mixin/shell_out'
21
+
22
+ class Chef
23
+ class Provider
24
+ class Package
25
+ class Windows
26
+ class Exe
27
+ include Chef::Mixin::ShellOut
28
+
29
+ def initialize(resource, installer_type, uninstall_entries)
30
+ @new_resource = resource
31
+ @installer_type = installer_type
32
+ @uninstall_entries = uninstall_entries
33
+ end
34
+
35
+ attr_reader :new_resource
36
+ attr_reader :installer_type
37
+ attr_reader :uninstall_entries
38
+
39
+ # From Chef::Provider::Package
40
+ def expand_options(options)
41
+ options ? " #{options}" : ""
42
+ end
43
+
44
+ # Returns a version if the package is installed or nil if it is not.
45
+ def installed_version
46
+ Chef::Log.debug("#{new_resource} checking package version")
47
+ current_installed_version
48
+ end
49
+
50
+ def package_version
51
+ new_resource.version || install_file_version
52
+ end
53
+
54
+ def install_package
55
+ Chef::Log.debug("#{new_resource} installing #{new_resource.installer_type} package '#{new_resource.source}'")
56
+ shell_out!(
57
+ [
58
+ "start",
59
+ "\"\"",
60
+ "/wait",
61
+ "\"#{new_resource.source}\"",
62
+ unattended_flags,
63
+ expand_options(new_resource.options),
64
+ "& exit %%%%ERRORLEVEL%%%%"
65
+ ].join(" "), timeout: new_resource.timeout, returns: new_resource.returns
66
+ )
67
+ end
68
+
69
+ def remove_package
70
+ uninstall_version = new_resource.version || current_installed_version
71
+ uninstall_entries.select { |entry| [uninstall_version].flatten.include?(entry.display_version) }
72
+ .map { |version| version.uninstall_string }.uniq.each do |uninstall_string|
73
+ Chef::Log.debug("Registry provided uninstall string for #{new_resource} is '#{uninstall_string}'")
74
+ shell_out!(uninstall_command(uninstall_string), { returns: new_resource.returns })
75
+ end
76
+ end
77
+
78
+ private
79
+
80
+ def uninstall_command(uninstall_string)
81
+ uninstall_string.delete!('"')
82
+ uninstall_string = [
83
+ %q{/d"},
84
+ ::File.dirname(uninstall_string),
85
+ %q{" },
86
+ ::File.basename(uninstall_string),
87
+ expand_options(new_resource.options),
88
+ " ",
89
+ unattended_flags
90
+ ].join
91
+ %Q{start "" /wait #{uninstall_string} & exit %%%%ERRORLEVEL%%%%}
92
+ end
93
+
94
+ def current_installed_version
95
+ @current_installed_version ||= uninstall_entries.count == 0 ? nil : begin
96
+ uninstall_entries.map { |entry| entry.display_version }.uniq
97
+ end
98
+ end
99
+
100
+ def install_file_version
101
+ @install_file_version ||= begin
102
+ if ::File.exist?(@new_resource.source)
103
+ version_info = Chef::ReservedNames::Win32::File.version_info(new_resource.source)
104
+ file_version = version_info.FileVersion || version_info.ProductVersion
105
+ file_version == '' ? nil : file_version
106
+ else
107
+ nil
108
+ end
109
+ end
110
+ end
111
+
112
+ # http://unattended.sourceforge.net/installers.php
113
+ def unattended_flags
114
+ case installer_type
115
+ when :installshield
116
+ '/s /sms'
117
+ when :nsis
118
+ '/S /NCRC'
119
+ when :inno
120
+ '/VERYSILENT /SUPPRESSMSGBOXES /NORESTART'
121
+ when :wise
122
+ '/s'
123
+ end
124
+ end
125
+ end
126
+ end
127
+ end
128
+ end
129
+ end
@@ -29,10 +29,14 @@ class Chef
29
29
  include Chef::ReservedNames::Win32::API::Installer if (RUBY_PLATFORM =~ /mswin|mingw32|windows/) && Chef::Platform.supports_msi?
30
30
  include Chef::Mixin::ShellOut
31
31
 
32
- def initialize(resource)
32
+ def initialize(resource, uninstall_entries)
33
33
  @new_resource = resource
34
+ @uninstall_entries = uninstall_entries
34
35
  end
35
36
 
37
+ attr_reader :new_resource
38
+ attr_reader :uninstall_entries
39
+
36
40
  # From Chef::Provider::Package
37
41
  def expand_options(options)
38
42
  options ? " #{options}" : ""
@@ -40,27 +44,47 @@ class Chef
40
44
 
41
45
  # Returns a version if the package is installed or nil if it is not.
42
46
  def installed_version
43
- Chef::Log.debug("#{@new_resource} getting product code for package at #{@new_resource.source}")
44
- product_code = get_product_property(@new_resource.source, "ProductCode")
45
- Chef::Log.debug("#{@new_resource} checking package status and version for #{product_code}")
46
- get_installed_version(product_code)
47
+ if ::File.exist?(new_resource.source)
48
+ Chef::Log.debug("#{new_resource} getting product code for package at #{new_resource.source}")
49
+ product_code = get_product_property(new_resource.source, "ProductCode")
50
+ Chef::Log.debug("#{new_resource} checking package status and version for #{product_code}")
51
+ get_installed_version(product_code)
52
+ else
53
+ uninstall_entries.count == 0 ? nil : begin
54
+ uninstall_entries.map { |entry| entry.display_version }.uniq
55
+ end
56
+ end
47
57
  end
48
58
 
49
59
  def package_version
50
- Chef::Log.debug("#{@new_resource} getting product version for package at #{@new_resource.source}")
51
- get_product_property(@new_resource.source, "ProductVersion")
60
+ return new_resource.version if new_resource.version
61
+ if ::File.exist?(new_resource.source)
62
+ Chef::Log.debug("#{new_resource} getting product version for package at #{new_resource.source}")
63
+ get_product_property(new_resource.source, "ProductVersion")
64
+ end
52
65
  end
53
66
 
54
- def install_package(name, version)
67
+ def install_package
55
68
  # We could use MsiConfigureProduct here, but we'll start off with msiexec
56
- Chef::Log.debug("#{@new_resource} installing MSI package '#{@new_resource.source}'")
57
- shell_out!("msiexec /qn /i \"#{@new_resource.source}\" #{expand_options(@new_resource.options)}", {:timeout => @new_resource.timeout, :returns => @new_resource.returns})
69
+ Chef::Log.debug("#{new_resource} installing MSI package '#{new_resource.source}'")
70
+ shell_out!("msiexec /qn /i \"#{new_resource.source}\" #{expand_options(new_resource.options)}", {:timeout => new_resource.timeout, :returns => new_resource.returns})
58
71
  end
59
72
 
60
- def remove_package(name, version)
73
+ def remove_package
61
74
  # We could use MsiConfigureProduct here, but we'll start off with msiexec
62
- Chef::Log.debug("#{@new_resource} removing MSI package '#{@new_resource.source}'")
63
- shell_out!("msiexec /qn /x \"#{@new_resource.source}\" #{expand_options(@new_resource.options)}", {:timeout => @new_resource.timeout, :returns => @new_resource.returns})
75
+ if ::File.exist?(new_resource.source)
76
+ Chef::Log.debug("#{new_resource} removing MSI package '#{new_resource.source}'")
77
+ shell_out!("msiexec /qn /x \"#{new_resource.source}\" #{expand_options(new_resource.options)}", {:timeout => new_resource.timeout, :returns => new_resource.returns})
78
+ else
79
+ uninstall_version = new_resource.version || installed_version
80
+ uninstall_entries.select { |entry| [uninstall_version].flatten.include?(entry.display_version) }
81
+ .map { |version| version.uninstall_string }.uniq.each do |uninstall_string|
82
+ Chef::Log.debug("#{new_resource} removing MSI package version using '#{uninstall_string}'")
83
+ uninstall_string += expand_options(new_resource.options)
84
+ uninstall_string += " /Q" unless uninstall_string =~ / \/Q\b/
85
+ shell_out!(uninstall_string, {:timeout => new_resource.timeout, :returns => new_resource.returns})
86
+ end
87
+ end
64
88
  end
65
89
  end
66
90
  end
@@ -0,0 +1,89 @@
1
+ #
2
+ # Author:: Seth Chisamore (<schisamo@chef.io>)
3
+ # Author:: Matt Wrock <matt@mattwrock.com>
4
+ # Copyright:: Copyright (c) 2011, 2015 Chef Software, Inc.
5
+ # License:: Apache License, Version 2.0
6
+ #
7
+ # Licensed under the Apache License, Version 2.0 (the "License");
8
+ # you may not use this file except in compliance with the License.
9
+ # You may obtain a copy of the License at
10
+ #
11
+ # http://www.apache.org/licenses/LICENSE-2.0
12
+ #
13
+ # Unless required by applicable law or agreed to in writing, software
14
+ # distributed under the License is distributed on an "AS IS" BASIS,
15
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16
+ # See the License for the specific language governing permissions and
17
+ # limitations under the License.
18
+ #
19
+
20
+ require 'win32/registry' if (RUBY_PLATFORM =~ /mswin|mingw32|windows/)
21
+
22
+ class Chef
23
+ class Provider
24
+ class Package
25
+ class Windows
26
+ class RegistryUninstallEntry
27
+
28
+ def self.find_entries(package_name)
29
+ Chef::Log.debug("Finding uninstall entries for #{package_name}")
30
+ entries = []
31
+ [
32
+ [::Win32::Registry::HKEY_LOCAL_MACHINE, (::Win32::Registry::Constants::KEY_READ | 0x0100)],
33
+ [::Win32::Registry::HKEY_LOCAL_MACHINE, (::Win32::Registry::Constants::KEY_READ | 0x0200)],
34
+ [::Win32::Registry::HKEY_CURRENT_USER]
35
+ ].each do |hkey|
36
+ desired = hkey.length > 1 ? hkey[1] : ::Win32::Registry::Constants::KEY_READ
37
+ begin
38
+ ::Win32::Registry.open(hkey[0], UNINSTALL_SUBKEY, desired) do |reg|
39
+ reg.each_key do |key, _wtime|
40
+ begin
41
+ entry = reg.open(key, desired)
42
+ display_name = read_registry_property(entry, 'DisplayName')
43
+ if display_name == package_name
44
+ entries.push(RegistryUninstallEntry.new(hkey, key, entry))
45
+ end
46
+ rescue ::Win32::Registry::Error => ex
47
+ Chef::Log.debug("Registry error opening key '#{key}' on node #{desired}: #{ex}")
48
+ end
49
+ end
50
+ end
51
+ rescue ::Win32::Registry::Error => ex
52
+ Chef::Log.debug("Registry error opening hive '#{hkey[0]}' :: #{desired}: #{ex}")
53
+ end
54
+ end
55
+ entries
56
+ end
57
+
58
+ def self.read_registry_property(data, property)
59
+ data[property]
60
+ rescue ::Win32::Registry::Error => ex
61
+ Chef::Log.debug("Failure to read property '#{property}'")
62
+ nil
63
+ end
64
+
65
+ def initialize(hive, key, registry_data)
66
+ Chef::Log.debug("Creating uninstall entry for #{hive}::#{key}")
67
+ @hive = hive
68
+ @key = key
69
+ @data = registry_data
70
+ @display_name = RegistryUninstallEntry.read_registry_property(registry_data, 'DisplayName')
71
+ @display_version = RegistryUninstallEntry.read_registry_property(registry_data, 'DisplayVersion')
72
+ @uninstall_string = RegistryUninstallEntry.read_registry_property(registry_data, 'UninstallString')
73
+ end
74
+
75
+ attr_reader :hive
76
+ attr_reader :key
77
+ attr_reader :display_name
78
+ attr_reader :display_version
79
+ attr_reader :uninstall_string
80
+ attr_reader :data
81
+
82
+ private
83
+
84
+ UNINSTALL_SUBKEY = 'Software\Microsoft\Windows\CurrentVersion\Uninstall'.freeze
85
+ end
86
+ end
87
+ end
88
+ end
89
+ end
@@ -785,19 +785,29 @@ class Chef
785
785
  def python_bin
786
786
  yum_executable = which(yum_binary)
787
787
  if yum_executable && shabang?(yum_executable)
788
- extract_interpreter(yum_executable)
788
+ shabang_or_fallback(extract_interpreter(yum_executable))
789
789
  else
790
790
  Chef::Log.warn("Yum executable not found or doesn't start with #!. Using default python.")
791
791
  "/usr/bin/python"
792
792
  end
793
793
  rescue StandardError => e
794
- Chef::Log.warn("An error occured attempting to determine correct python executable. Using default.")
794
+ Chef::Log.warn("An error occurred attempting to determine correct python executable. Using default.")
795
795
  Chef::Log.debug(e)
796
796
  "/usr/bin/python"
797
797
  end
798
798
 
799
799
  def extract_interpreter(file)
800
- ::File.open(file, 'r', &:readline)[2..-1].chomp
800
+ ::File.open(file, 'r', &:readline)[2..-1].strip
801
+ end
802
+
803
+ # dnf based systems have a yum shim that has /bin/bash as the interpreter. Don't use this.
804
+ def shabang_or_fallback(interpreter)
805
+ if interpreter == '/bin/bash'
806
+ Chef::Log.warn("Yum executable interpreter is /bin/bash. Falling back to default python.")
807
+ "/usr/bin/python"
808
+ else
809
+ interpreter
810
+ end
801
811
  end
802
812
 
803
813
  def shabang?(file)
@@ -199,6 +199,9 @@ elseif ( $LASTEXITCODE -ne $null -and $LASTEXITCODE -ne 0 )
199
199
  $exitstatus = $LASTEXITCODE
200
200
  }
201
201
 
202
+ # Print STDOUT for the script execution
203
+ Write-Output $chefscriptresult
204
+
202
205
  # If this script is launched with -File, the process exit
203
206
  # status of PowerShell.exe will be $exitstatus. If it was
204
207
  # launched with -Command, it will be 0 if $exitstatus was 0,
@@ -145,18 +145,51 @@ class Chef
145
145
  end
146
146
 
147
147
  def load_json_data
148
- Chef::FileCache.load("remote_file/#{sanitized_cache_file_basename}")
148
+ path = sanitized_cache_file_path(sanitized_cache_file_basename)
149
+ if Chef::FileCache.has_key?(path)
150
+ Chef::FileCache.load(path)
151
+ else
152
+ old_path = sanitized_cache_file_path(sanitized_cache_file_basename_md5)
153
+ if Chef::FileCache.has_key?(old_path)
154
+ # We found an old cache control data file. We started using sha256 instead of md5
155
+ # to name these. Upgrade the file to the new name.
156
+ Chef::Log.debug("Found old cache control data file at #{old_path}. Moving to #{path}.")
157
+ Chef::FileCache.load(old_path).tap do |data|
158
+ Chef::FileCache.store(path, data)
159
+ Chef::FileCache.delete(old_path)
160
+ end
161
+ else
162
+ raise Chef::Exceptions::FileNotFound
163
+ end
164
+ end
149
165
  end
150
166
 
151
- def sanitized_cache_file_basename
167
+ def sanitized_cache_file_path(basename)
168
+ "remote_file/#{basename}"
169
+ end
170
+
171
+ def scrubbed_uri
152
172
  # Scrub and truncate in accordance with the goals of keeping the name
153
173
  # human-readable but within the bounds of local file system
154
174
  # path length limits
155
- scrubbed_uri = uri.gsub(/\W/, '_')[0..63]
175
+ uri.gsub(/\W/, '_')[0..63]
176
+ end
177
+
178
+ def sanitized_cache_file_basename
179
+ uri_sha2 = Chef::Digester.instance.generate_checksum(StringIO.new(uri))
180
+ cache_file_basename(uri_sha2[0,32])
181
+ end
182
+
183
+
184
+ def sanitized_cache_file_basename_md5
185
+ # Old way of creating the file basename
156
186
  uri_md5 = Chef::Digester.instance.generate_md5_checksum(StringIO.new(uri))
157
- "#{scrubbed_uri}-#{uri_md5}.json"
187
+ cache_file_basename(uri_md5)
158
188
  end
159
189
 
190
+ def cache_file_basename(checksum)
191
+ "#{scrubbed_uri}-#{checksum}.json"
192
+ end
160
193
  end
161
194
  end
162
195
  end
@@ -105,7 +105,7 @@ class Chef
105
105
  # case you'd end up with a tar archive (no gzip) named, e.g., foo.tgz,
106
106
  # which is not what you wanted.
107
107
  if uri.to_s =~ /gz$/
108
- Chef::Log.debug("turning gzip compression off due to filename ending in gz")
108
+ Chef::Log.debug("Turning gzip compression off due to filename ending in gz")
109
109
  opts[:disable_gzip] = true
110
110
  end
111
111
  opts
@@ -27,6 +27,7 @@ class Chef
27
27
 
28
28
  provides :bash
29
29
  provides :csh
30
+ provides :ksh
30
31
  provides :perl
31
32
  provides :python
32
33
  provides :ruby
@@ -44,16 +44,19 @@ class Chef
44
44
  supports[:restart] = false if supports[:restart].nil?
45
45
  end
46
46
 
47
- def load_new_resource_state
48
- # If the user didn't specify a change in enabled state,
49
- # it will be the same as the old resource
50
- if ( @new_resource.enabled.nil? )
51
- @new_resource.enabled(@current_resource.enabled)
52
- end
53
- if ( @new_resource.running.nil? )
54
- @new_resource.running(@current_resource.running)
55
- end
56
- end
47
+ # the new_resource#enabled and #running variables are not user input, but when we
48
+ # do (e.g.) action_enable we want to set new_resource.enabled so that the comparison
49
+ # between desired and current state produces the correct change in reporting.
50
+ # XXX?: the #nil? check below will likely fail if this is a cloned resource or if
51
+ # we just run multiple actions.
52
+ def load_new_resource_state
53
+ if ( @new_resource.enabled.nil? )
54
+ @new_resource.enabled(@current_resource.enabled)
55
+ end
56
+ if ( @new_resource.running.nil? )
57
+ @new_resource.running(@current_resource.running)
58
+ end
59
+ end
57
60
 
58
61
  def shared_resource_requirements
59
62
  end
@@ -30,35 +30,39 @@ class Chef
30
30
 
31
31
  def initialize(new_resource, run_context=nil)
32
32
  super
33
- @init_command = "/usr/sbin/svcadm"
34
- @status_command = "/bin/svcs -l"
33
+ @init_command = "/usr/sbin/svcadm"
34
+ @status_command = "/bin/svcs"
35
35
  @maintenace = false
36
36
  end
37
37
 
38
38
  def load_current_resource
39
39
  @current_resource = Chef::Resource::Service.new(@new_resource.name)
40
40
  @current_resource.service_name(@new_resource.service_name)
41
- unless ::File.exists? "/bin/svcs"
42
- raise Chef::Exceptions::Service, "/bin/svcs does not exist!"
41
+
42
+ [@init_command, @status_command].each do |cmd|
43
+ unless ::File.executable? cmd then
44
+ raise Chef::Exceptions::Service, "#{cmd} not executable!"
45
+ end
43
46
  end
44
47
  @status = service_status.enabled
48
+
45
49
  @current_resource
46
50
  end
47
51
 
48
52
  def enable_service
49
- shell_out!("#{default_init_command} clear #{@new_resource.service_name}") if @maintenance
50
- shell_out!("#{default_init_command} enable -s #{@new_resource.service_name}")
53
+ shell_out!(default_init_command, "clear", @new_resource.service_name) if @maintenance
54
+ shell_out!(default_init_command, "enable", "-s", @new_resource.service_name)
51
55
  end
52
56
 
53
57
  def disable_service
54
- shell_out!("#{default_init_command} disable -s #{@new_resource.service_name}")
58
+ shell_out!(default_init_command, "disable", "-s", @new_resource.service_name)
55
59
  end
56
60
 
57
61
  alias_method :stop_service, :disable_service
58
62
  alias_method :start_service, :enable_service
59
63
 
60
64
  def reload_service
61
- shell_out_with_systems_locale!("#{default_init_command} refresh #{@new_resource.service_name}")
65
+ shell_out!(default_init_command, "refresh", @new_resource.service_name)
62
66
  end
63
67
 
64
68
  def restart_service
@@ -68,16 +72,38 @@ class Chef
68
72
  end
69
73
 
70
74
  def service_status
71
- status = shell_out!("#{@status_command} #{@current_resource.service_name}", :returns => [0, 1])
72
- status.stdout.each_line do |line|
73
- case line
74
- when /state\s+online/
75
- @current_resource.enabled(true)
76
- @current_resource.running(true)
77
- when /state\s+maintenance/
78
- @maintenance = true
79
- end
75
+ cmd = shell_out!(@status_command, "-l", @current_resource.service_name, :returns => [0, 1])
76
+ # Example output
77
+ # $ svcs -l rsyslog
78
+ # fmri svc:/application/rsyslog:default
79
+ # name rsyslog logging utility
80
+ # enabled true
81
+ # state online
82
+ # next_state none
83
+ # state_time April 2, 2015 04:25:19 PM EDT
84
+ # logfile /var/svc/log/application-rsyslog:default.log
85
+ # restarter svc:/system/svc/restarter:default
86
+ # contract_id 1115271
87
+ # dependency require_all/error svc:/milestone/multi-user:default (online)
88
+ # $
89
+
90
+ # load output into hash
91
+ status = {}
92
+ cmd.stdout.each_line do |line|
93
+ key, value = line.strip.split(/\s+/, 2)
94
+ status[key] = value
95
+ end
96
+
97
+ # check service state
98
+ @maintenance = false
99
+ case status['state']
100
+ when 'online'
101
+ @current_resource.enabled(true)
102
+ @current_resource.running(true)
103
+ when 'maintenance'
104
+ @maintenance = true
80
105
  end
106
+
81
107
  unless @current_resource.enabled
82
108
  @current_resource.enabled(false)
83
109
  @current_resource.running(false)