chef 12.1.2 → 12.2.0.rc.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (113) hide show
  1. checksums.yaml +7 -0
  2. data/lib/chef/application/client.rb +2 -2
  3. data/lib/chef/audit/audit_reporter.rb +1 -1
  4. data/lib/chef/audit/runner.rb +15 -2
  5. data/lib/chef/client.rb +1 -1
  6. data/lib/chef/config.rb +6 -4
  7. data/lib/chef/dsl/powershell.rb +29 -0
  8. data/lib/chef/exceptions.rb +18 -3
  9. data/lib/chef/formatters/doc.rb +2 -2
  10. data/lib/chef/knife/bootstrap.rb +2 -1
  11. data/lib/chef/knife/bootstrap/templates/chef-full.erb +1 -1
  12. data/lib/chef/knife/core/subcommand_loader.rb +13 -5
  13. data/lib/chef/knife/exec.rb +2 -1
  14. data/lib/chef/knife/ssh.rb +12 -2
  15. data/lib/chef/mixin/params_validate.rb +42 -19
  16. data/lib/chef/mixin/powershell_type_coercions.rb +82 -0
  17. data/lib/chef/mixin/windows_architecture_helper.rb +8 -0
  18. data/lib/chef/node.rb +1 -1
  19. data/lib/chef/platform/provider_mapping.rb +0 -107
  20. data/lib/chef/platform/query_helpers.rb +7 -0
  21. data/lib/chef/provider/batch.rb +2 -0
  22. data/lib/chef/provider/cron.rb +2 -0
  23. data/lib/chef/provider/cron/aix.rb +2 -0
  24. data/lib/chef/provider/cron/unix.rb +2 -0
  25. data/lib/chef/provider/deploy.rb +104 -87
  26. data/lib/chef/provider/dsc_resource.rb +157 -0
  27. data/lib/chef/provider/env.rb +2 -0
  28. data/lib/chef/provider/env/windows.rb +2 -0
  29. data/lib/chef/provider/git.rb +4 -0
  30. data/lib/chef/provider/group.rb +5 -5
  31. data/lib/chef/provider/group/dscl.rb +2 -0
  32. data/lib/chef/provider/group/groupmod.rb +2 -0
  33. data/lib/chef/provider/group/usermod.rb +2 -0
  34. data/lib/chef/provider/group/windows.rb +2 -0
  35. data/lib/chef/provider/mdadm.rb +2 -0
  36. data/lib/chef/provider/mount/windows.rb +2 -0
  37. data/lib/chef/provider/package/homebrew.rb +1 -1
  38. data/lib/chef/provider/package/openbsd.rb +49 -18
  39. data/lib/chef/provider/package/rubygems.rb +7 -2
  40. data/lib/chef/provider/powershell_script.rb +2 -0
  41. data/lib/chef/provider/service/macosx.rb +1 -2
  42. data/lib/chef/provider/user/dscl.rb +7 -1
  43. data/lib/chef/provider/user/windows.rb +2 -0
  44. data/lib/chef/providers.rb +1 -0
  45. data/lib/chef/recipe.rb +2 -0
  46. data/lib/chef/resource.rb +9 -0
  47. data/lib/chef/resource/batch.rb +2 -0
  48. data/lib/chef/resource/cron.rb +3 -3
  49. data/lib/chef/resource/deploy.rb +52 -217
  50. data/lib/chef/resource/dsc_resource.rb +83 -0
  51. data/lib/chef/resource/env.rb +2 -0
  52. data/lib/chef/resource/git.rb +1 -1
  53. data/lib/chef/resource/group.rb +2 -0
  54. data/lib/chef/resource/homebrew_package.rb +1 -1
  55. data/lib/chef/resource/lwrp_base.rb +0 -8
  56. data/lib/chef/resource/mdadm.rb +2 -0
  57. data/lib/chef/resource/mount.rb +2 -0
  58. data/lib/chef/resource/powershell_script.rb +2 -0
  59. data/lib/chef/resource/user.rb +2 -0
  60. data/lib/chef/resources.rb +1 -0
  61. data/lib/chef/run_context.rb +1 -1
  62. data/lib/chef/shell.rb +7 -5
  63. data/lib/chef/util/dsc/resource_store.rb +110 -0
  64. data/lib/chef/util/path_helper.rb +76 -0
  65. data/lib/chef/util/powershell/cmdlet.rb +41 -7
  66. data/lib/chef/util/powershell/cmdlet_result.rb +18 -3
  67. data/lib/chef/util/powershell/ps_credential.rb +38 -0
  68. data/lib/chef/version.rb +1 -1
  69. data/lib/chef/win32/api.rb +2 -0
  70. data/lib/chef/win32/api/crypto.rb +63 -0
  71. data/lib/chef/win32/api/installer.rb +1 -1
  72. data/lib/chef/win32/crypto.rb +49 -0
  73. data/lib/chef/workstation_config_loader.rb +4 -3
  74. data/spec/functional/file_content_management/deploy_strategies_spec.rb +1 -1
  75. data/spec/functional/resource/cookbook_file_spec.rb +1 -1
  76. data/spec/functional/resource/deploy_revision_spec.rb +35 -0
  77. data/spec/functional/resource/directory_spec.rb +1 -1
  78. data/spec/functional/resource/dsc_resource_spec.rb +93 -0
  79. data/spec/functional/resource/env_spec.rb +4 -3
  80. data/spec/functional/resource/file_spec.rb +1 -1
  81. data/spec/functional/resource/powershell_spec.rb +2 -1
  82. data/spec/functional/resource/remote_directory_spec.rb +1 -1
  83. data/spec/functional/resource/remote_file_spec.rb +1 -1
  84. data/spec/functional/resource/template_spec.rb +1 -1
  85. data/spec/functional/resource/user/dscl_spec.rb +1 -2
  86. data/spec/functional/resource/user/useradd_spec.rb +27 -13
  87. data/spec/functional/util/powershell/cmdlet_spec.rb +3 -3
  88. data/spec/functional/win32/crypto_spec.rb +57 -0
  89. data/spec/spec_helper.rb +3 -0
  90. data/spec/support/platform_helpers.rb +14 -0
  91. data/spec/support/shared/functional/securable_resource_with_reporting.rb +5 -5
  92. data/spec/unit/application/client_spec.rb +4 -4
  93. data/spec/unit/audit/audit_reporter_spec.rb +1 -1
  94. data/spec/unit/audit/runner_spec.rb +10 -0
  95. data/spec/unit/config_spec.rb +2 -8
  96. data/spec/unit/knife/bootstrap_spec.rb +20 -8
  97. data/spec/unit/knife/core/subcommand_loader_spec.rb +29 -29
  98. data/spec/unit/mixin/params_validate_spec.rb +75 -61
  99. data/spec/unit/mixin/powershell_type_coercions_spec.rb +72 -0
  100. data/spec/unit/platform/query_helpers_spec.rb +22 -0
  101. data/spec/unit/platform_spec.rb +0 -5
  102. data/spec/unit/provider/dsc_resource_spec.rb +84 -0
  103. data/spec/unit/provider/package/openbsd_spec.rb +105 -17
  104. data/spec/unit/provider/service/macosx_spec.rb +3 -3
  105. data/spec/unit/provider_resolver_spec.rb +132 -0
  106. data/spec/unit/recipe_spec.rb +4 -0
  107. data/spec/unit/resource/deploy_spec.rb +27 -0
  108. data/spec/unit/resource/dsc_resource_spec.rb +85 -0
  109. data/spec/unit/shell_spec.rb +1 -1
  110. data/spec/unit/util/dsc/resource_store.rb +76 -0
  111. data/spec/unit/util/powershell/ps_credential_spec.rb +37 -0
  112. data/spec/unit/workstation_config_loader_spec.rb +1 -1
  113. metadata +159 -186
