puppet 4.2.1 → 4.2.2
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of puppet might be problematic. Click here for more details.
- data/Rakefile +20 -0
- data/ext/osx/puppet.plist +2 -2
- data/ext/solaris/smf/puppet +44 -0
- data/ext/solaris/smf/puppet.xml +44 -0
- data/ext/suse/client.init +2 -2
- data/ext/suse/server.init +2 -2
- data/install.rb +21 -39
- data/lib/puppet/application/cert.rb +16 -0
- data/lib/puppet/configurer.rb +2 -2
- data/lib/puppet/defaults.rb +2 -1
- data/lib/puppet/file_system/windows.rb +3 -1
- data/lib/puppet/parser/compiler.rb +1 -3
- data/lib/puppet/parser/functions/inline_template.rb +2 -2
- data/lib/puppet/parser/resource.rb +13 -10
- data/lib/puppet/pops/evaluator/evaluator_impl.rb +5 -1
- data/lib/puppet/pops/issues.rb +4 -0
- data/lib/puppet/pops/model/factory.rb +4 -3
- data/lib/puppet/pops/model/model_meta.rb +4 -1
- data/lib/puppet/pops/parser/egrammar.ra +10 -0
- data/lib/puppet/pops/parser/eparser.rb +1279 -1148
- data/lib/puppet/pops/parser/lexer2.rb +6 -0
- data/lib/puppet/pops/validation/checker4_0.rb +17 -1
- data/lib/puppet/pops/validation/validator_factory_4_0.rb +3 -1
- data/lib/puppet/provider/exec.rb +6 -1
- data/lib/puppet/provider/package/yum.rb +9 -3
- data/lib/puppet/provider/service/launchd.rb +36 -7
- data/lib/puppet/provider/service/systemd.rb +10 -2
- data/lib/puppet/reference/configuration.rb +10 -4
- data/lib/puppet/type/package.rb +9 -6
- data/lib/puppet/util/execution.rb +18 -2
- data/lib/puppet/version.rb +1 -1
- data/spec/unit/file_system_spec.rb +20 -0
- data/spec/unit/pops/parser/lexer2_spec.rb +13 -0
- data/spec/unit/pops/validator/validator_spec.rb +24 -0
- data/spec/unit/provider/package/yum_spec.rb +15 -0
- data/spec/unit/provider/service/launchd_spec.rb +85 -10
- data/spec/unit/provider/service/systemd_spec.rb +1 -0
- data/spec/unit/type/exec_spec.rb +16 -8
- metadata +3039 -3029
- checksums.yaml +0 -7
@@ -131,7 +131,13 @@ class Puppet::Pops::Parser::Lexer2
|
|
131
131
|
"type" => [:TYPE, 'type', 4],
|
132
132
|
"attr" => [:ATTR, 'attr', 4],
|
133
133
|
"private" => [:PRIVATE, 'private', 7],
|
134
|
+
# The following tokens exist in reserved form. Later they will be made
|
135
|
+
# live subject to a feature switch.
|
136
|
+
"application" => [:APPLICATION_R, 'application', 11],
|
137
|
+
"consumes" => [:CONSUMES_R, 'consumes', 8],
|
138
|
+
"produces" => [:PRODUCES_R, 'produces', 8],
|
134
139
|
}
|
140
|
+
|
135
141
|
KEYWORDS.each {|k,v| v[1].freeze; v.freeze }
|
136
142
|
KEYWORDS.freeze
|
137
143
|
|
@@ -299,6 +299,12 @@ class Puppet::Pops::Validation::Checker4_0
|
|
299
299
|
'runtime' => true,
|
300
300
|
}
|
301
301
|
|
302
|
+
FUTURE_RESERVED_WORDS = {
|
303
|
+
'application' => true,
|
304
|
+
'produces' => true,
|
305
|
+
'consumes' => true
|
306
|
+
}
|
307
|
+
|
302
308
|
# for 'class', 'define', and function
|
303
309
|
def check_NamedDefinition(o)
|
304
310
|
top(o.eContainer, o)
|
@@ -309,6 +315,12 @@ class Puppet::Pops::Validation::Checker4_0
|
|
309
315
|
if RESERVED_TYPE_NAMES[o.name()]
|
310
316
|
acceptor.accept(Issues::RESERVED_TYPE_NAME, o, {:name => o.name})
|
311
317
|
end
|
318
|
+
|
319
|
+
# This is perhaps not ideal but it's very difficult to pass a ReservedWord through
|
320
|
+
# the mechanism that creates qualified names (namestack, namepop etc.)
|
321
|
+
if FUTURE_RESERVED_WORDS[o.name]
|
322
|
+
acceptor.accept(Issues::FUTURE_RESERVED_WORD, o, {:word => o.name})
|
323
|
+
end
|
312
324
|
end
|
313
325
|
|
314
326
|
def check_FunctionDefinition(o)
|
@@ -495,7 +507,11 @@ class Puppet::Pops::Validation::Checker4_0
|
|
495
507
|
end
|
496
508
|
|
497
509
|
def check_ReservedWord(o)
|
498
|
-
|
510
|
+
if o.future
|
511
|
+
acceptor.accept(Issues::FUTURE_RESERVED_WORD, o, :word => o.word)
|
512
|
+
else
|
513
|
+
acceptor.accept(Issues::RESERVED_WORD, o, :word => o.word)
|
514
|
+
end
|
499
515
|
end
|
500
516
|
|
501
517
|
def check_SelectorExpression(o)
|
@@ -23,7 +23,9 @@ class Puppet::Pops::Validation::ValidatorFactory_4_0 < Puppet::Pops::Validation:
|
|
23
23
|
p[Issues::RT_NO_STORECONFIGS_EXPORT] = Puppet[:storeconfigs] ? :ignore : :warning
|
24
24
|
p[Issues::RT_NO_STORECONFIGS] = Puppet[:storeconfigs] ? :ignore : :warning
|
25
25
|
|
26
|
-
p[Issues::
|
26
|
+
p[Issues::FUTURE_RESERVED_WORD] = :deprecation
|
27
|
+
|
28
|
+
p[Issues::NAME_WITH_HYPHEN] = :error
|
27
29
|
p[Issues::EMPTY_RESOURCE_SPECIALIZATION] = :ignore
|
28
30
|
p
|
29
31
|
end
|
data/lib/puppet/provider/exec.rb
CHANGED
@@ -47,7 +47,12 @@ class Puppet::Provider::Exec < Puppet::Provider
|
|
47
47
|
end
|
48
48
|
end
|
49
49
|
|
50
|
-
|
50
|
+
# Ruby 2.1 and later interrupt execution in a way that bypasses error
|
51
|
+
# handling by default. Passing Timeout::Error causes an exception to be
|
52
|
+
# raised that can be rescued inside of the block by cleanup routines.
|
53
|
+
#
|
54
|
+
# This is backwards compatible all the way to Ruby 1.8.7.
|
55
|
+
Timeout::timeout(resource[:timeout], Timeout::Error) do
|
51
56
|
# note that we are passing "false" for the "override_locale" parameter, which ensures that the user's
|
52
57
|
# default/system locale will be respected. Callers may override this behavior by setting locale-related
|
53
58
|
# environment variables (LANG, LC_ALL, etc.) in their 'environment' configuration.
|
@@ -151,9 +151,15 @@ Puppet::Type.type(:package).provide :yum, :parent => :rpm, :source => :rpm do
|
|
151
151
|
end
|
152
152
|
end
|
153
153
|
|
154
|
-
|
155
|
-
|
156
|
-
|
154
|
+
# Yum on el-4 and el-5 returns exit status 0 when trying to install a package it doesn't recognize;
|
155
|
+
# ensure we capture output to check for errors.
|
156
|
+
no_debug = if Facter.value(:operatingsystemmajrelease).to_i > 5 then ["-d", "0"] else [] end
|
157
|
+
args = no_debug + ["-e", "0", "-y", install_options, operation, wanted].compact
|
158
|
+
output = yum *args
|
159
|
+
|
160
|
+
if output =~ /^No package #{wanted} available\.$/
|
161
|
+
raise Puppet::Error, "Could not find package #{wanted}"
|
162
|
+
end
|
157
163
|
|
158
164
|
# If a version was specified, query again to see if it is a matching version
|
159
165
|
if should
|
@@ -65,12 +65,27 @@ Puppet::Type.type(:service).provide :launchd, :parent => :base do
|
|
65
65
|
]
|
66
66
|
end
|
67
67
|
|
68
|
+
# Gets the current Darwin version, example 10.6 returns 9 and 10.10 returns 14
|
69
|
+
# See https://en.wikipedia.org/wiki/Darwin_(operating_system)#Release_history
|
70
|
+
# for more information.
|
71
|
+
#
|
72
|
+
# @api private
|
73
|
+
def self.get_os_version
|
74
|
+
@os_version ||= Facter.value(:operatingsystemmajrelease).to_i
|
75
|
+
end
|
76
|
+
|
68
77
|
# Defines the path to the overrides plist file where service enabling
|
69
78
|
# behavior is defined in 10.6 and greater.
|
70
79
|
#
|
80
|
+
# With the rewrite of launchd in 10.10+, this moves and slightly changes format.
|
81
|
+
#
|
71
82
|
# @api private
|
72
83
|
def self.launchd_overrides
|
73
|
-
|
84
|
+
if self.get_os_version < 14
|
85
|
+
"/var/db/launchd.db/com.apple.launchd/overrides.plist"
|
86
|
+
else
|
87
|
+
"/var/db/com.apple.xpc.launchd/disabled.plist"
|
88
|
+
end
|
74
89
|
end
|
75
90
|
|
76
91
|
# Caching is enabled through the following three methods. Self.prefetch will
|
@@ -219,8 +234,10 @@ Puppet::Type.type(:service).provide :launchd, :parent => :base do
|
|
219
234
|
did_enable_job = false
|
220
235
|
cmds = []
|
221
236
|
cmds << :launchctl << :load
|
237
|
+
# always add -w so it always starts the job, it is a noop if it is not needed, this means we do
|
238
|
+
# not have to rescan all launchd plists.
|
239
|
+
cmds << "-w"
|
222
240
|
if self.enabled? == :false || self.status == :stopped # launchctl won't load disabled jobs
|
223
|
-
cmds << "-w"
|
224
241
|
did_enable_job = true
|
225
242
|
end
|
226
243
|
cmds << job_path
|
@@ -277,7 +294,11 @@ Puppet::Type.type(:service).provide :launchd, :parent => :base do
|
|
277
294
|
|
278
295
|
if FileTest.file?(self.class.launchd_overrides) and overrides = self.class.read_plist(self.class.launchd_overrides)
|
279
296
|
if overrides.has_key?(resource[:name])
|
280
|
-
|
297
|
+
if self.class.get_os_version < 14
|
298
|
+
overrides_disabled = overrides[resource[:name]]["Disabled"] if overrides[resource[:name]].has_key?("Disabled")
|
299
|
+
else
|
300
|
+
overrides_disabled = overrides[resource[:name]]
|
301
|
+
end
|
281
302
|
end
|
282
303
|
end
|
283
304
|
|
@@ -296,13 +317,21 @@ Puppet::Type.type(:service).provide :launchd, :parent => :base do
|
|
296
317
|
# without actually loading/unloading the job.
|
297
318
|
def enable
|
298
319
|
overrides = self.class.read_plist(self.class.launchd_overrides)
|
299
|
-
|
320
|
+
if self.class.get_os_version < 14
|
321
|
+
overrides[resource[:name]] = { "Disabled" => false }
|
322
|
+
else
|
323
|
+
overrides[resource[:name]] = false
|
324
|
+
end
|
300
325
|
Plist::Emit.save_plist(overrides, self.class.launchd_overrides)
|
301
326
|
end
|
302
327
|
|
303
328
|
def disable
|
304
|
-
|
305
|
-
|
306
|
-
|
329
|
+
overrides = self.class.read_plist(self.class.launchd_overrides)
|
330
|
+
if self.class.get_os_version < 14
|
331
|
+
overrides[resource[:name]] = { "Disabled" => true }
|
332
|
+
else
|
333
|
+
overrides[resource[:name]] = true
|
334
|
+
end
|
335
|
+
Plist::Emit.save_plist(overrides, self.class.launchd_overrides)
|
307
336
|
end
|
308
337
|
end
|
@@ -105,7 +105,7 @@ Puppet::Type.type(:service).provide :systemd, :parent => :base do
|
|
105
105
|
end
|
106
106
|
|
107
107
|
def enable
|
108
|
-
|
108
|
+
self.unmask
|
109
109
|
output = systemctl("enable", @resource[:name])
|
110
110
|
rescue Puppet::ExecutionFailure
|
111
111
|
raise Puppet::Error, "Could not enable #{self.name}: #{output}", $!.backtrace
|
@@ -113,7 +113,6 @@ Puppet::Type.type(:service).provide :systemd, :parent => :base do
|
|
113
113
|
|
114
114
|
def mask
|
115
115
|
self.disable
|
116
|
-
|
117
116
|
begin
|
118
117
|
output = systemctl("mask", @resource[:name])
|
119
118
|
rescue Puppet::ExecutionFailure
|
@@ -121,11 +120,20 @@ Puppet::Type.type(:service).provide :systemd, :parent => :base do
|
|
121
120
|
end
|
122
121
|
end
|
123
122
|
|
123
|
+
def unmask
|
124
|
+
begin
|
125
|
+
output = systemctl("unmask", @resource[:name])
|
126
|
+
rescue Puppet::ExecutionFailure
|
127
|
+
raise Puppet::Error, "Could not unmask #{self.name}: #{output}", $!.backtrace
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
124
131
|
def restartcmd
|
125
132
|
[command(:systemctl), "restart", @resource[:name]]
|
126
133
|
end
|
127
134
|
|
128
135
|
def startcmd
|
136
|
+
self.unmask
|
129
137
|
[command(:systemctl), "start", @resource[:name]]
|
130
138
|
end
|
131
139
|
|
@@ -22,10 +22,16 @@ config = Puppet::Util::Reference.newreference(:configuration, :depth => 1, :doc
|
|
22
22
|
|
23
23
|
# Now print the data about the item.
|
24
24
|
val = object.default
|
25
|
-
if name.to_s ==
|
26
|
-
val =
|
27
|
-
elsif name.to_s ==
|
28
|
-
val =
|
25
|
+
if name.to_s == 'vardir'
|
26
|
+
val = 'Unix/Linux: /opt/puppetlabs/puppet/cache -- Windows: C:\ProgramData\PuppetLabs\puppet\cache -- Non-root user: ~/.puppetlabs/opt/puppet/cache'
|
27
|
+
elsif name.to_s == 'confdir'
|
28
|
+
val = 'Unix/Linux: /etc/puppetlabs/puppet -- Windows: C:\ProgramData\PuppetLabs\puppet\etc -- Non-root user: ~/.puppetlabs/etc/puppet'
|
29
|
+
elsif name.to_s == 'codedir'
|
30
|
+
val = 'Unix/Linux: /etc/puppetlabs/code -- Windows: C:\ProgramData\PuppetLabs\code -- Non-root user: ~/.puppetlabs/etc/code'
|
31
|
+
elsif name.to_s == 'rundir'
|
32
|
+
val = 'Unix/Linux: /var/run/puppetlabs -- Windows: C:\ProgramData\PuppetLabs\puppet\var\run -- Non-root user: ~/.puppetlabs/var/run'
|
33
|
+
elsif name.to_s == 'logdir'
|
34
|
+
val = 'Unix/Linux: /var/log/puppetlabs/puppet -- Windows: C:\ProgramData\PuppetLabs\puppet\var\log -- Non-root user: ~/.puppetlabs/var/log'
|
29
35
|
end
|
30
36
|
|
31
37
|
# Leave out the section information; it was apparently confusing people.
|
data/lib/puppet/type/package.rb
CHANGED
@@ -404,8 +404,9 @@ module Puppet
|
|
404
404
|
end
|
405
405
|
|
406
406
|
newparam(:configfiles) do
|
407
|
-
desc "Whether
|
408
|
-
|
407
|
+
desc "Whether to keep or replace modified config files when installing or
|
408
|
+
upgrading a package. This only affects the `apt` and `dpkg` providers.
|
409
|
+
Defaults to `keep`."
|
409
410
|
|
410
411
|
defaultto :keep
|
411
412
|
|
@@ -456,10 +457,12 @@ module Puppet
|
|
456
457
|
key and value pair are interpreted in a provider specific way. Each
|
457
458
|
option will automatically be quoted when passed to the install command.
|
458
459
|
|
459
|
-
|
460
|
-
|
461
|
-
|
462
|
-
|
460
|
+
With Windows packages, note that file paths in an install option must
|
461
|
+
use backslashes. (Since install options are passed directly to the
|
462
|
+
installation command, forward slashes won't be automatically converted
|
463
|
+
like they are in `file` resources.) Note also that backslashes in
|
464
|
+
double-quoted strings _must_ be escaped and backslashes in single-quoted
|
465
|
+
strings _can_ be escaped.
|
463
466
|
EOT
|
464
467
|
end
|
465
468
|
|
@@ -1,3 +1,4 @@
|
|
1
|
+
require 'timeout'
|
1
2
|
require 'puppet/file_system/uniquefile'
|
2
3
|
|
3
4
|
module Puppet
|
@@ -192,8 +193,23 @@ module Puppet::Util::Execution
|
|
192
193
|
if execution_stub = Puppet::Util::ExecutionStub.current_value
|
193
194
|
return execution_stub.call(*exec_args)
|
194
195
|
elsif Puppet.features.posix?
|
195
|
-
child_pid =
|
196
|
-
|
196
|
+
child_pid = nil
|
197
|
+
begin
|
198
|
+
child_pid = execute_posix(*exec_args)
|
199
|
+
exit_status = Process.waitpid2(child_pid).last.exitstatus
|
200
|
+
child_pid = nil
|
201
|
+
rescue Timeout::Error => e
|
202
|
+
# NOTE: For Ruby 2.1+, an explicit Timeout::Error class has to be
|
203
|
+
# passed to Timeout.timeout in order for there to be something for
|
204
|
+
# this block to rescue.
|
205
|
+
unless child_pid.nil?
|
206
|
+
Process.kill(:TERM, child_pid)
|
207
|
+
# Spawn a thread to reap the process if it dies.
|
208
|
+
Thread.new { Process.waitpid(child_pid) }
|
209
|
+
end
|
210
|
+
|
211
|
+
raise e
|
212
|
+
end
|
197
213
|
elsif Puppet.features.microsoft_windows?
|
198
214
|
process_info = execute_windows(*exec_args)
|
199
215
|
begin
|
data/lib/puppet/version.rb
CHANGED
@@ -446,6 +446,26 @@ describe "Puppet::FileSystem" do
|
|
446
446
|
expect(Puppet::FileSystem.readlink(symlink)).to eq(missing_file.to_s)
|
447
447
|
end
|
448
448
|
|
449
|
+
it "should be able to unlink a dangling symlink pointed at a file" do
|
450
|
+
symlink = tmpfile("somefile_link")
|
451
|
+
Puppet::FileSystem.symlink(file, symlink)
|
452
|
+
::File.delete(file)
|
453
|
+
Puppet::FileSystem.unlink(symlink)
|
454
|
+
|
455
|
+
expect(Puppet::FileSystem).to_not be_exist(file)
|
456
|
+
expect(Puppet::FileSystem).to_not be_exist(symlink)
|
457
|
+
end
|
458
|
+
|
459
|
+
it "should be able to unlink a dangling symlink pointed at a directory" do
|
460
|
+
symlink = tmpfile("somedir_link")
|
461
|
+
Puppet::FileSystem.symlink(dir, symlink)
|
462
|
+
Dir.rmdir(dir)
|
463
|
+
Puppet::FileSystem.unlink(symlink)
|
464
|
+
|
465
|
+
expect(Puppet::FileSystem).to_not be_exist(dir)
|
466
|
+
expect(Puppet::FileSystem).to_not be_exist(symlink)
|
467
|
+
end
|
468
|
+
|
449
469
|
it "should delete only the symlink and not the target when calling unlink instance method" do
|
450
470
|
[file, dir].each do |target|
|
451
471
|
symlink = tmpfile("#{Puppet::FileSystem.basename(target)}_link")
|
@@ -91,12 +91,25 @@ describe 'Lexer2' do
|
|
91
91
|
"true" => :BOOLEAN,
|
92
92
|
"in" => :IN,
|
93
93
|
"unless" => :UNLESS,
|
94
|
+
"private" => :PRIVATE,
|
95
|
+
"type" => :TYPE,
|
96
|
+
"attr" => :ATTR,
|
94
97
|
}.each do |string, name|
|
95
98
|
it "should lex a keyword from '#{string}'" do
|
96
99
|
expect(tokens_scanned_from(string)).to match_tokens2(name)
|
97
100
|
end
|
98
101
|
end
|
99
102
|
|
103
|
+
{
|
104
|
+
"application" => :APPLICATION_R,
|
105
|
+
"consumes" => :CONSUMES_R,
|
106
|
+
"produces" => :PRODUCES_R,
|
107
|
+
}.each do |string, name|
|
108
|
+
it "should lex a (future reserved) keyword from '#{string}'" do
|
109
|
+
expect(tokens_scanned_from(string)).to match_tokens2(name)
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
100
113
|
# TODO: Complete with all edge cases
|
101
114
|
[ 'A', 'A::B', '::A', '::A::B',].each do |string|
|
102
115
|
it "should lex a CLASSREF on the form '#{string}'" do
|
@@ -119,6 +119,30 @@ describe "validating 4x" do
|
|
119
119
|
end
|
120
120
|
end
|
121
121
|
|
122
|
+
context 'for future reserved words' do
|
123
|
+
['application', 'produces', 'consumes'].each do |word|
|
124
|
+
it "produces an issue for the word '#{word}'" do
|
125
|
+
source = "$a = #{word}"
|
126
|
+
expect(validate(parse(source))).to have_issue(Puppet::Pops::Issues::FUTURE_RESERVED_WORD)
|
127
|
+
end
|
128
|
+
|
129
|
+
it 'produces a warning issue when used as a class name' do
|
130
|
+
source = "class #{word} {}"
|
131
|
+
expect(validate(parse(source))).to have_issue(Puppet::Pops::Issues::FUTURE_RESERVED_WORD)
|
132
|
+
end
|
133
|
+
|
134
|
+
it 'produces no warning or error when used as a parameter name' do
|
135
|
+
source = "define foo($#{word}) { notice $#{word} }"
|
136
|
+
expect(validate(parse(source)).diagnostics.empty?).to eq(true)
|
137
|
+
end
|
138
|
+
|
139
|
+
it 'produces no warning or error when used as an attribute name' do
|
140
|
+
source = "foo { bar: #{word} => ok }"
|
141
|
+
expect(validate(parse(source)).diagnostics.empty?).to eq(true)
|
142
|
+
end
|
143
|
+
end
|
144
|
+
end
|
145
|
+
|
122
146
|
context 'for reserved type names' do
|
123
147
|
[# type/Type, is a reserved name but results in syntax error because it is a keyword in lower case form
|
124
148
|
'any',
|
@@ -181,6 +181,7 @@ describe provider_class do
|
|
181
181
|
Puppet::Util.stubs(:which).with("rpm").returns("/bin/rpm")
|
182
182
|
provider.stubs(:which).with("rpm").returns("/bin/rpm")
|
183
183
|
Puppet::Util::Execution.expects(:execute).with(["/bin/rpm", "--version"], {:combine => true, :custom_environment => {}, :failonfail => true}).returns("4.10.1\n").at_most_once
|
184
|
+
Facter.stubs(:value).with(:operatingsystemmajrelease).returns('6')
|
184
185
|
end
|
185
186
|
|
186
187
|
it 'should call yum install for :installed' do
|
@@ -189,6 +190,20 @@ describe provider_class do
|
|
189
190
|
provider.install
|
190
191
|
end
|
191
192
|
|
193
|
+
context 'on el-5' do
|
194
|
+
before(:each) do
|
195
|
+
Facter.stubs(:value).with(:operatingsystemmajrelease).returns('5')
|
196
|
+
end
|
197
|
+
|
198
|
+
it 'should catch yum install failures when status code is wrong' do
|
199
|
+
resource.stubs(:should).with(:ensure).returns :installed
|
200
|
+
provider.expects(:yum).with('-e', '0', '-y', :install, name).returns("No package #{name} available.")
|
201
|
+
expect {
|
202
|
+
provider.install
|
203
|
+
}.to raise_error(Puppet::Error, "Could not find package #{name}")
|
204
|
+
end
|
205
|
+
end
|
206
|
+
|
192
207
|
it 'should use :install to update' do
|
193
208
|
provider.expects(:install)
|
194
209
|
provider.update
|
@@ -6,8 +6,9 @@ require 'spec_helper'
|
|
6
6
|
describe Puppet::Type.type(:service).provider(:launchd) do
|
7
7
|
let (:joblabel) { "com.foo.food" }
|
8
8
|
let (:provider) { subject.class }
|
9
|
-
let (:launchd_overrides) { '/var/db/launchd.db/com.apple.launchd/overrides.plist' }
|
10
9
|
let(:resource) { Puppet::Type.type(:service).new(:name => joblabel, :provider => :launchd) }
|
10
|
+
let (:launchd_overrides_6_9) { '/var/db/launchd.db/com.apple.launchd/overrides.plist' }
|
11
|
+
let (:launchd_overrides_10_) { '/var/db/com.apple.xpc.launchd/disabled.plist' }
|
11
12
|
subject { resource.provider }
|
12
13
|
|
13
14
|
describe "the type interface" do
|
@@ -37,6 +38,56 @@ describe Puppet::Type.type(:service).provider(:launchd) do
|
|
37
38
|
end
|
38
39
|
end
|
39
40
|
|
41
|
+
[[10, '10.6'], [13, '10.9']].each do |kernel, version|
|
42
|
+
describe "when checking whether the service is enabled on OS X #{version}" do
|
43
|
+
it "should return true if the job plist says disabled is true and the global overrides says disabled is false" do
|
44
|
+
provider.expects(:get_os_version).returns(kernel).at_least_once
|
45
|
+
subject.expects(:plist_from_label).returns([joblabel, {"Disabled" => true}])
|
46
|
+
provider.expects(:read_plist).with(launchd_overrides_6_9).returns({joblabel => {"Disabled" => false}})
|
47
|
+
FileTest.expects(:file?).with(launchd_overrides_6_9).returns(true)
|
48
|
+
expect(subject.enabled?).to eq(:true)
|
49
|
+
end
|
50
|
+
it "should return false if the job plist says disabled is false and the global overrides says disabled is true" do
|
51
|
+
provider.expects(:get_os_version).returns(kernel).at_least_once
|
52
|
+
subject.expects(:plist_from_label).returns([joblabel, {"Disabled" => false}])
|
53
|
+
provider.expects(:read_plist).with(launchd_overrides_6_9).returns({joblabel => {"Disabled" => true}})
|
54
|
+
FileTest.expects(:file?).with(launchd_overrides_6_9).returns(true)
|
55
|
+
expect(subject.enabled?).to eq(:false)
|
56
|
+
end
|
57
|
+
it "should return true if the job plist and the global overrides have no disabled keys" do
|
58
|
+
provider.expects(:get_os_version).returns(kernel).at_least_once
|
59
|
+
subject.expects(:plist_from_label).returns([joblabel, {}])
|
60
|
+
provider.expects(:read_plist).with(launchd_overrides_6_9).returns({})
|
61
|
+
FileTest.expects(:file?).with(launchd_overrides_6_9).returns(true)
|
62
|
+
expect(subject.enabled?).to eq(:true)
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
describe "when checking whether the service is enabled on OS X 10.10" do
|
68
|
+
it "should return true if the job plist says disabled is true and the global overrides says disabled is false" do
|
69
|
+
provider.expects(:get_os_version).returns(14).at_least_once
|
70
|
+
subject.expects(:plist_from_label).returns([joblabel, {"Disabled" => true}])
|
71
|
+
provider.expects(:read_plist).with(launchd_overrides_10_).returns({joblabel => false})
|
72
|
+
FileTest.expects(:file?).with(launchd_overrides_10_).returns(true)
|
73
|
+
expect(subject.enabled?).to eq(:true)
|
74
|
+
end
|
75
|
+
it "should return false if the job plist says disabled is false and the global overrides says disabled is true" do
|
76
|
+
provider.expects(:get_os_version).returns(14).at_least_once
|
77
|
+
subject.expects(:plist_from_label).returns([joblabel, {"Disabled" => false}])
|
78
|
+
provider.expects(:read_plist).with(launchd_overrides_10_).returns({joblabel => true})
|
79
|
+
FileTest.expects(:file?).with(launchd_overrides_10_).returns(true)
|
80
|
+
expect(subject.enabled?).to eq(:false)
|
81
|
+
end
|
82
|
+
it "should return true if the job plist and the global overrides have no disabled keys" do
|
83
|
+
provider.expects(:get_os_version).returns(14).at_least_once
|
84
|
+
subject.expects(:plist_from_label).returns([joblabel, {}])
|
85
|
+
provider.expects(:read_plist).with(launchd_overrides_10_).returns({})
|
86
|
+
FileTest.expects(:file?).with(launchd_overrides_10_).returns(true)
|
87
|
+
expect(subject.enabled?).to eq(:true)
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
40
91
|
describe "when starting the service" do
|
41
92
|
it "should call any explicit 'start' command" do
|
42
93
|
resource[:start] = "/bin/false"
|
@@ -47,13 +98,13 @@ describe Puppet::Type.type(:service).provider(:launchd) do
|
|
47
98
|
it "should look for the relevant plist once" do
|
48
99
|
subject.expects(:plist_from_label).returns([joblabel, {}]).once
|
49
100
|
subject.expects(:enabled?).returns :true
|
50
|
-
subject.expects(:execute).with([:launchctl, :load, joblabel])
|
101
|
+
subject.expects(:execute).with([:launchctl, :load, "-w", joblabel])
|
51
102
|
subject.start
|
52
103
|
end
|
53
104
|
it "should execute 'launchctl load' once without writing to the plist if the job is enabled" do
|
54
105
|
subject.expects(:plist_from_label).returns([joblabel, {}])
|
55
106
|
subject.expects(:enabled?).returns :true
|
56
|
-
subject.expects(:execute).with([:launchctl, :load, joblabel]).once
|
107
|
+
subject.expects(:execute).with([:launchctl, :load, "-w", joblabel]).once
|
57
108
|
subject.start
|
58
109
|
end
|
59
110
|
it "should execute 'launchctl load' with writing to the plist once if the job is disabled" do
|
@@ -147,21 +198,45 @@ describe Puppet::Type.type(:service).provider(:launchd) do
|
|
147
198
|
end
|
148
199
|
end
|
149
200
|
|
150
|
-
|
201
|
+
[[10, "10.6"], [13, "10.9"]].each do |kernel, version|
|
202
|
+
describe "when enabling the service on OS X #{version}" do
|
203
|
+
it "should write to the global launchd overrides file once" do
|
204
|
+
resource[:enable] = true
|
205
|
+
provider.expects(:get_os_version).returns(kernel).at_least_once
|
206
|
+
provider.expects(:read_plist).with(launchd_overrides_6_9).returns({})
|
207
|
+
Plist::Emit.expects(:save_plist).with(has_entry(resource[:name], {'Disabled' => false}), launchd_overrides_6_9).once
|
208
|
+
subject.enable
|
209
|
+
end
|
210
|
+
end
|
211
|
+
|
212
|
+
describe "when disabling the service on OS X #{version}" do
|
213
|
+
it "should write to the global launchd overrides file once" do
|
214
|
+
resource[:enable] = false
|
215
|
+
provider.expects(:get_os_version).returns(kernel).at_least_once
|
216
|
+
provider.expects(:read_plist).with(launchd_overrides_6_9).returns({})
|
217
|
+
Plist::Emit.expects(:save_plist).with(has_entry(resource[:name], {'Disabled' => true}), launchd_overrides_6_9).once
|
218
|
+
subject.disable
|
219
|
+
end
|
220
|
+
end
|
221
|
+
end
|
222
|
+
|
223
|
+
describe "when enabling the service on OS X 10.10" do
|
151
224
|
it "should write to the global launchd overrides file once" do
|
152
225
|
resource[:enable] = true
|
153
|
-
provider.expects(:
|
154
|
-
|
226
|
+
provider.expects(:get_os_version).returns(14).at_least_once
|
227
|
+
provider.expects(:read_plist).with(launchd_overrides_10_).returns({})
|
228
|
+
Plist::Emit.expects(:save_plist).with(has_entry(resource[:name], false), launchd_overrides_10_).once
|
155
229
|
subject.enable
|
156
230
|
end
|
157
231
|
end
|
158
232
|
|
159
|
-
describe "when disabling the service" do
|
233
|
+
describe "when disabling the service on OS X 10.10" do
|
160
234
|
it "should write to the global launchd overrides file once" do
|
161
235
|
resource[:enable] = false
|
162
|
-
provider.
|
163
|
-
|
164
|
-
|
236
|
+
provider.expects(:get_os_version).returns(14).at_least_once
|
237
|
+
provider.expects(:read_plist).with(launchd_overrides_10_).returns({})
|
238
|
+
Plist::Emit.expects(:save_plist).with(has_entry(resource[:name], true), launchd_overrides_10_).once
|
239
|
+
subject.disable
|
165
240
|
end
|
166
241
|
end
|
167
242
|
|