puppet 2.6.7 → 2.6.8
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/CHANGELOG +49 -0
- data/install.rb +6 -2
- data/lib/puppet.rb +1 -1
- data/lib/puppet/application.rb +16 -8
- data/lib/puppet/application/agent.rb +2 -0
- data/lib/puppet/application/apply.rb +3 -0
- data/lib/puppet/application/master.rb +1 -1
- data/lib/puppet/configurer.rb +10 -1
- data/lib/puppet/defaults.rb +9 -0
- data/lib/puppet/file_serving/fileset.rb +1 -0
- data/lib/puppet/indirector/exec.rb +1 -2
- data/lib/puppet/indirector/report/yaml.rb +11 -0
- data/lib/puppet/node/environment.rb +1 -1
- data/lib/puppet/parameter.rb +2 -0
- data/lib/puppet/parameter/path.rb +42 -0
- data/lib/puppet/parser/compiler.rb +1 -1
- data/lib/puppet/parser/lexer.rb +3 -2
- data/lib/puppet/parser/parser_support.rb +0 -1
- data/lib/puppet/provider/exec/posix.rb +112 -0
- data/lib/puppet/provider/exec/shell.rb +17 -0
- data/lib/puppet/provider/group/groupadd.rb +3 -0
- data/lib/puppet/provider/nameservice/#directoryservice.rb# +519 -0
- data/lib/puppet/provider/package/gem.rb +2 -2
- data/lib/puppet/provider/package/macports.rb +106 -0
- data/lib/puppet/provider/service/debian.rb +6 -2
- data/lib/puppet/rails/inventory_node.rb +5 -0
- data/lib/puppet/reference/#providers.rb# +123 -0
- data/lib/puppet/resource/type_collection.rb +6 -1
- data/lib/puppet/simple_graph.rb +1 -1
- data/lib/puppet/transaction.rb +1 -1
- data/lib/puppet/transaction/report.rb +28 -10
- data/lib/puppet/type/cron.rb +3 -1
- data/lib/puppet/type/exec.rb +30 -167
- data/lib/puppet/type/file.rb +12 -1
- data/lib/puppet/type/file/source.rb +1 -0
- data/lib/puppet/type/group.rb +11 -1
- data/lib/puppet/type/service.rb +19 -11
- data/lib/puppet/util/command_line.rb +15 -12
- data/lib/puppet/util/command_line/puppetrun +0 -1
- data/lib/puppet/util/loadedfile.rb +1 -5
- data/lib/puppet/util/metric.rb +3 -5
- data/lib/puppet/util/plugins.rb +82 -0
- data/spec/integration/configurer_spec.rb +38 -5
- data/spec/integration/transaction_spec.rb +43 -42
- data/spec/lib/puppet_spec/verbose.rb +9 -0
- data/spec/shared_behaviours/path_parameters.rb +185 -0
- data/spec/spec_helper.rb +6 -0
- data/spec/unit/application/agent_spec.rb +7 -0
- data/spec/unit/application/apply_spec.rb +6 -0
- data/spec/unit/application/master_spec.rb +2 -2
- data/spec/unit/configurer_spec.rb +48 -0
- data/spec/unit/file_serving/fileset_spec.rb +8 -0
- data/spec/unit/indirector/certificate_status/#file_spec.rb# +188 -0
- data/spec/unit/indirector/exec_spec.rb +2 -3
- data/spec/unit/indirector/facts/inventory_active_record_spec.rb +5 -1
- data/spec/unit/indirector/report/yaml_spec.rb +38 -0
- data/spec/unit/node/environment_spec.rb +15 -14
- data/spec/unit/parameter/path_spec.rb +24 -0
- data/spec/unit/parser/compiler_spec.rb +1 -2
- data/spec/unit/parser/lexer_spec.rb +12 -0
- data/spec/unit/provider/exec/posix_spec.rb +120 -0
- data/spec/unit/provider/exec/shell_spec.rb +50 -0
- data/spec/unit/provider/group/groupadd_spec.rb +11 -1
- data/spec/unit/provider/package/gem_spec.rb +11 -1
- data/spec/unit/provider/package/macports_spec.rb +122 -0
- data/spec/unit/provider/service/debian_spec.rb +14 -2
- data/spec/unit/resource/#type_collection_spec.rb# +463 -0
- data/spec/unit/resource/type_collection_spec.rb +21 -17
- data/spec/unit/transaction/report_spec.rb +13 -2
- data/spec/unit/type/cron_spec.rb +466 -18
- data/spec/unit/type/exec_spec.rb +633 -106
- data/spec/unit/type/file/source_spec.rb +1 -0
- data/spec/unit/type/group_spec.rb +8 -1
- data/spec/unit/type_spec.rb +1 -1
- data/spec/unit/util/loadedfile_spec.rb +7 -0
- data/spec/unit/util/rdoc/parser_spec.rb +2 -1
- data/tasks/rake/git_workflow.rake +3 -1
- data/test/ral/type/exec.rb +87 -176
- metadata +21 -5
- data/lib/puppet/provider/package/darwinport.rb +0 -86
data/CHANGELOG
CHANGED
@@ -1,3 +1,52 @@
|
|
1
|
+
2.6.8
|
2
|
+
=====
|
3
|
+
c1edcb2 add test for ticket 7101
|
4
|
+
db26326 Move tests from puppet-acceptance repo
|
5
|
+
bee1ef7 Updated CHANGELOG for 2.6.8rc1
|
6
|
+
8b7444d (#2331) Remove darwinports pkg provider, replace with rewritten macports provider
|
7
|
+
65c4e14 Fixed #7082 - Added system support for groups
|
8
|
+
b7f4ff7 (#7018) Give more context on the service type's assumptions. Wording tweaks.
|
9
|
+
bb19dea (#7018) explain internals better in service provider documentation
|
10
|
+
23c9663 maint: Fix sqlite3 require to really be optional
|
11
|
+
4b73d41 maint: Fix sporadic sqlite error
|
12
|
+
54b9f5d (#6818) Stop from getting Rails 3 named_scope deprecation warning
|
13
|
+
e493f8a (#6856) Copy dangling symlinks with 'links => manage' File resource.
|
14
|
+
1e4968e (maint) Indentation fixes
|
15
|
+
99d78f2 (#6490) Add plugin initialization callback system to core
|
16
|
+
5d1cb02 Fix #4339 - Locally save the last report to $lastrunreport
|
17
|
+
306aa30 Fix #4339 - Save a last run report summary to $statedir/last_run_summary.yaml
|
18
|
+
9bb3018 Fixed #3127 - removed legacy debug code
|
19
|
+
d2bacd3 Fixed #3127 - Fixed gem selection regex
|
20
|
+
1b66c28 (#5437) Invalidate cached TypeCollection when there was an error parsing
|
21
|
+
0675c9a (#6937) Adjust formatting of recurse's desc
|
22
|
+
2cdadf9 (#6937) Document the recurse parameter of File type.
|
23
|
+
647a640 (#6893) Document the cron type in the case of specials.
|
24
|
+
87ca313 (#5670) Don't trigger refresh from a failed resource
|
25
|
+
f5aabf5 (#5908) Add support for new update-rc.d disable API
|
26
|
+
37f9ca0 (#6862) Add a default subject for the mail_patches rake task
|
27
|
+
9a4de12 Fixed #6256 - Creation of rrd directory.
|
28
|
+
7c60db5 (#5477) Allow watch_file to watch non-existent files, especially site.pp
|
29
|
+
7761acb (#5221) Add test for fix to fileset with trailing separator
|
30
|
+
357514c (#5221) Fix fileset path absoluteness checking with trailing slash
|
31
|
+
f8941b8 (#4769) Fix negative timeout support for newer rubies
|
32
|
+
a29c7fd Fixed #6562 - Minor kick documentation fix
|
33
|
+
df20513 (#6658) Propagate ENC connection errors to the agent
|
34
|
+
08115c0 (#4884) Remove typo from spec test
|
35
|
+
f2c771b (#4884) Modify tests to pass on non-OS X systems
|
36
|
+
ec1aa19 (#4884) Revise new exec tests, add a few more
|
37
|
+
196294a (4576) - if ENC declares invalid class, it is logged at warning.
|
38
|
+
0d2d6f3 (#4884) Add an shell provider for execs
|
39
|
+
d2e911a (#4884) Fix Test::Unit exec tests
|
40
|
+
fa0cfc6 (#4884) Break the exec type out to have a posix provider
|
41
|
+
c86a980 (#4884) Add consistent path validation and behavior
|
42
|
+
77fbf7f (#4884) Add expand_path to requiring the spec_helper
|
43
|
+
7ec9057 (#4884) Autorequire shared behaviors and method to silence warnings
|
44
|
+
acc99ba (#4884) Fix whitespace
|
45
|
+
6a4d291 (#4884) Get rid of open3 require since it wasn't being used
|
46
|
+
3e7ebbb Fixed #6554 - Missing $haveftool if/else conditional in install.rb breaking Ruby 1.9
|
47
|
+
fddc165 (#5814) Improved cron type specs
|
48
|
+
f2dfee6 (#5814) cron_spec shouldn't depend on cron provider
|
49
|
+
|
1
50
|
2.6.7
|
2
51
|
=====
|
3
52
|
17f673d Updated CHANGELOG for 2.6.7rc1
|
data/install.rb
CHANGED
@@ -92,8 +92,12 @@ def do_configs(configs, target, strip = 'conf/')
|
|
92
92
|
Dir.mkdir(target) unless File.directory? target
|
93
93
|
configs.each do |cf|
|
94
94
|
ocf = File.join(InstallOptions.config_dir, cf.gsub(/#{strip}/, ''))
|
95
|
-
|
96
|
-
|
95
|
+
if $haveftools
|
96
|
+
File.install(cf, ocf, 0644, true)
|
97
|
+
else
|
98
|
+
FileUtils.install(cf, ocf, {:mode => 0644, :verbose => true})
|
99
|
+
end
|
100
|
+
end
|
97
101
|
end
|
98
102
|
|
99
103
|
def do_bins(bins, target, strip = 's?bin/')
|
data/lib/puppet.rb
CHANGED
data/lib/puppet/application.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
require 'optparse'
|
2
|
+
require 'puppet/util/plugins'
|
2
3
|
|
3
4
|
# This class handles all the aspects of a Puppet application/executable
|
4
5
|
# * setting up options
|
@@ -297,11 +298,11 @@ class Application
|
|
297
298
|
|
298
299
|
# This is the main application entry point
|
299
300
|
def run
|
300
|
-
exit_on_fail("initialize") { preinit }
|
301
|
-
exit_on_fail("parse options") { parse_options }
|
301
|
+
exit_on_fail("initialize") { hook('preinit') { preinit } }
|
302
|
+
exit_on_fail("parse options") { hook('parse_options') { parse_options } }
|
302
303
|
exit_on_fail("parse configuration file") { Puppet.settings.parse } if should_parse_config?
|
303
|
-
exit_on_fail("prepare for execution") { setup }
|
304
|
-
exit_on_fail("run") { run_command }
|
304
|
+
exit_on_fail("prepare for execution") { hook('setup') { setup } }
|
305
|
+
exit_on_fail("run") { hook('run_command') { run_command } }
|
305
306
|
end
|
306
307
|
|
307
308
|
def main
|
@@ -407,11 +408,18 @@ class Application
|
|
407
408
|
private
|
408
409
|
|
409
410
|
def exit_on_fail(message, code = 1)
|
410
|
-
|
411
|
+
yield
|
411
412
|
rescue RuntimeError, NotImplementedError => detail
|
412
|
-
|
413
|
-
|
414
|
-
|
413
|
+
puts detail.backtrace if Puppet[:trace]
|
414
|
+
$stderr.puts "Could not #{message}: #{detail}"
|
415
|
+
exit(code)
|
416
|
+
end
|
417
|
+
|
418
|
+
def hook(step,&block)
|
419
|
+
Puppet::Plugins.send("before_application_#{step}",:application_object => self)
|
420
|
+
x = yield
|
421
|
+
Puppet::Plugins.send("after_application_#{step}",:application_object => self, :return_value => x)
|
422
|
+
x
|
415
423
|
end
|
416
424
|
end
|
417
425
|
end
|
@@ -229,6 +229,8 @@ class Puppet::Application::Agent < Puppet::Application
|
|
229
229
|
Puppet::SSL::Host.ca_location = options[:fingerprint] ? :none : :remote
|
230
230
|
|
231
231
|
Puppet::Transaction::Report.terminus_class = :rest
|
232
|
+
# we want the last report to be persisted locally
|
233
|
+
Puppet::Transaction::Report.cache_class = :yaml
|
232
234
|
|
233
235
|
# Override the default; puppetd needs this, usually.
|
234
236
|
# You can still override this on the command-line with, e.g., :compiler.
|
@@ -148,6 +148,9 @@ class Puppet::Application::Apply < Puppet::Application
|
|
148
148
|
exit(1)
|
149
149
|
end
|
150
150
|
|
151
|
+
# we want the last report to be persisted locally
|
152
|
+
Puppet::Transaction::Report.cache_class = :yaml
|
153
|
+
|
151
154
|
if options[:debug]
|
152
155
|
Puppet::Util::Log.level = :debug
|
153
156
|
elsif options[:verbose]
|
@@ -136,7 +136,7 @@ class Puppet::Application::Master < Puppet::Application
|
|
136
136
|
|
137
137
|
exit(Puppet.settings.print_configs ? 0 : 1) if Puppet.settings.print_configs?
|
138
138
|
|
139
|
-
Puppet.settings.use :main, :master, :ssl
|
139
|
+
Puppet.settings.use :main, :master, :ssl, :metrics
|
140
140
|
|
141
141
|
# Cache our nodes in yaml. Currently not configurable.
|
142
142
|
Puppet::Node.cache_class = :yaml
|
data/lib/puppet/configurer.rb
CHANGED
@@ -166,19 +166,28 @@ class Puppet::Configurer
|
|
166
166
|
execute_postrun_command
|
167
167
|
|
168
168
|
Puppet::Util::Log.close(report)
|
169
|
-
|
170
169
|
send_report(report, transaction)
|
171
170
|
end
|
172
171
|
|
173
172
|
def send_report(report, trans)
|
174
173
|
report.finalize_report if trans
|
175
174
|
puts report.summary if Puppet[:summarize]
|
175
|
+
save_last_run_summary(report)
|
176
176
|
report.save if Puppet[:report]
|
177
177
|
rescue => detail
|
178
178
|
puts detail.backtrace if Puppet[:trace]
|
179
179
|
Puppet.err "Could not send report: #{detail}"
|
180
180
|
end
|
181
181
|
|
182
|
+
def save_last_run_summary(report)
|
183
|
+
Puppet::Util::FileLocking.writelock(Puppet[:lastrunfile], 0660) do |file|
|
184
|
+
file.print YAML.dump(report.raw_summary)
|
185
|
+
end
|
186
|
+
rescue => detail
|
187
|
+
puts detail.backtrace if Puppet[:trace]
|
188
|
+
Puppet.err "Could not save last run local report: #{detail}"
|
189
|
+
end
|
190
|
+
|
182
191
|
private
|
183
192
|
|
184
193
|
def self.timeout
|
data/lib/puppet/defaults.rb
CHANGED
@@ -474,6 +474,7 @@ module Puppet
|
|
474
474
|
|
475
475
|
setdefaults(:metrics,
|
476
476
|
:rrddir => {:default => "$vardir/rrd",
|
477
|
+
:mode => 0750,
|
477
478
|
:owner => "service",
|
478
479
|
:group => "service",
|
479
480
|
:desc => "The directory where RRD database files are stored.
|
@@ -606,6 +607,14 @@ module Puppet
|
|
606
607
|
:report => [false,
|
607
608
|
"Whether to send reports after every transaction."
|
608
609
|
],
|
610
|
+
:lastrunfile => { :default => "$statedir/last_run_summary.yaml",
|
611
|
+
:mode => 0660,
|
612
|
+
:desc => "Where puppet agent stores the last run report summary in yaml format."
|
613
|
+
},
|
614
|
+
:lastrunreport => { :default => "$statedir/last_run_report.yaml",
|
615
|
+
:mode => 0660,
|
616
|
+
:desc => "Where puppet agent stores the last run report in yaml format."
|
617
|
+
},
|
609
618
|
:graph => [false, "Whether to create dot graph files for the different
|
610
619
|
configuration graphs. These dot files can be interpreted by tools
|
611
620
|
like OmniGraffle or dot (which is part of ImageMagick)."],
|
@@ -35,8 +35,7 @@ class Puppet::Indirector::Exec < Puppet::Indirector::Terminus
|
|
35
35
|
begin
|
36
36
|
output = execute(external_command)
|
37
37
|
rescue Puppet::ExecutionFailure => detail
|
38
|
-
Puppet
|
39
|
-
return nil
|
38
|
+
raise Puppet::Error, "Failed to find #{name} via exec: #{detail}"
|
40
39
|
end
|
41
40
|
|
42
41
|
if output =~ /\A\s*\Z/ # all whitespace
|
@@ -0,0 +1,11 @@
|
|
1
|
+
require 'puppet/transaction/report'
|
2
|
+
require 'puppet/indirector/yaml'
|
3
|
+
|
4
|
+
class Puppet::Transaction::Report::Yaml < Puppet::Indirector::Yaml
|
5
|
+
desc "Store last report as a flat file, serialized using YAML."
|
6
|
+
|
7
|
+
# Force report to be saved there
|
8
|
+
def path(name,ext='.yaml')
|
9
|
+
Puppet[:lastrunreport]
|
10
|
+
end
|
11
|
+
end
|
@@ -79,7 +79,7 @@ class Puppet::Node::Environment
|
|
79
79
|
# environment has changed do we delve deeper.
|
80
80
|
Thread.current[:known_resource_types] = nil if (krt = Thread.current[:known_resource_types]) && krt.environment != self
|
81
81
|
Thread.current[:known_resource_types] ||= synchronize {
|
82
|
-
if @known_resource_types.nil? or @known_resource_types.
|
82
|
+
if @known_resource_types.nil? or @known_resource_types.require_reparse?
|
83
83
|
@known_resource_types = Puppet::Resource::TypeCollection.new(self)
|
84
84
|
@known_resource_types.perform_initial_import
|
85
85
|
end
|
data/lib/puppet/parameter.rb
CHANGED
@@ -0,0 +1,42 @@
|
|
1
|
+
require 'puppet/parameter'
|
2
|
+
|
3
|
+
class Puppet::Parameter::Path < Puppet::Parameter
|
4
|
+
def self.accept_arrays(bool = true)
|
5
|
+
@accept_arrays = !!bool
|
6
|
+
end
|
7
|
+
def self.arrays?
|
8
|
+
@accept_arrays
|
9
|
+
end
|
10
|
+
|
11
|
+
def validate_path(paths)
|
12
|
+
if paths.is_a?(Array) and ! self.class.arrays? then
|
13
|
+
fail "#{name} only accepts a single path, not an array of paths"
|
14
|
+
end
|
15
|
+
|
16
|
+
# We *always* support Unix path separators, as Win32 does now too.
|
17
|
+
absolute = "[/#{::Regexp.quote(::File::SEPARATOR)}]"
|
18
|
+
win32 = Puppet.features.microsoft_windows?
|
19
|
+
|
20
|
+
Array(paths).each do |path|
|
21
|
+
next if path =~ %r{^#{absolute}}
|
22
|
+
next if win32 and path =~ %r{^(?:[a-zA-Z]:)?#{absolute}}
|
23
|
+
fail("#{name} must be a fully qualified path")
|
24
|
+
end
|
25
|
+
|
26
|
+
paths
|
27
|
+
end
|
28
|
+
|
29
|
+
# This will be overridden if someone uses the validate option, which is why
|
30
|
+
# it just delegates to the other, useful, method.
|
31
|
+
def unsafe_validate(paths)
|
32
|
+
validate_path(paths)
|
33
|
+
end
|
34
|
+
|
35
|
+
# Likewise, this might be overridden, but by default...
|
36
|
+
def unsafe_munge(paths)
|
37
|
+
if paths.is_a?(Array) and ! self.class.arrays? then
|
38
|
+
fail "#{name} only accepts a single path, not an array of paths"
|
39
|
+
end
|
40
|
+
paths
|
41
|
+
end
|
42
|
+
end
|
@@ -162,7 +162,7 @@ class Puppet::Parser::Compiler
|
|
162
162
|
resource.evaluate unless lazy_evaluate
|
163
163
|
found << name
|
164
164
|
else
|
165
|
-
Puppet.
|
165
|
+
Puppet.warning "Could not find class #{name} for #{node.name}"
|
166
166
|
@catalog.tag(name)
|
167
167
|
end
|
168
168
|
end
|
data/lib/puppet/parser/lexer.rb
CHANGED
@@ -312,7 +312,8 @@ class Puppet::Parser::Lexer
|
|
312
312
|
def file=(file)
|
313
313
|
@file = file
|
314
314
|
@line = 1
|
315
|
-
|
315
|
+
contents = File.exists?(file) ? File.read(file) : ""
|
316
|
+
@scanner = StringScanner.new(contents)
|
316
317
|
end
|
317
318
|
|
318
319
|
def shift_token
|
@@ -547,7 +548,7 @@ class Puppet::Parser::Lexer
|
|
547
548
|
value,terminator = slurpstring('"$')
|
548
549
|
token_queue << [TOKENS[token_type[terminator]],preamble+value]
|
549
550
|
if terminator != '$' or @scanner.scan(/\{/)
|
550
|
-
token_queue.shift
|
551
|
+
token_queue.shift
|
551
552
|
elsif var_name = @scanner.scan(%r{(\w*::)*\w+|[0-9]})
|
552
553
|
token_queue << [TOKENS[:VARIABLE],var_name]
|
553
554
|
tokenize_interpolated_string(DQ_continuation_token_types)
|
@@ -88,7 +88,6 @@ class Puppet::Parser::Parser
|
|
88
88
|
unless file =~ /\.pp$/
|
89
89
|
file = file + ".pp"
|
90
90
|
end
|
91
|
-
raise Puppet::Error, "Could not find file #{file}" unless FileTest.exist?(file)
|
92
91
|
end
|
93
92
|
raise Puppet::AlreadyImportedError, "Import loop detected" if known_resource_types.watching_file?(file)
|
94
93
|
|
@@ -0,0 +1,112 @@
|
|
1
|
+
Puppet::Type.type(:exec).provide :posix do
|
2
|
+
include Puppet::Util::Execution
|
3
|
+
|
4
|
+
confine :feature => :posix
|
5
|
+
defaultfor :feature => :posix
|
6
|
+
|
7
|
+
desc "Execute external binaries directly, on POSIX systems.
|
8
|
+
This does not pass through a shell, or perform any interpolation, but
|
9
|
+
only directly calls the command with the arguments given."
|
10
|
+
|
11
|
+
def run(command, check = false)
|
12
|
+
output = nil
|
13
|
+
status = nil
|
14
|
+
dir = nil
|
15
|
+
|
16
|
+
checkexe(command)
|
17
|
+
|
18
|
+
if dir = resource[:cwd]
|
19
|
+
unless File.directory?(dir)
|
20
|
+
if check
|
21
|
+
dir = nil
|
22
|
+
else
|
23
|
+
self.fail "Working directory '#{dir}' does not exist"
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
dir ||= Dir.pwd
|
29
|
+
|
30
|
+
debug "Executing#{check ? " check": ""} '#{command}'"
|
31
|
+
begin
|
32
|
+
# Do our chdir
|
33
|
+
Dir.chdir(dir) do
|
34
|
+
environment = {}
|
35
|
+
|
36
|
+
environment[:PATH] = resource[:path].join(":") if resource[:path]
|
37
|
+
|
38
|
+
if envlist = resource[:environment]
|
39
|
+
envlist = [envlist] unless envlist.is_a? Array
|
40
|
+
envlist.each do |setting|
|
41
|
+
if setting =~ /^(\w+)=((.|\n)+)$/
|
42
|
+
env_name = $1
|
43
|
+
value = $2
|
44
|
+
if environment.include?(env_name) || environment.include?(env_name.to_sym)
|
45
|
+
warning "Overriding environment setting '#{env_name}' with '#{value}'"
|
46
|
+
end
|
47
|
+
environment[env_name] = value
|
48
|
+
else
|
49
|
+
warning "Cannot understand environment setting #{setting.inspect}"
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
withenv environment do
|
55
|
+
Timeout::timeout(resource[:timeout]) do
|
56
|
+
output, status = Puppet::Util::SUIDManager.
|
57
|
+
run_and_capture([command], resource[:user], resource[:group])
|
58
|
+
end
|
59
|
+
# The shell returns 127 if the command is missing.
|
60
|
+
if status.exitstatus == 127
|
61
|
+
raise ArgumentError, output
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
rescue Errno::ENOENT => detail
|
66
|
+
self.fail detail.to_s
|
67
|
+
end
|
68
|
+
|
69
|
+
return output, status
|
70
|
+
end
|
71
|
+
|
72
|
+
# Verify that we have the executable
|
73
|
+
def checkexe(command)
|
74
|
+
exe = extractexe(command)
|
75
|
+
|
76
|
+
if resource[:path]
|
77
|
+
if Puppet.features.posix? and !File.exists?(exe)
|
78
|
+
withenv :PATH => resource[:path].join(File::PATH_SEPARATOR) do
|
79
|
+
exe = which(exe) || raise(ArgumentError,"Could not find command '#{exe}'")
|
80
|
+
end
|
81
|
+
elsif Puppet.features.microsoft_windows? and !File.exists?(exe)
|
82
|
+
resource[:path].each do |path|
|
83
|
+
[".exe", ".ps1", ".bat", ".com", ""].each do |extension|
|
84
|
+
file = File.join(path, exe+extension)
|
85
|
+
return if File.exists?(file)
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
raise ArgumentError, "Could not find command '#{exe}'" unless File.exists?(exe)
|
92
|
+
unless File.executable?(exe)
|
93
|
+
raise ArgumentError,
|
94
|
+
"'#{exe}' is not executable"
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
def extractexe(command)
|
99
|
+
# easy case: command was quoted
|
100
|
+
if command =~ /^"([^"]+)"/
|
101
|
+
$1
|
102
|
+
else
|
103
|
+
command.split(/ /)[0]
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
def validatecmd(command)
|
108
|
+
exe = extractexe(command)
|
109
|
+
# if we're not fully qualified, require a path
|
110
|
+
self.fail "'#{command}' is not qualified and no path was specified. Please qualify the command or specify a path." if File.expand_path(exe) != exe and resource[:path].nil?
|
111
|
+
end
|
112
|
+
end
|