@@ -0,0 +1,157 @@
1
+ #
2
+ # Author:: Adam Edwards (<adamed@getchef.com>)
3
+ #
4
+ # Copyright:: 2014, Chef Software, Inc.
5
+ #
6
+ # Licensed under the Apache License, Version 2.0 (the "License");
7
+ # you may not use this file except in compliance with the License.
8
+ # You may obtain a copy of the License at
9
+ #
10
+ # http://www.apache.org/licenses/LICENSE-2.0
11
+ #
12
+ # Unless required by applicable law or agreed to in writing, software
13
+ # distributed under the License is distributed on an "AS IS" BASIS,
14
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
+ # See the License for the specific language governing permissions and
16
+ # limitations under the License.
17
+ #
18
+
19
+ require 'chef/util/powershell/cmdlet'
20
+ require 'chef/util/dsc/local_configuration_manager'
21
+ require 'chef/mixin/powershell_type_coercions'
22
+ require 'chef/util/dsc/resource_store'
23
+
24
+ class Chef
25
+ class Provider
26
+ class DscResource < Chef::Provider
27
+ include Chef::Mixin::PowershellTypeCoercions
28
+
29
+ provides :dsc_resource, os: "windows"
30
+
31
+ def initialize(new_resource, run_context)
32
+ super
33
+ @new_resource = new_resource
34
+ @module_name = new_resource.module_name
35
+ end
36
+
37
+ def action_run
38
+ if ! test_resource
39
+ converge_by(generate_description) do
40
+ result = set_resource
41
+ end
42
+ end
43
+ end
44
+
45
+ def load_current_resource
46
+ end
47
+
48
+ def whyrun_supported?
49
+ true
50
+ end
51
+
52
+ def define_resource_requirements
53
+ requirements.assert(:run) do |a|
54
+ a.assertion { supports_dsc_invoke_resource? }
55
+ err = ["You must have Powershell version >= 5.0.10018.0 to use dsc_resource."]
56
+ a.failure_message Chef::Exceptions::NoProviderAvailable,
57
+ err
58
+ a.whyrun err + ["Assuming a previous resource installs Powershell 5.0.10018.0 or higher."]
59
+ a.block_action!
60
+ end
61
+ requirements.assert(:run) do |a|
62
+ a.assertion {
63
+ meta_configuration['RefreshMode'] == 'Disabled'
64
+ }
65
+ err = ["The LCM must have its RefreshMode set to Disabled. "]
66
+ a.failure_message Chef::Exceptions::NoProviderAvailable, err.join(' ')
67
+ a.whyrun err + ["Assuming a previous resource sets the RefreshMode."]
68
+ a.block_action!
69
+ end
70
+ end
71
+
72
+ protected
73
+
74
+ def local_configuration_manager
75
+ @local_configuration_manager ||= Chef::Util::DSC::LocalConfigurationManager.new(
76
+ node,
77
+ nil
78
+ )
79
+ end
80
+
81
+ def resource_store
82
+ Chef::Util::DSC::ResourceStore.instance
83
+ end
84
+
85
+ def supports_dsc_invoke_resource?
86
+ run_context && Chef::Platform.supports_dsc_invoke_resource?(node)
87
+ end
88
+
89
+ def generate_description
90
+ @converge_description
91
+ end
92
+
93
+ def dsc_resource_name
94
+ new_resource.resource.to_s
95
+ end
96
+
97
+ def module_name
98
+ @module_name ||= begin
99
+ found = resource_store.find(dsc_resource_name)
100
+
101
+ r = case found.length
102
+ when 0
103
+ raise Chef::Exceptions::ResourceNotFound,
104
+ "Could not find #{dsc_resource_name}. Check to make "\
105
+ "sure that it shows up when running Get-DscResource"
106
+ when 1
107
+ if found[0]['Module'].nil?
108
+ :none
109
+ else
110
+ found[0]['Module']
111
+ end
112
+ else
113
+ raise Chef::Exceptions::MultipleDscResourcesFound, found
114
+ end
115
+ end
116
+ end
117
+
118
+ def test_resource
119
+ result = invoke_resource(:test)
120
+ # We really want this information from the verbose stream,
121
+ # however Invoke-DscResource is not correctly writing to that
122
+ # stream and instead just dumping to stdout
123
+ @converge_description = result.stdout
124
+ result.return_value[0]["InDesiredState"]
125
+ end
126
+
127
+ def set_resource
128
+ result = invoke_resource(:set)
129
+ result.return_value
130
+ end
131
+
132
+ def invoke_resource(method, output_format=:object)
133
+ properties = translate_type(@new_resource.properties)
134
+ switches = "-Method #{method.to_s} -Name #{@new_resource.resource}"\
135
+ " -Property #{properties} -Verbose"
136
+
137
+ if module_name != :none
138
+ switches += " -Module #{module_name}"
139
+ end
140
+
141
+ cmdlet = Chef::Util::Powershell::Cmdlet.new(
142
+ node,
143
+ "Invoke-DscResource #{switches}",
144
+ output_format
145
+ )
146
+ cmdlet.run!
147
+ end
148
+
149
+ def meta_configuration
150
+ cmdlet = Chef::Util::Powershell::Cmdlet.new(node, "Get-DscLocalConfigurationManager", :object)
151
+ result = cmdlet.run!
152
+ result.return_value
153
+ end
154
+
155
+ end
156
+ end
157
+ end
@@ -26,6 +26,8 @@ class Chef
26
26
  include Chef::Mixin::Command
