chef 12.0.0.rc.0 → 12.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (60) hide show
  1. checksums.yaml +7 -0
  2. data/README.md +1 -1
  3. data/lib/chef/api_client/registration.rb +3 -1
  4. data/lib/chef/chef_fs/data_handler/group_data_handler.rb +4 -0
  5. data/lib/chef/config.rb +46 -38
  6. data/lib/chef/event_loggers/windows_eventlog.rb +5 -6
  7. data/lib/chef/exceptions.rb +13 -1
  8. data/lib/chef/file_content_management/tempfile.rb +33 -5
  9. data/lib/chef/knife.rb +11 -3
  10. data/lib/chef/knife/bootstrap.rb +8 -7
  11. data/lib/chef/mixin/deep_merge.rb +15 -54
  12. data/lib/chef/mixin/which.rb +37 -0
  13. data/lib/chef/node.rb +14 -25
  14. data/lib/chef/node/attribute.rb +227 -41
  15. data/lib/chef/node/attribute_collections.rb +117 -3
  16. data/lib/chef/node/immutable_collections.rb +6 -6
  17. data/lib/chef/platform/provider_priority_map.rb +3 -2
  18. data/lib/chef/platform/service_helpers.rb +37 -8
  19. data/lib/chef/provider/service/aixinit.rb +1 -1
  20. data/lib/chef/provider/service/arch.rb +1 -1
  21. data/lib/chef/provider/service/debian.rb +5 -1
  22. data/lib/chef/provider/service/init.rb +4 -0
  23. data/lib/chef/provider/service/insserv.rb +5 -1
  24. data/lib/chef/provider/service/invokercd.rb +5 -1
  25. data/lib/chef/provider/service/redhat.rb +5 -1
  26. data/lib/chef/provider/service/systemd.rb +50 -32
  27. data/lib/chef/provider/service/upstart.rb +5 -2
  28. data/lib/chef/provider_resolver.rb +30 -16
  29. data/lib/chef/resource.rb +2 -1
  30. data/lib/chef/resources.rb +7 -0
  31. data/lib/chef/run_context.rb +0 -5
  32. data/lib/chef/run_list/run_list_expansion.rb +2 -2
  33. data/lib/chef/shell.rb +2 -2
  34. data/lib/chef/util/selinux.rb +2 -10
  35. data/lib/chef/version.rb +1 -1
  36. data/lib/chef/workstation_config_loader.rb +1 -1
  37. data/spec/support/shared/unit/resource/static_provider_resolution.rb +1 -6
  38. data/spec/unit/api_client/registration_spec.rb +22 -0
  39. data/spec/unit/application/knife_spec.rb +6 -2
  40. data/spec/unit/chef_fs/data_handler/group_handler_spec.rb +63 -0
  41. data/spec/unit/config_spec.rb +5 -5
  42. data/spec/unit/knife/bootstrap_spec.rb +27 -1
  43. data/spec/unit/knife_spec.rb +5 -0
  44. data/spec/unit/mixin/deep_merge_spec.rb +0 -40
  45. data/spec/unit/node/attribute_spec.rb +37 -50
  46. data/spec/unit/node_spec.rb +321 -13
  47. data/spec/unit/provider/file/content_spec.rb +23 -2
  48. data/spec/unit/provider/service/systemd_service_spec.rb +173 -158
  49. data/spec/unit/provider_resolver_spec.rb +175 -10
  50. data/spec/unit/resource/timestamped_deploy_spec.rb +8 -29
  51. data/spec/unit/runner_spec.rb +3 -1
  52. metadata +141 -191
  53. data/spec/.DS_Store +0 -0
  54. data/spec/data/.DS_Store +0 -0
  55. data/spec/data/lwrp/.DS_Store +0 -0
  56. data/spec/data/lwrp/providers/.DS_Store +0 -0
  57. data/spec/data/lwrp/resources/.DS_Store +0 -0
  58. data/spec/data/lwrp_override/.DS_Store +0 -0
  59. data/spec/data/lwrp_override/providers/.DS_Store +0 -0
  60. data/spec/data/lwrp_override/resources/.DS_Store +0 -0
@@ -63,7 +63,7 @@ class Chef
63
63
  MUTATOR_METHODS.each do |mutator|
64
64
  class_eval(<<-METHOD_DEFN, __FILE__, __LINE__)
65
65
  def #{mutator}(*args, &block)
66
- root.reset_cache
66
+ root.reset_cache(root.top_level_breadcrumb)
67
67
  super
