puppet 3.4.2 → 3.4.3
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.
- checksums.yaml +7 -0
- data/ext/build_defaults.yaml +1 -1
- data/ext/redhat/puppet.spec.erb +8 -8
- data/lib/puppet/defaults.rb +5 -1
- data/lib/puppet/indirector/resource_type/parser.rb +58 -38
- data/lib/puppet/metatype/manager.rb +0 -1
- data/lib/puppet/network/http/connection.rb +8 -0
- data/lib/puppet/network/http/webrick.rb +4 -1
- data/lib/puppet/node/environment.rb +13 -32
- data/lib/puppet/parser/compiler.rb +1 -2
- data/lib/puppet/parser/functions/each.rb +4 -4
- data/lib/puppet/parser/type_loader.rb +20 -1
- data/lib/puppet/provider/package/dpkg.rb +13 -54
- data/lib/puppet/provider/package/rpm.rb +7 -11
- data/lib/puppet/transaction/resource_harness.rb +17 -17
- data/lib/puppet/type.rb +83 -117
- data/lib/puppet/type/exec.rb +42 -20
- data/lib/puppet/type/file.rb +4 -0
- data/lib/puppet/type/interface.rb +4 -0
- data/lib/puppet/type/mount.rb +4 -2
- data/lib/puppet/type/package.rb +4 -0
- data/lib/puppet/type/schedule.rb +14 -13
- data/lib/puppet/type/service.rb +9 -6
- data/lib/puppet/type/stage.rb +17 -9
- data/lib/puppet/type/user.rb +1 -1
- data/lib/puppet/util/monkey_patches.rb +16 -11
- data/lib/puppet/util/rdoc/code_objects.rb +4 -0
- data/lib/puppet/util/windows.rb +1 -0
- data/lib/puppet/util/windows/file.rb +36 -13
- data/lib/puppet/util/windows/process.rb +7 -4
- data/lib/puppet/util/windows/registry.rb +35 -1
- data/lib/puppet/util/windows/string.rb +14 -0
- data/lib/puppet/version.rb +1 -1
- data/spec/integration/util_spec.rb +31 -0
- data/spec/unit/node/environment_spec.rb +5 -13
- data/spec/unit/provider/package/aptitude_spec.rb +13 -10
- data/spec/unit/provider/package/aptrpm_spec.rb +2 -2
- data/spec/unit/provider/package/dpkg_spec.rb +93 -234
- data/spec/unit/provider/package/rpm_spec.rb +50 -74
- data/spec/unit/provider/package/yum_spec.rb +5 -6
- data/spec/unit/transaction/resource_harness_spec.rb +111 -3
- data/spec/unit/type/user_spec.rb +7 -5
- data/spec/unit/util/windows/registry_spec.rb +54 -0
- data/spec/unit/util/windows/string_spec.rb +54 -0
- data/tasks/benchmark.rake +110 -0
- data/tasks/ci.rake +1 -1
- metadata +11 -15
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: ce22f48d6ff156cc3bce494d7d78a7cbec873e71
|
4
|
+
data.tar.gz: 3977c8d441e6629f8f30bda14521112c649ce0fe
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 60e002a57f5b2d7b52bf114e94ca07d2c72c3457ef1505e8b28e7a2fc04a618627b37712b471001ecfb642efaa8da723581db646f08a48fb3afa26f4e5246642
|
7
|
+
data.tar.gz: 79108cfb2a13238829fda9a759a0106bb549f887dcf7b9b5be76e311f34110b5e047fa1a00562f9a0cd9066ea378aed3ace944d352167cbc4e6912d57a8bef96
|
data/ext/build_defaults.yaml
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
packaging_url: 'git://github.com/puppetlabs/packaging.git --branch=master'
|
3
3
|
packaging_repo: 'packaging'
|
4
4
|
default_cow: 'base-squeeze-i386.cow'
|
5
|
-
cows: 'base-lucid-i386.cow base-precise-i386.cow base-quantal-i386.cow base-raring-i386.cow base-
|
5
|
+
cows: 'base-lucid-i386.cow base-precise-i386.cow base-quantal-i386.cow base-raring-i386.cow base-squeeze-i386.cow base-stable-i386.cow base-testing-i386.cow base-wheezy-i386.cow base-saucy-i386.cow'
|
6
6
|
pbuild_conf: '/etc/pbuilderrc'
|
7
7
|
packager: 'puppetlabs'
|
8
8
|
gpg_name: 'info@puppetlabs.com'
|
data/ext/redhat/puppet.spec.erb
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
# Augeas and SELinux requirements may be disabled at build time by passing
|
2
2
|
# --without augeas and/or --without selinux to rpmbuild or mock
|
3
3
|
|
4
|
-
# Fedora 17 ships with
|
5
|
-
# sitelibdir. Adjust our target if installing on f17.
|
6
|
-
%if 0%{?fedora} >= 17
|
4
|
+
# Fedora 17 ships with ruby 1.9, RHEL 7 with ruby 2.0, which use vendorlibdir instead
|
5
|
+
# of sitelibdir. Adjust our target if installing on f17 or rhel7.
|
6
|
+
%if 0%{?fedora} >= 17 || 0%{?rhel} >= 7
|
7
7
|
%global puppet_libdir %(ruby -rrbconfig -e 'puts RbConfig::CONFIG["vendorlibdir"]')
|
8
8
|
%else
|
9
9
|
%global puppet_libdir %(ruby -rrbconfig -e 'puts RbConfig::CONFIG["sitelibdir"]')
|
10
10
|
%endif
|
11
11
|
|
12
|
-
%if 0%{?fedora} >= 17
|
12
|
+
%if 0%{?fedora} >= 17 || 0%{?rhel} >= 7
|
13
13
|
%global _with_systemd 1
|
14
14
|
%else
|
15
15
|
%global _with_systemd 0
|
@@ -66,7 +66,7 @@ Requires: shadow-utils
|
|
66
66
|
%if 0%{?_with_systemd}
|
67
67
|
# Required for %%post, %%preun, %%postun
|
68
68
|
Requires: systemd
|
69
|
-
%if 0%{?fedora} >= 18
|
69
|
+
%if 0%{?fedora} >= 18 || 0%{?rhel} >= 7
|
70
70
|
BuildRequires: systemd
|
71
71
|
%else
|
72
72
|
BuildRequires: systemd-units
|
@@ -120,7 +120,7 @@ install -d -m0755 %{buildroot}%{_localstatedir}/run/puppet
|
|
120
120
|
install -d -m0750 %{buildroot}%{_localstatedir}/log/puppet
|
121
121
|
|
122
122
|
%if 0%{?_with_systemd}
|
123
|
-
# Systemd for fedora >= 17
|
123
|
+
# Systemd for fedora >= 17 or el 7
|
124
124
|
%{__install} -d -m0755 %{buildroot}%{_unitdir}
|
125
125
|
install -Dp -m0644 ext/systemd/puppet.service %{buildroot}%{_unitdir}/puppet.service
|
126
126
|
ln -s %{_unitdir}/puppet.service %{buildroot}%{_unitdir}/puppetagent.service
|
@@ -163,7 +163,7 @@ vimdir=%{buildroot}%{_datadir}/vim/vimfiles
|
|
163
163
|
install -Dp -m0644 ext/vim/ftdetect/puppet.vim $vimdir/ftdetect/puppet.vim
|
164
164
|
install -Dp -m0644 ext/vim/syntax/puppet.vim $vimdir/syntax/puppet.vim
|
165
165
|
|
166
|
-
%if 0%{?fedora} >= 15
|
166
|
+
%if 0%{?fedora} >= 15 || 0%{?rhel} >= 7
|
167
167
|
# Setup tmpfiles.d config
|
168
168
|
mkdir -p %{buildroot}%{_sysconfdir}/tmpfiles.d
|
169
169
|
echo "D /var/run/%{name} 0755 %{name} %{name} -" > \
|
@@ -198,7 +198,7 @@ cp -pr ext/puppet-nm-dispatcher \
|
|
198
198
|
%endif
|
199
199
|
%dir %{_sysconfdir}/puppet
|
200
200
|
%dir %{_sysconfdir}/%{name}/modules
|
201
|
-
%if 0%{?fedora} >= 15
|
201
|
+
%if 0%{?fedora} >= 15 || 0%{?rhel} >= 7
|
202
202
|
%config(noreplace) %{_sysconfdir}/tmpfiles.d/%{name}.conf
|
203
203
|
%endif
|
204
204
|
%config(noreplace) %{_sysconfdir}/puppet/puppet.conf
|
data/lib/puppet/defaults.rb
CHANGED
@@ -1465,7 +1465,11 @@ EOT
|
|
1465
1465
|
separator is ':', and the Windows path separator is ';'.)",
|
1466
1466
|
|
1467
1467
|
:call_hook => :on_initialize_and_write, # Call our hook with the default value, so we always get the value added to facter.
|
1468
|
-
:hook => proc
|
1468
|
+
:hook => proc do |value|
|
1469
|
+
paths = value.split(File::PATH_SEPARATOR)
|
1470
|
+
Facter.search(*paths)
|
1471
|
+
end
|
1472
|
+
}
|
1469
1473
|
)
|
1470
1474
|
|
1471
1475
|
|
@@ -23,18 +23,25 @@ class Puppet::Indirector::ResourceType::Parser < Puppet::Indirector::Code
|
|
23
23
|
# @return [Puppet::Resource::Type, nil]
|
24
24
|
# @api public
|
25
25
|
def find(request)
|
26
|
-
|
26
|
+
begin
|
27
|
+
# This is a fix in 3.x that will be replaced with the use of a context
|
28
|
+
# (That is not available until 3.5).
|
29
|
+
$squelsh_parse_errors = true
|
30
|
+
krt = resource_types_in(request.environment)
|
27
31
|
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
32
|
+
# This is a bit ugly.
|
33
|
+
[:hostclass, :definition, :node].each do |type|
|
34
|
+
# We have to us 'find_<type>' here because it will
|
35
|
+
# load any missing types from disk, whereas the plain
|
36
|
+
# '<type>' method only returns from memory.
|
37
|
+
if r = krt.send("find_#{type}", [""], request.key)
|
38
|
+
return r
|
39
|
+
end
|
35
40
|
end
|
41
|
+
nil
|
42
|
+
ensure
|
43
|
+
$squelsh_parse_errors = false
|
36
44
|
end
|
37
|
-
nil
|
38
45
|
end
|
39
46
|
|
40
47
|
# Search for resource types using a regular expression. Unlike `find`, this
|
@@ -53,39 +60,52 @@ class Puppet::Indirector::ResourceType::Parser < Puppet::Indirector::Code
|
|
53
60
|
#
|
54
61
|
# @api public
|
55
62
|
def search(request)
|
56
|
-
|
57
|
-
|
58
|
-
|
63
|
+
begin
|
64
|
+
# This is a fix in 3.x that will be replaced with the use of a context
|
65
|
+
# (That is not available until 3.5).
|
66
|
+
$squelsh_parse_errors = true
|
59
67
|
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
when "defined_type"
|
64
|
-
krt.definitions.values
|
65
|
-
when "node"
|
66
|
-
krt.nodes.values
|
67
|
-
when nil
|
68
|
-
result_candidates = [krt.hostclasses.values, krt.definitions.values, krt.nodes.values]
|
69
|
-
else
|
70
|
-
raise ArgumentError, "Unrecognized kind filter: " +
|
71
|
-
"'#{request.options[:kind]}', expected one " +
|
72
|
-
" of 'class', 'defined_type', or 'node'."
|
73
|
-
end
|
68
|
+
krt = resource_types_in(request.environment)
|
69
|
+
# Make sure we've got all of the types loaded.
|
70
|
+
krt.loader.import_all
|
74
71
|
|
75
|
-
|
76
|
-
|
77
|
-
|
72
|
+
result_candidates = case request.options[:kind]
|
73
|
+
when "class"
|
74
|
+
krt.hostclasses.values
|
75
|
+
when "defined_type"
|
76
|
+
krt.definitions.values
|
77
|
+
when "node"
|
78
|
+
krt.nodes.values
|
79
|
+
when nil
|
80
|
+
result_candidates = [krt.hostclasses.values, krt.definitions.values, krt.nodes.values]
|
81
|
+
else
|
82
|
+
raise ArgumentError, "Unrecognized kind filter: " +
|
83
|
+
"'#{request.options[:kind]}', expected one " +
|
84
|
+
" of 'class', 'defined_type', or 'node'."
|
85
|
+
end
|
78
86
|
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
87
|
+
result = result_candidates.flatten.reject { |t| t.name == "" }
|
88
|
+
return nil if result.empty?
|
89
|
+
return result if request.key == "*"
|
90
|
+
|
91
|
+
# Strip the regex of any wrapping slashes that might exist
|
92
|
+
key = request.key.sub(/^\//, '').sub(/\/$/, '')
|
93
|
+
begin
|
94
|
+
regex = Regexp.new(key)
|
95
|
+
rescue => detail
|
96
|
+
raise ArgumentError, "Invalid regex '#{request.key}': #{detail}"
|
97
|
+
end
|
98
|
+
|
99
|
+
result.reject! { |t| t.name.to_s !~ regex }
|
100
|
+
return nil if result.empty?
|
101
|
+
result
|
85
102
|
end
|
103
|
+
ensure
|
104
|
+
$squelsh_parse_errors = false
|
105
|
+
end
|
86
106
|
|
87
|
-
|
88
|
-
|
89
|
-
|
107
|
+
def resource_types_in(environment)
|
108
|
+
environment.check_for_reparse
|
109
|
+
environment.known_resource_types
|
90
110
|
end
|
91
111
|
end
|
@@ -154,7 +154,6 @@ module Manager
|
|
154
154
|
name = name.downcase.intern
|
155
155
|
return @types[name] if @types[name]
|
156
156
|
end
|
157
|
-
|
158
157
|
# Try loading the type.
|
159
158
|
if typeloader.load(name, Puppet::Node::Environment.current)
|
160
159
|
Puppet.warning "Loaded puppet/type/#{name} but no class was created" unless @types.include? name
|
@@ -28,6 +28,8 @@ module Puppet::Network::HTTP
|
|
28
28
|
:redirect_limit => 10
|
29
29
|
}
|
30
30
|
|
31
|
+
@@openssl_initialized = false
|
32
|
+
|
31
33
|
# Creates a new HTTP client connection to `host`:`port`.
|
32
34
|
# @param host [String] the host to which this client will connect to
|
33
35
|
# @param port [Fixnum] the port to which this client will connect to
|
@@ -177,6 +179,12 @@ module Puppet::Network::HTTP
|
|
177
179
|
|
178
180
|
# Use cert information from a Puppet client to set up the http object.
|
179
181
|
def cert_setup
|
182
|
+
# PUP-1411, make sure that openssl is initialized before we try to connect
|
183
|
+
if ! @@openssl_initialized
|
184
|
+
OpenSSL::SSL::SSLContext.new
|
185
|
+
@@openssl_initialized = true
|
186
|
+
end
|
187
|
+
|
180
188
|
@verify.setup_connection(@connection)
|
181
189
|
end
|
182
190
|
|
@@ -28,7 +28,10 @@ class Puppet::Network::HTTP::WEBrick
|
|
28
28
|
@listening = true
|
29
29
|
@thread = Thread.new do
|
30
30
|
@server.start do |sock|
|
31
|
-
|
31
|
+
timeout = 10.0
|
32
|
+
if ! IO.select([sock],nil,nil,timeout)
|
33
|
+
raise "Client did not send data within %.1f seconds of connecting" % timeout
|
34
|
+
end
|
32
35
|
sock.accept
|
33
36
|
@server.run(sock)
|
34
37
|
end
|
@@ -19,23 +19,6 @@ end
|
|
19
19
|
# The 'environment' global variable represents the current environment that's
|
20
20
|
# being used in the compiler.
|
21
21
|
#
|
22
|
-
# ### `$known_resource_types`
|
23
|
-
#
|
24
|
-
# The 'known_resource_types' global variable represents a singleton instance
|
25
|
-
# of the Puppet::Resource::TypeCollection class. The variable is discarded
|
26
|
-
# and regenerated if it is accessed by an environment that doesn't match the
|
27
|
-
# environment of the 'known_resource_types'
|
28
|
-
#
|
29
|
-
# This behavior of discarding the known_resource_types every time the
|
30
|
-
# environment changes is not ideal. In the best case this can cause valid data
|
31
|
-
# to be discarded and reloaded. If Puppet is being used with numerous
|
32
|
-
# environments then this penalty will be repeatedly incurred.
|
33
|
-
#
|
34
|
-
# In the worst case (#15106) demonstrates that if a different environment is
|
35
|
-
# accessed during catalog compilation, for whatever reason, the
|
36
|
-
# known_resource_types can be discarded which loses information that cannot
|
37
|
-
# be recovered and can cause a catalog compilation to completely fail.
|
38
|
-
#
|
39
22
|
# ## The root environment
|
40
23
|
#
|
41
24
|
# In addition to normal environments that are defined by the user,there is a
|
@@ -204,20 +187,11 @@ class Puppet::Node::Environment
|
|
204
187
|
# @api public
|
205
188
|
# @return [Puppet::Resource::TypeCollection] The current global TypeCollection
|
206
189
|
def known_resource_types
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
$known_resource_types = nil if $known_resource_types && $known_resource_types.environment != self
|
213
|
-
$known_resource_types ||=
|
214
|
-
if @known_resource_types.nil? or @known_resource_types.require_reparse?
|
215
|
-
@known_resource_types = Puppet::Resource::TypeCollection.new(self)
|
216
|
-
@known_resource_types.import_ast(perform_initial_import, '')
|
217
|
-
@known_resource_types
|
218
|
-
else
|
219
|
-
@known_resource_types
|
220
|
-
end
|
190
|
+
if @known_resource_types.nil?
|
191
|
+
@known_resource_types = Puppet::Resource::TypeCollection.new(self)
|
192
|
+
@known_resource_types.import_ast(perform_initial_import(), '')
|
193
|
+
end
|
194
|
+
@known_resource_types
|
221
195
|
end
|
222
196
|
|
223
197
|
# Yields each modules' plugin directory if the plugin directory (modulename/lib)
|
@@ -393,6 +367,13 @@ class Puppet::Node::Environment
|
|
393
367
|
deps
|
394
368
|
end
|
395
369
|
|
370
|
+
|
371
|
+
def check_for_reparse
|
372
|
+
if @known_resource_types && @known_resource_types.require_reparse?
|
373
|
+
@known_resource_types = nil
|
374
|
+
end
|
375
|
+
end
|
376
|
+
|
396
377
|
# @return [String] The stringified value of the `name` instance variable
|
397
378
|
# @api public
|
398
379
|
def to_s
|
@@ -465,7 +446,7 @@ class Puppet::Node::Environment
|
|
465
446
|
end
|
466
447
|
parser.parse
|
467
448
|
rescue => detail
|
468
|
-
known_resource_types.parse_failed = true
|
449
|
+
@known_resource_types.parse_failed = true
|
469
450
|
|
470
451
|
msg = "Could not parse for environment #{self}: #{detail}"
|
471
452
|
error = Puppet::Error.new(msg)
|
@@ -17,10 +17,9 @@ class Puppet::Parser::Compiler
|
|
17
17
|
include Puppet::Resource::TypeCollectionHelper
|
18
18
|
|
19
19
|
def self.compile(node)
|
20
|
-
$known_resource_types = nil
|
21
20
|
$env_module_directories = nil
|
21
|
+
node.environment.check_for_reparse
|
22
22
|
|
23
|
-
# ...and we actually do the compile now we have caching ready.
|
24
23
|
new(node).compile.to_resource
|
25
24
|
rescue => detail
|
26
25
|
message = "#{detail} on node #{node.name}"
|
@@ -9,21 +9,21 @@ Puppet::Parser::Functions::newfunction(
|
|
9
9
|
This function takes two mandatory arguments: the first should be an Array or a Hash, and the second
|
10
10
|
a parameterized block as produced by the puppet syntax:
|
11
11
|
|
12
|
-
$a.each
|
12
|
+
$a.each |$x| { ... }
|
13
13
|
|
14
14
|
When the first argument is an Array, the parameterized block should define one or two block parameters.
|
15
15
|
For each application of the block, the next element from the array is selected, and it is passed to
|
16
16
|
the block if the block has one parameter. If the block has two parameters, the first is the elements
|
17
17
|
index, and the second the value. The index starts from 0.
|
18
18
|
|
19
|
-
$a.each
|
19
|
+
$a.each |$index, $value| { ... }
|
20
20
|
|
21
21
|
When the first argument is a Hash, the parameterized block should define one or two parameters.
|
22
22
|
When one parameter is defined, the iteration is performed with each entry as an array of `[key, value]`,
|
23
23
|
and when two parameters are defined the iteration is performed with key and value.
|
24
24
|
|
25
|
-
$a.each
|
26
|
-
$a.each
|
25
|
+
$a.each |$entry| { ..."key ${$entry[0]}, value ${$entry[1]}" }
|
26
|
+
$a.each |$key, $value| { ..."key ${key}, value ${value}" }
|
27
27
|
|
28
28
|
- Since 3.2
|
29
29
|
- requires `parser = future`.
|
@@ -95,7 +95,26 @@ class Puppet::Parser::TypeLoader
|
|
95
95
|
@loaded ||= {}
|
96
96
|
loaded_asts = []
|
97
97
|
files.reject { |file| @loaded[file] }.each do |file|
|
98
|
-
|
98
|
+
# NOTE: This ugly implementation will be replaced in Puppet 3.5.
|
99
|
+
# The implementation now makes use of a global variable because the context support is
|
100
|
+
# not available until Puppet 3.5.
|
101
|
+
# The use case is that parsing for the purpose of searching for information
|
102
|
+
# should not abort. There is currently one such use case in indirector/resourcetype/parser
|
103
|
+
#
|
104
|
+
if $squelsh_parse_errors
|
105
|
+
begin
|
106
|
+
loaded_asts << parse_file(file)
|
107
|
+
rescue => e
|
108
|
+
# Resume from errors so that all parseable files would
|
109
|
+
# still be parsed. Mark this file as loaded so that
|
110
|
+
# it would not be parsed next time (handle it as if
|
111
|
+
# it was successfully parsed).
|
112
|
+
Puppet.debug("Unable to parse '#{file}': #{e.message}")
|
113
|
+
end
|
114
|
+
else
|
115
|
+
loaded_asts << parse_file(file)
|
116
|
+
end
|
117
|
+
|
99
118
|
@loaded[file] = true
|
100
119
|
end
|
101
120
|
|
@@ -28,9 +28,11 @@ Puppet::Type.type(:package).provide :dpkg, :parent => Puppet::Provider::Package
|
|
28
28
|
|
29
29
|
# list out all of the packages
|
30
30
|
dpkgquery_piped('-W', '--showformat', self::DPKG_QUERY_FORMAT_STRING) do |pipe|
|
31
|
-
|
32
|
-
|
33
|
-
|
31
|
+
# now turn each returned line into a package object
|
32
|
+
pipe.each_line do |line|
|
33
|
+
if hash = parse_line(line)
|
34
|
+
packages << new(hash)
|
35
|
+
end
|
34
36
|
end
|
35
37
|
end
|
36
38
|
|
@@ -41,33 +43,9 @@ Puppet::Type.type(:package).provide :dpkg, :parent => Puppet::Provider::Package
|
|
41
43
|
|
42
44
|
# Note: self:: is required here to keep these constants in the context of what will
|
43
45
|
# eventually become this Puppet::Type::Package::ProviderDpkg class.
|
44
|
-
self::
|
45
|
-
self::
|
46
|
-
self::
|
47
|
-
self::DPKG_PACKAGE_NOT_FOUND_REGEX = /no package.*match/i
|
48
|
-
self::FIELDS= [:desired, :error, :status, :name, :ensure, :description]
|
49
|
-
self::END_REGEX = %r{^#{self::DPKG_DESCRIPTION_DELIMITER}$}
|
50
|
-
|
51
|
-
# Handles parsing one package's worth of multi-line dpkg-query output. Will
|
52
|
-
# emit warnings if it encounters an initial line that does not match
|
53
|
-
# DPKG_QUERY_FORMAT_STRING. Swallows extra description lines silently.
|
54
|
-
#
|
55
|
-
# @param pipe [IO] the pipe yielded while processing dpkg output
|
56
|
-
# @return [Hash,nil] parsed dpkg-query entry as a hash of FIELDS strings or
|
57
|
-
# nil if we failed to parse
|
58
|
-
# @api private
|
59
|
-
def self.parse_multi_line(pipe)
|
60
|
-
|
61
|
-
line = pipe.gets
|
62
|
-
unless hash = parse_line(line)
|
63
|
-
Puppet.warning "Failed to match dpkg-query line #{line.inspect}" if !self::DPKG_PACKAGE_NOT_FOUND_REGEX.match(line)
|
64
|
-
return nil
|
65
|
-
end
|
66
|
-
|
67
|
-
consume_excess_description(pipe)
|
68
|
-
|
69
|
-
return hash
|
70
|
-
end
|
46
|
+
self::DPKG_QUERY_FORMAT_STRING = %Q{'${Status} ${Package} ${Version}\\n'}
|
47
|
+
self::FIELDS_REGEX = %r{^(\S+) +(\S+) +(\S+) (\S+) (\S*)$}
|
48
|
+
self::FIELDS= [:desired, :error, :status, :name, :ensure]
|
71
49
|
|
72
50
|
# @param line [String] one line of dpkg-query output
|
73
51
|
# @return [Hash,nil] a hash of FIELDS or nil if we failed to match
|
@@ -90,31 +68,13 @@ Puppet::Type.type(:package).provide :dpkg, :parent => Puppet::Provider::Package
|
|
90
68
|
hash[:ensure] = :absent
|
91
69
|
end
|
92
70
|
hash[:ensure] = :held if hash[:desired] == 'hold'
|
71
|
+
else
|
72
|
+
Puppet.debug("Failed to match dpkg-query line #{line.inspect}")
|
93
73
|
end
|
94
74
|
|
95
75
|
return hash
|
96
76
|
end
|
97
77
|
|
98
|
-
# Silently consumes the extra description lines from dpkg-query and brings
|
99
|
-
# us to the next package entry start.
|
100
|
-
#
|
101
|
-
# @note dpkg-query Description field has a one line summary and a multi-line
|
102
|
-
# description. dpkg-query binary:Summary is what we want to use but was
|
103
|
-
# introduced in 2012 dpkg 1.16.2
|
104
|
-
# (https://launchpad.net/debian/+source/dpkg/1.16.2) and is not not available
|
105
|
-
# in older Debian versions. So we're placing a delimiter marker at the end
|
106
|
-
# of the description so we can consume and ignore the multiline description
|
107
|
-
# without issuing warnings
|
108
|
-
#
|
109
|
-
# @param pipe [IO] the pipe yielded while processing dpkg output
|
110
|
-
# @return nil
|
111
|
-
def self.consume_excess_description(pipe)
|
112
|
-
until pipe.eof?
|
113
|
-
break if self::END_REGEX.match(pipe.gets)
|
114
|
-
end
|
115
|
-
return nil
|
116
|
-
end
|
117
|
-
|
118
78
|
public
|
119
79
|
|
120
80
|
def install
|
@@ -154,14 +114,13 @@ Puppet::Type.type(:package).provide :dpkg, :parent => Puppet::Provider::Package
|
|
154
114
|
|
155
115
|
# list out our specific package
|
156
116
|
begin
|
157
|
-
|
117
|
+
output = dpkgquery(
|
158
118
|
"-W",
|
159
119
|
"--showformat",
|
160
120
|
self.class::DPKG_QUERY_FORMAT_STRING,
|
161
121
|
@resource[:name]
|
162
|
-
)
|
163
|
-
|
164
|
-
end
|
122
|
+
)
|
123
|
+
hash = self.class.parse_line(output)
|
165
124
|
rescue Puppet::ExecutionFailure
|
166
125
|
# dpkg-query exits 1 if the package is not found.
|
167
126
|
return {:ensure => :purged, :status => 'missing', :name => @resource[:name], :error => 'ok'}
|