27
27
  attr_accessor :key_exists
28
28
 
29
+ provides :env, os: "!windows"
30
+
29
31
  def initialize(new_resource, run_context)
30
32
  super
31
33
  @key_exists = true
@@ -24,6 +24,8 @@ class Chef
24
24
  class Windows < Chef::Provider::Env
25
25
  include Chef::Mixin::WindowsEnvHelper
26
26
 
27
+ provides :env, os: "windows"
28
+
27
29
  def create_env
28
30
  obj = env_obj(@new_resource.key_name)
29
31
  unless obj
@@ -39,6 +39,10 @@ class Chef
39
39
  end
40
40
  end
41
41
 
42
+ def additional_remotes
43
+ new_resource.additional_remotes || {}
44
+ end
45
+
42
46
  def define_resource_requirements
43
47
  # Parent directory of the target must exist.
44
48
  requirements.assert(:checkout, :sync) do |a|
@@ -125,13 +125,13 @@ class Chef
125
125
  def action_create
126
126
  case @group_exists
127
127
  when false
128
- converge_by("create #{@new_resource}") do
128
+ converge_by("create #{@new_resource.group_name}") do
129
129
  create_group
130
130
  Chef::Log.info("#{@new_resource} created")
131
131
  end
132
132
  else
133
133
  if compare_group