68
68
  end
69
69
  METHOD_DEFN
@@ -128,7 +128,7 @@ class Chef
128
128
  MUTATOR_METHODS.each do |mutator|
129
129
  class_eval(<<-METHOD_DEFN, __FILE__, __LINE__)
130
130
  def #{mutator}(*args, &block)
131
- root.reset_cache
131
+ root.reset_cache(root.top_level_breadcrumb)
132
132
  super
133
133
  end
134
134
  METHOD_DEFN
@@ -140,6 +140,7 @@ class Chef
140
140
  end
141
141
 
142
142
  def [](key)
143
+ root.top_level_breadcrumb ||= key
143
144
  value = super
144
145
  if !key?(key)
145
146
  value = self.class.new(root)
@@ -150,10 +151,11 @@ class Chef
150
151
  end
151
152
 
152
153
  def []=(key, value)
154
+ root.top_level_breadcrumb ||= key
153
155
  if set_unless? && key?(key)
154
156
  self[key]
155
157
  else
156
- root.reset_cache
158
+ root.reset_cache(root.top_level_breadcrumb)
157
159
  super
158
160
  end
159
161
  end
@@ -209,5 +211,117 @@ class Chef
209
211
 
210
212
  end
211
213
 
214
+ # == MultiMash
215
+ # This is a Hash-like object that contains multiple VividMashes in it. Its
216
+ # purpose is so that the user can descend into the mash and delete a subtree
217
+ # from all of the Mash objects (used to delete all values in a subtree from
218
+ # default, force_default, role_default and env_default at the same time). The
219
+ # assignment operator strictly does assignment (does no merging) and works
220
+ # by deleting the subtree and then assigning to the last mash which passed in
221
+ # the initializer.
222
+ #
223
+ # A lot of the complexity of this class comes from the fact that at any key
224
+ # value some or all of the mashes may walk off their ends and become nil or
225
+ # true or something. The schema may change so that one precidence leve may
226
+ # be 'true' object and another may be a VividMash. It is also possible that
227
+ # one or many of them may transition from VividMashes to Hashes or Arrays.
228
+ #
229
+ # It also supports the case where you may be deleting a key using node.rm
230
+ # in which case if intermediate keys all walk off into nil then you don't want
231
+ # to be autovivifying keys as you go. On the other hand you may be using
232
+ # node.force_default! in which case you'll wind up with a []= operator at the
233
+ # end and you want autovivification, so we conditionally have to support either
234
+ # operation.
235
+ #
236
+ # @todo: can we have an autovivify class that decorates a class that doesn't
237
+ # autovivify or something so that the code is less awful?
238
+ #
239
+ class MultiMash
240
+ attr_reader :root
241
+ attr_reader :mashes
242
+ attr_reader :opts
243
+ attr_reader :primary_mash
244
+
245
+ # Initialize with an array of mashes. For the delete return value to work
246
+ # properly the mashes must come from the same attribute level (i.e. all
247
+ # override or all default, but not a mix of both).
248
+ def initialize(root, primary_mash, mashes, opts={})
249
+ @root = root
250
+ @primary_mash = primary_mash
251
+ @mashes = mashes
252
+ @opts = opts
253
+ @opts[:autovivify] = true if @opts[:autovivify].nil?
254
+ end
255
+
256
+ def [](key)
257
+ # handle the secondary mashes
258
+ new_mashes = []
259
+ mashes.each do |mash|
260
+ new_mash = safe_evalute_key(mash, key)
261
+ # secondary mashes never autovivify so once they fall into nil, we just stop tracking them
262
+ new_mashes.push(new_mash) unless new_mash.nil?
263
+ end
264
+
265
+ new_primary_mash = safe_evalute_key(primary_mash, key)
266
+
267
+ if new_primary_mash.nil? && @opts[:autovivify]
268
+ primary_mash[key] = VividMash.new(root)
269
+ new_primary_mash = primary_mash[key]
270
+ end
271
+
272
+ MultiMash.new(root, new_primary_mash, new_mashes, opts)
273
+ end
274
+
275
+ def []=(key, value)
276
+ if primary_mash.nil?
277
+ # This theoretically should never happen since node#force_default! setter methods will autovivify and
278
+ # node#rm methods do not end in #[]= operators.
279
+ raise TypeError, "No autovivification was specified initially on a method chain ending in assignment"
280
+ end
281
+ ret = delete(key)
282
+ primary_mash[key] = value
283
+ ret
284
+ end
285
+
286
+ # mash.element('foo', 'bar') is the same as mash['foo']['bar']
287
+ def element(key = nil, *subkeys)
288
+ return self if key.nil?
289
+ submash = self[key]
290
+ subkeys.empty? ? submash : submash.element(*subkeys)
291
+ end
292
+
293
+ def delete(key)
294
+ # the return value is a deep merge which is correct semantics when
295
+ # merging between attributes on the same level (this would be incorrect
296
+ # if passed both override and default attributes which would need hash_only
297
+ # merging).
298
+ ret = mashes.inject(Mash.new) do |merged, mash|
299
+ Chef::Mixin::DeepMerge.merge(merged, mash)
300
+ end
301
+ ret = Chef::Mixin::DeepMerge.merge(ret, primary_mash)
302
+ mashes.each do |mash|
303
+ mash.delete(key) if mash.respond_to?(:delete)
304
+ end
305
+ primary_mash.delete(key) if primary_mash.respond_to?(:delete)
306
+ ret[key]
307
+ end
308
+
309
+ private
310
+
311
+ def safe_evalute_key(mash, key)
312
+ if mash.respond_to?(:[])
313
+ if mash.respond_to?(:has_key?)
314
+ if mash.has_key?(key)
315
+ return mash[key] if mash[key].respond_to?(:[])
316
+ end
317
+ elsif !mash[key].nil?
318
+ return mash[key] if mash[key].respond_to?(:[])
319
+ end
320
+ end
321
+ return nil
322
+ end
323
+
324
+ end
325
+
212
326
  end
213
327
  end
@@ -78,9 +78,7 @@ class Chef
78
78
  # Ruby 1.8 blocks can't have block arguments, so we must use string eval:
79
79
  class_eval(<<-METHOD_DEFN, __FILE__, __LINE__)
80
80
  def #{mutator_method_name}(*args, &block)
81
- msg = "Node attributes are read-only when you do not specify which precedence level to set. " +
82
- %Q(To set an attribute use code like `node.default["key"] = "value"')
83
- raise Exceptions::ImmutableAttributeModification, msg
81
+ raise Exceptions::ImmutableAttributeModification
84
82
  end
85
83
  METHOD_DEFN
86
84
  end
@@ -157,6 +155,10 @@ class Chef
157
155
  end
158
156
  end
159
157
 
158
+ def public_method_that_only_deep_merge_should_use(key, value)
159
+ internal_set(key, immutablize(value))
160
+ end
161
+
160
162
  alias :attribute? :has_key?
161
163
 
162
164
  # Redefine all of the methods that mutate a Hash to raise an error when called.
@@ -165,9 +167,7 @@ class Chef
165
167
  # Ruby 1.8 blocks can't have block arguments, so we must use string eval:
166
168
  class_eval(<<-METHOD_DEFN, __FILE__, __LINE__)
167
169
  def #{mutator_method_name}(*args, &block)
168
- msg = "Node attributes are read-only when you do not specify which precedence level to set. " +
169
- %Q(To set an attribute use code like `node.default["key"] = "value"')
170
- raise Exceptions::ImmutableAttributeModification, msg
170
+ raise Exceptions::ImmutableAttributeModification
171
171
  end
172
172
  METHOD_DEFN
173
173
  end
@@ -34,9 +34,10 @@ class Chef
34
34
  ], platform_family: "gentoo"
35
35
 