134
- converge_by(["alter group #{@new_resource}"] + change_desc) do
134
+ converge_by(["alter group #{@new_resource.group_name}"] + change_desc) do
135
135
  manage_group
136
136
  Chef::Log.info("#{@new_resource} altered")
137
137
  end
@@ -141,7 +141,7 @@ class Chef
141
141
 
142
142
  def action_remove
143
143
  if @group_exists
144
- converge_by("remove group #{@new_resource}") do
144
+ converge_by("remove group #{@new_resource.group_name}") do
145
145
  remove_group
146
146
  Chef::Log.info("#{@new_resource} removed")
147
147
  end
@@ -150,7 +150,7 @@ class Chef
150
150
 
151
151
  def action_manage
152
152
  if @group_exists && compare_group
153
- converge_by(["manage group #{@new_resource}"] + change_desc) do
153
+ converge_by(["manage group #{@new_resource.group_name}"] + change_desc) do
154
154
  manage_group
155
155
  Chef::Log.info("#{@new_resource} managed")
156
156
  end
@@ -159,7 +159,7 @@ class Chef
159
159
 
160
160
  def action_modify
161
161
  if compare_group
162
- converge_by(["modify group #{@new_resource}"] + change_desc) do
162
+ converge_by(["modify group #{@new_resource.group_name}"] + change_desc) do
163
163
  manage_group
164
164
  Chef::Log.info("#{@new_resource} modified")
165
165
  end
@@ -21,6 +21,8 @@ class Chef
21
21
  class Group
22
22
  class Dscl < Chef::Provider::Group
23
23
 
24
+ provides :group, os: "darwin"
25
+
24
26
  def dscl(*args)
25
27
  host = "."
26
28
  stdout_result = ""; stderr_result = ""; cmd = "dscl #{host} -#{args.join(' ')}"
@@ -21,6 +21,8 @@ class Chef
21
21
  class Group
22
22
  class Groupmod < Chef::Provider::Group
23
23
 
24
+ provides :group, os: "netbsd"
25
+
24
26
  def load_current_resource
25
27
  super
26
28
  [ "group", "user" ].each do |binary|
@@ -23,6 +23,8 @@ class Chef
23
23
  class Group
24
24
  class Usermod < Chef::Provider::Group::Groupadd
25
25
 
26
+ provides :group, os: "openbsd"
27
+
26
28
  def load_current_resource
27
29
  super
28
30
  end
@@ -26,6 +26,8 @@ class Chef
26
26
  class Group
27
27
  class Windows < Chef::Provider::Group
28
28
 
29
+ provides :group, os: "windows"
30
+
29
31
  def initialize(new_resource,run_context)
30
32
  super