36
36
  priority :service, [
37
- # on debian-ish system if an upstart script exists that always wins
38
- Chef::Provider::Service::Upstart,
37
+ # we can determine what systemd supports accurately
39
38
  Chef::Provider::Service::Systemd,
39
+ # on debian-ish system if an upstart script exists that must win over sysv types
40
+ Chef::Provider::Service::Upstart,
40
41
  Chef::Provider::Service::Insserv,
41
42
  Chef::Provider::Service::Debian,
42
43
  Chef::Provider::Service::Invokercd,
@@ -18,6 +18,7 @@
18
18
 
19
19
  # XXX: mixing shellout into a mixin into classes has to be code smell
20
20
  require 'chef/mixin/shell_out'
21
+ require 'chef/mixin/which'
21
22
 
22
23
  class Chef
23
24
  class Platform
@@ -25,12 +26,21 @@ class Chef
25
26
  class << self
26
27
 
27
28
  include Chef::Mixin::ShellOut
29
+ include Chef::Mixin::Which
28
30
 
29
31
  # This helper is mostly used to sort out the mess of different
30
32
  # linux mechanisms that can be used to start services. It does
31
33
  # not necessarily need to linux-specific, but currently all our
32
34
  # other service providers are narrowly platform-specific with no
33
35
  # alternatives.
36
+ #
37
+ # NOTE: if a system has (for example) chkconfig installed then we
38
+ # should report that chkconfig is installed. The fact that a system
39
+ # may also have systemd installed does not mean that we do not
40
+ # report that systemd is also installed. This module is purely for
41
+ # discovery of all the alternatives, handling the priority of the
42
+ # different services is NOT a design concern of this module.
43
+ #
34
44
  def service_resource_providers
35
45
  service_resource_providers = []
36
46
 
@@ -55,8 +65,7 @@ class Chef
55
65
  service_resource_providers << :redhat
56
66
  end
57
67
 
58
- if ::File.exist?("/bin/systemctl")
59
- # FIXME: look for systemd as init provider
68
+ if systemd_sanity_check?
60
69
  service_resource_providers << :systemd
61
70
  end
62
71
 
@@ -86,7 +95,7 @@ class Chef
86
95
  configs << :usr_local_etc_rcd
87
96
  end
88
97
 
89
- if ::File.exist?("/bin/systemctl") && platform_has_systemd_unit?(service_name)
98
+ if systemd_sanity_check? && platform_has_systemd_unit?(service_name)
90
99
  configs << :systemd
91
100
  end
92
101
 
@@ -95,17 +104,37 @@ class Chef
95
104
 
96
105
  private
97
106
 
98
- def extract_systemd_services(output)
107
+ def systemctl_path
108
+ if @systemctl_path.nil?
109
+ @systemctl_path = which("systemctl")
110
+ end
111
+ @systemctl_path
112
+ end
113
+
114
+ def systemd_sanity_check?
115
+ systemctl_path && File.exist?("/proc/1/comm") && File.open("/proc/1/comm").gets.chomp == "systemd"
116
+ end
117
+
118
+ def extract_systemd_services(command)
119
+ output = shell_out!(command).stdout
99
120
  # first line finds e.g. "sshd.service"
100
- services = output.lines.split.map { |l| l.split[0] }
121
+ services = []
122
+ output.each_line do |line|
123
+ fields = line.split
124
+ services << fields[0] if fields[1] == "loaded" || fields[1] == "not-found"
125
+ end
101
126
  # this splits off the suffix after the last dot to return "sshd"
102
- services += services.map { |s| s.sub(/(.*)\..*/, '\1') }
127
+ services += services.select {|s| s.match(/\.service$/) }.map { |s| s.sub(/(.*)\.service$/, '\1') }
128
+ rescue Mixlib::ShellOut::ShellCommandFailed
129
+ false
103
130
  end
104
131
 
105
132
  def platform_has_systemd_unit?(service_name)
106
- services = extract_systemd_services(shell_out!("systemctl --all").stdout) +
107
- extract_systemd_services(shell_out!("systemctl --list-unit-files").stdout)
133
+ services = extract_systemd_services("#{systemctl_path} --all") +
134
+ extract_systemd_services("#{systemctl_path} list-unit-files")
108
135
  services.include?(service_name)
136
+ rescue Mixlib::ShellOut::ShellCommandFailed
137
+ false
109
138
  end
110
139
  end
111
140
  end
@@ -114,4 +114,4 @@ class Chef
114
114
  end
115
115
  end
116
116
  end
117
- end
117
+ end
@@ -23,7 +23,7 @@ class Chef::Provider::Service::Arch < Chef::Provider::Service::Init
23
23
  provides :service, platform_family: "arch"
24
24
 
25
25
  def self.supports?(resource, action)
26
- ::File.exist?("/etc/rc.d/#{resource.service_name}")
26
+ Chef::Platform::ServiceHelpers.config_for_service(resource.service_name).include?(:etc_rcd)
27
27
  end
28
28
 
29
29
  def initialize(new_resource, run_context)
@@ -27,8 +27,12 @@ class Chef
27
27
 
28
28
  provides :service, platform_family: "debian"
29
29
 
30
+ def self.provides?(node, resource)
31
+ super && Chef::Platform::ServiceHelpers.service_resource_providers.include?(:debian)
32
+ end
33
+
30
34
  def self.supports?(resource, action)
31
- Chef::Platform::ServiceHelpers.service_resource_providers.include?(:debian)
35
+ Chef::Platform::ServiceHelpers.config_for_service(resource.service_name).include?(:initd)
32
36
  end
33
37
 
34
38
  def load_current_resource
@@ -28,6 +28,10 @@ class Chef
28
28
 
29
29
  provides :service, os: "!windows"
30
30
 
31
+ def self.supports?(resource, action)
32
+ Chef::Platform::ServiceHelpers.config_for_service(resource.service_name).include?(:initd)
33
+ end
34
+
31
35
  def initialize(new_resource, run_context)
32
36
  super
33
37
  @init_command = "/etc/init.d/#{@new_resource.service_name}"
@@ -26,8 +26,12 @@ class Chef
26
26
 
27
27
  provides :service, os: "linux"
28
28
 
29
+ def self.provides?(node, resource)
30
+ super && Chef::Platform::ServiceHelpers.service_resource_providers.include?(:insserv)
31
+ end
32
+
29
33
  def self.supports?(resource, action)
30
- Chef::Platform::ServiceHelpers.service_resource_providers.include?(:insserv)
34
+ Chef::Platform::ServiceHelpers.config_for_service(resource.service_name).include?(:initd)
31
35
  end
32
36
 
33
37
  def load_current_resource
@@ -25,8 +25,12 @@ class Chef
25
25
 
26
26
  provides :service, platform_family: "debian"
27
27
 
28
+ def self.provides?(node, resource)
29
+ super && Chef::Platform::ServiceHelpers.service_resource_providers.include?(:invokercd)
30
+ end
31
+
28
32
  def self.supports?(resource, action)
29
- Chef::Platform::ServiceHelpers.service_resource_providers.include?(:invokerc)
33
+ Chef::Platform::ServiceHelpers.config_for_service(resource.service_name).include?(:initd)
30
34
  end
31
35
 
32
36
  def initialize(new_resource, run_context)
@@ -28,8 +28,12 @@ class Chef
28
28
 
29
29
  provides :service, platform_family: [ "rhel", "fedora", "suse" ]
30
30
 
31
+ def self.provides?(node, resource)
32
+ super && Chef::Platform::ServiceHelpers.service_resource_providers.include?(:redhat)
33
+ end
34
+
31
35
  def self.supports?(resource, action)
32
- Chef::Platform::ServiceHelpers.service_resource_providers.include?(:redhat)
36
+ Chef::Platform::ServiceHelpers.config_for_service(resource.service_name).include?(:initd)
33
37
  end
34
38
 
35
39
  def initialize(new_resource, run_context)
@@ -18,87 +18,95 @@
18
18
 
19
19
  require 'chef/resource/service'
20
20
  require 'chef/provider/service/simple'
21
+ require 'chef/mixin/which'
21
22
 
22
23
  class Chef::Provider::Service::Systemd < Chef::Provider::Service::Simple
23
24
 
25
+ include Chef::Mixin::Which
26
+
24
27
  provides :service, os: "linux"
25
28
 
29
+ attr_accessor :status_check_success
30
+
31
+ def self.provides?(node, resource)
32
+ super && Chef::Platform::ServiceHelpers.service_resource_providers.include?(:systemd)
33
+ end
34
+
26
35
  def self.supports?(resource, action)
27
- Chef::Platform::ServiceHelpers.service_resource_providers.include?(:systemd)
36
+ Chef::Platform::ServiceHelpers.config_for_service(resource.service_name).include?(:systemd)
28
37
  end
29
38
 
30
39
  def load_current_resource
31
- @current_resource = Chef::Resource::Service.new(@new_resource.name)
32
- @current_resource.service_name(@new_resource.service_name)
40
+ @current_resource = Chef::Resource::Service.new(new_resource.name)
41
+ current_resource.service_name(new_resource.service_name)
33
42
  @status_check_success = true
34
43
 
35
- if @new_resource.status_command
36
- Chef::Log.debug("#{@new_resource} you have specified a status command, running..")
44
+ if new_resource.status_command
45
+ Chef::Log.debug("#{new_resource} you have specified a status command, running..")
37
46
 
38
- unless shell_out(@new_resource.status_command).error?
39
- @current_resource.running(true)
47
+ unless shell_out(new_resource.status_command).error?
48
+ current_resource.running(true)
40
49
  else
41
50
  @status_check_success = false
42
- @current_resource.running(false)
43
- @current_resource.enabled(false)
44
- nil
51
+ current_resource.running(false)
52
+ current_resource.enabled(false)
45
53
  end
46
54
  else
47
- @current_resource.running(is_active?)
55
+ current_resource.running(is_active?)
48
56
  end
49
57
 
50
- @current_resource.enabled(is_enabled?)
51
- @current_resource
58
+ current_resource.enabled(is_enabled?)
59
+ current_resource
52
60
  end
53
61
 
54
62
  def define_resource_requirements
55
63
  shared_resource_requirements
56
64
  requirements.assert(:all_actions) do |a|
57
- a.assertion { @status_check_success }
65
+ a.assertion { status_check_success }
58
66
  # We won't stop in any case, but in whyrun warn and tell what we're doing.
59
- a.whyrun ["Failed to determine status of #{@new_resource}, using command #{@new_resource.status_command}.",
67
+ a.whyrun ["Failed to determine status of #{new_resource}, using command #{new_resource.status_command}.",
60
68
  "Assuming service would have been installed and is disabled"]
61
69
  end
62
70
  end
63
71
 
64
72
  def start_service
65
- if @current_resource.running
66
- Chef::Log.debug("#{@new_resource} already running, not starting")
73
+ if current_resource.running
74
+ Chef::Log.debug("#{new_resource} already running, not starting")
67
75
  else
68
- if @new_resource.start_command
76
+ if new_resource.start_command
69
77
  super
70
78
  else
71
- shell_out_with_systems_locale!("/bin/systemctl start #{@new_resource.service_name}")
79
+ shell_out_with_systems_locale!("#{systemctl_path} start #{new_resource.service_name}")
72
80
  end
73
81
  end
74
82
  end
75
83
 
76
84
  def stop_service
77
- unless @current_resource.running
78
- Chef::Log.debug("#{@new_resource} not running, not stopping")
85
+ unless current_resource.running
86
+ Chef::Log.debug("#{new_resource} not running, not stopping")
79
87
  else
80
- if @new_resource.stop_command
88
+ if new_resource.stop_command
81
89
  super
82
90
  else
83
- shell_out_with_systems_locale!("/bin/systemctl stop #{@new_resource.service_name}")
91
+ shell_out_with_systems_locale!("#{systemctl_path} stop #{new_resource.service_name}")
84
92
  end
85
93
  end
86
94
  end
87
95
 
88
96
  def restart_service
89
- if @new_resource.restart_command
97
+ if new_resource.restart_command
90
98
  super
91
99
  else
92
- shell_out_with_systems_locale!("/bin/systemctl restart #{@new_resource.service_name}")
100
+ shell_out_with_systems_locale!("#{systemctl_path} restart #{new_resource.service_name}")
93
101
  end
94
102
  end
95
103
 
96
104
  def reload_service
97
- if @new_resource.reload_command
105
+ if new_resource.reload_command
98
106
  super
99
107
  else
100
- if @current_resource.running
101
- shell_out_with_systems_locale!("/bin/systemctl reload #{@new_resource.service_name}")
108
+ if current_resource.running
109
+ shell_out_with_systems_locale!("#{systemctl_path} reload #{new_resource.service_name}")
102
110
  else
103
111
  start_service
104
112
  end
@@ -106,18 +114,28 @@ class Chef::Provider::Service::Systemd < Chef::Provider::Service::Simple
106
114
  end
107
115
 
108
116
  def enable_service
109
- shell_out!("/bin/systemctl enable #{@new_resource.service_name}")
117
+ shell_out!("#{systemctl_path} enable #{new_resource.service_name}")
110
118
  end
111
119
 
112
120
  def disable_service
113
- shell_out!("/bin/systemctl disable #{@new_resource.service_name}")
121
+ shell_out!("#{systemctl_path} disable #{new_resource.service_name}")
114
122
  end
115
123
 
116
124
  def is_active?
117
- shell_out("/bin/systemctl is-active #{@new_resource.service_name} --quiet").exitstatus == 0
125
+ shell_out("#{systemctl_path} is-active #{new_resource.service_name} --quiet").exitstatus == 0
118
126
  end
119
127
 
120
128
  def is_enabled?
121
- shell_out("/bin/systemctl is-enabled #{@new_resource.service_name} --quiet").exitstatus == 0
129
+ shell_out("#{systemctl_path} is-enabled #{new_resource.service_name} --quiet").exitstatus == 0
122
130
  end
131
+
132
+ private
133
+
134
+ def systemctl_path
135
+ if @systemctl_path.nil?
136
+ @systemctl_path = which("systemctl")
137
+ end
138
+ @systemctl_path
139
+ end
140
+
123
141
  end