31
33
  @net_group = Chef::Util::Windows::NetGroup.new(@new_resource.group_name)
@@ -23,6 +23,8 @@ class Chef
23
23
  class Provider
24
24
  class Mdadm < Chef::Provider
25
25
 
26
+ provides :mdadm
27
+
26
28
  def popen4
27
29
  raise Exception, "deprecated"
28
30
  end
@@ -27,6 +27,8 @@ class Chef
27
27
  class Mount
28
28
  class Windows < Chef::Provider::Mount
29
29
 
30
+ provides :mount, os: "windows"
31
+
30
32
  def is_volume(name)
31
33
  name =~ /^\\\\\?\\Volume\{[\w-]+\}\\$/ ? true : false
32
34
  end
@@ -27,7 +27,7 @@ class Chef
27
27
  class Homebrew < Chef::Provider::Package
28
28
 
29
29
  provides :homebrew_package
30
- provides :package, os: ["mac_os_x", "darwin"]
30
+ provides :package, os: "darwin"
31
31
 
32
32
  include Chef::Mixin::HomebrewUser
33
33
 
@@ -24,6 +24,7 @@ require 'chef/resource/package'
24
24
  require 'chef/provider/package'
25
25
  require 'chef/mixin/shell_out'
26
26
  require 'chef/mixin/get_source_from_package'
27
+ require 'chef/exceptions'
27
28
 
28
29
  class Chef
29
30
  class Provider
@@ -37,25 +38,42 @@ class Chef
37
38
 
38
39
  def initialize(*args)
39
40
  super
40
- @current_resource = Chef::Resource::Package.new(@new_resource.name)
41
- @new_resource.source(pkg_path) if !@new_resource.source
41
+ @current_resource = Chef::Resource::Package.new(new_resource.name)
42
42
  end
43
43
 
44
44
  def load_current_resource
45
- @current_resource.package_name(@new_resource.package_name)
45
+ @current_resource.package_name(new_resource.package_name)
46
46
  @current_resource.version(installed_version)
47
47
  @current_resource
48
48
  end
49
49
 
50
+ def define_resource_requirements
51
+ super
52
+
53
+ # Below are incomplete/missing features for this package provider
54
+ requirements.assert(:all_actions) do |a|
55
+ a.assertion { !new_resource.source }
56
+ a.failure_message(Chef::Exceptions::Package, 'The openbsd package provider does not support the source attribute')
57
+ end
58
+ requirements.assert(:all_actions) do |a|
59
+ a.assertion do
60
+ if new_resource.package_name =~ /^(.+?)--(.+)/
61
+ !new_resource.version
62
+ else
63
+ true
64
+ end
65
+ end
66
+ a.failure_message(Chef::Exceptions::Package, 'The openbsd package provider does not support providing a version and flavor')
67
+ end
68
+ end
69
+
50
70
  def install_package(name, version)
51
71
  unless @current_resource.version
52
- version_string = ''
53
- version_string += "-#{version}" if version
54
72
  if parts = name.match(/^(.+?)--(.+)/) # use double-dash for stems with flavors, see man page for pkg_add
55
73
  name = parts[1]
56
74
  end
57
- shell_out!("pkg_add -r #{name}#{version_string}", :env => {"PKG_PATH" => @new_resource.source}).status
58
- Chef::Log.debug("#{@new_resource} installed from: #{@new_resource.source}")
75
+ shell_out!("pkg_add -r #{name}#{version_string}", :env => {"PKG_PATH" => pkg_path}).status
76
+ Chef::Log.debug("#{new_resource.package_name} installed")
59
77
  end
60
78
  end
61
79
 
@@ -71,32 +89,45 @@ class Chef
71
89
  private
72
90
 
73
91
  def installed_version
74
- if parts = @new_resource.package_name.match(/^(.+?)--(.+)/)
92
+ if parts = new_resource.package_name.match(/^(.+?)--(.+)/)
75
93
  name = parts[1]
76
94
  else
77
- name = @new_resource.package_name
95
+ name = new_resource.package_name
78
96
  end
79
97
  pkg_info = shell_out!("pkg_info -e \"#{name}->0\"", :env => nil, :returns => [0,1])
80
98
  result = pkg_info.stdout[/^inst:#{Regexp.escape(name)}-(.+?)\s/, 1]
81
- Chef::Log.debug("installed_version of '#{@new_resource.package_name}' is '#{result}'")
99
+ Chef::Log.debug("installed_version of '#{new_resource.package_name}' is '#{result}'")
82
100
  result
83
101
  end
84
102
 
85
103
  def candidate_version
86
104
  @candidate_version ||= begin
87
- version_string = ''
88
- version_string += "-#{version}" if @new_resource.version
89
- pkg_info = shell_out!("pkg_info -I \"#{@new_resource.package_name}#{version_string}\"", :env => nil, :returns => [0,1])
90
- if parts = @new_resource.package_name.match(/^(.+?)--(.+)/)
91
- result = pkg_info.stdout[/^#{Regexp.escape(parts[1])}-(.+?)\s/, 1]
105
+ results = []
106
+ shell_out!("pkg_info -I \"#{new_resource.package_name}#{version_string}\"", :env => nil, :returns => [0,1]).stdout.each_line do |line|
107
+ if parts = new_resource.package_name.match(/^(.+?)--(.+)/)
108
+ results << line[/^#{Regexp.escape(parts[1])}-(.+?)\s/, 1]
109
+ else
110
+ results << line[/^#{Regexp.escape(new_resource.package_name)}-(.+?)\s/, 1]
111
+ end
112
+ end
113
+ results = results.reject(&:nil?)
114
+ Chef::Log.debug("candidate versions of '#{new_resource.package_name}' are '#{results}'")
115
+ case results.length
116
+ when 0
117
+ []
118
+ when 1
119
+ results[0]
92
120
  else
93
- result = pkg_info.stdout[/^#{Regexp.escape(@new_resource.package_name)}-(.+?)\s/, 1]
121
+ raise Chef::Exceptions::Package, "#{new_resource.name} has multiple matching candidates. Please use a more specific name" if results.length > 1
94
122
  end
95
- Chef::Log.debug("candidate_version of '#{@new_resource.package_name}' is '#{result}'")
96
- result
97
123
  end
98
124
  end
99
125
 
126
+ def version_string
127
+ ver = ''
128
+ ver += "-#{new_resource.version}" if new_resource.version
129
+ end
130
+
100
131
  def pkg_path
101
132
  ENV['PKG_PATH'] || "http://ftp.OpenBSD.org/pub/#{node.kernel.name}/#{node.kernel.release}/packages/#{node.kernel.machine}/"
102
133
  end
@@ -380,8 +380,13 @@ class Chef
380
380
  # Opscode Omnibus - The ruby that ships inside omnibus is only used for Chef
381
381
  # Default to installing somewhere more functional
382
382
  if new_resource.options && new_resource.options.kind_of?(Hash)
383
- msg = "options should be a string instead of a hash\n"
384
- msg << "in #{new_resource} from #{new_resource.source_line}"
383
+ msg = [
384
+ "Gem options must be passed to gem_package as a string instead of a hash when",
385
+ "using this installation of Chef because it runs with its own packaged Ruby. A hash",
386
+ "may only be used when installing a gem to the same Ruby installation that Chef is",
387
+ "running under. See https://docs.chef.io/resource_gem_package.html for more information.",
388
+ "Error raised at #{new_resource} from #{new_resource.source_line}",
389
+ ].join("\n")
385
390
  raise ArgumentError, msg
386
391
  end
387
392
  gem_location = find_gem_by_path
@@ -22,6 +22,8 @@ class Chef
22
22
  class Provider
23
23
  class PowershellScript < Chef::Provider::WindowsScript
24
24
 
25
+ provides :powershell_script, os: "windows"
26
+
25
27
  protected
26
28
  EXIT_STATUS_EXCEPTION_HANDLER = "\ntrap [Exception] {write-error -exception ($_.Exception.Message);exit 1}".freeze
27
29
  EXIT_STATUS_NORMALIZATION_SCRIPT = "\nif ($? -ne $true) { if ( $LASTEXITCODE ) {exit $LASTEXITCODE} else { exit 1 }}".freeze
@@ -33,8 +33,7 @@ class Chef
33
33
  /Library/LaunchDaemons
34
34
  /System/Library/LaunchAgents
35
35
  /System/Library/LaunchDaemons }
36
-
37
- locations << "#{ENV['HOME']}/Library/LaunchAgents" if ENV['HOME']
36
+ Chef::Util::PathHelper.home('Library', 'LaunchAgents') { |p| locations << p }
38
37
  locations
39
38
  end
40
39