puppet 6.14.0 → 6.15.0
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 +4 -4
- data/Gemfile.lock +15 -15
- data/ext/windows/service/daemon.rb +3 -3
- data/lib/puppet.rb +1 -1
- data/lib/puppet/agent.rb +2 -10
- data/lib/puppet/application/agent.rb +2 -1
- data/lib/puppet/application/filebucket.rb +5 -14
- data/lib/puppet/application/ssl.rb +2 -2
- data/lib/puppet/configurer.rb +7 -3
- data/lib/puppet/configurer/plugin_handler.rb +1 -1
- data/lib/puppet/defaults.rb +22 -2
- data/lib/puppet/environments.rb +4 -5
- data/lib/puppet/face/plugin.rb +1 -1
- data/lib/puppet/file_system/file_impl.rb +13 -9
- data/lib/puppet/forge/repository.rb +1 -1
- data/lib/puppet/functions/call.rb +1 -1
- data/lib/puppet/functions/reduce.rb +2 -4
- data/lib/puppet/http.rb +2 -0
- data/lib/puppet/http/client.rb +191 -52
- data/lib/puppet/http/external_client.rb +96 -0
- data/lib/puppet/http/redirector.rb +34 -0
- data/lib/puppet/http/resolver.rb +46 -3
- data/lib/puppet/http/resolver/server_list.rb +75 -15
- data/lib/puppet/http/resolver/settings.rb +22 -2
- data/lib/puppet/http/resolver/srv.rb +28 -2
- data/lib/puppet/http/response.rb +63 -1
- data/lib/puppet/http/retry_after_handler.rb +39 -0
- data/lib/puppet/http/service.rb +67 -1
- data/lib/puppet/http/service/ca.rb +71 -9
- data/lib/puppet/http/service/compiler.rb +213 -11
- data/lib/puppet/http/service/file_server.rb +105 -4
- data/lib/puppet/http/service/report.rb +36 -3
- data/lib/puppet/http/session.rb +59 -8
- data/lib/puppet/indirector/catalog/rest.rb +2 -1
- data/lib/puppet/indirector/facts/rest.rb +2 -1
- data/lib/puppet/indirector/file_bucket_file/rest.rb +48 -0
- data/lib/puppet/indirector/file_metadata/rest.rb +4 -2
- data/lib/puppet/indirector/node/rest.rb +2 -1
- data/lib/puppet/indirector/report/yaml.rb +23 -0
- data/lib/puppet/indirector/status/rest.rb +2 -1
- data/lib/puppet/metatype/manager.rb +80 -80
- data/lib/puppet/network/http/base_pool.rb +6 -1
- data/lib/puppet/network/http/pool.rb +2 -4
- data/lib/puppet/network/http_pool.rb +1 -0
- data/lib/puppet/node/environment.rb +11 -1
- data/lib/puppet/pal/pal_impl.rb +1 -29
- data/lib/puppet/parser/compiler.rb +14 -7
- data/lib/puppet/parser/functions.rb +18 -13
- data/lib/puppet/pops/loaders.rb +7 -5
- data/lib/puppet/provider/group/windows_adsi.rb +3 -3
- data/lib/puppet/provider/package/apt.rb +61 -1
- data/lib/puppet/provider/package/dnfmodule.rb +39 -12
- data/lib/puppet/provider/package/gem.rb +41 -7
- data/lib/puppet/provider/package/pacman.rb +2 -5
- data/lib/puppet/provider/package/pip.rb +105 -33
- data/lib/puppet/provider/package/pip3.rb +0 -2
- data/lib/puppet/provider/package/pkgdmg.rb +1 -1
- data/lib/puppet/provider/package/pkgng.rb +16 -4
- data/lib/puppet/provider/package/puppet_gem.rb +6 -2
- data/lib/puppet/provider/package/rpm.rb +6 -213
- data/lib/puppet/provider/package/yum.rb +92 -19
- data/lib/puppet/provider/service/systemd.rb +2 -1
- data/lib/puppet/reports/http.rb +13 -11
- data/lib/puppet/resource/type_collection.rb +20 -16
- data/lib/puppet/ssl.rb +1 -0
- data/lib/puppet/ssl/host.rb +4 -4
- data/lib/puppet/ssl/oids.rb +1 -0
- data/lib/puppet/ssl/state_machine.rb +50 -33
- data/lib/puppet/transaction/report.rb +2 -2
- data/lib/puppet/type.rb +6 -1
- data/lib/puppet/type/file/source.rb +4 -2
- data/lib/puppet/type/package.rb +25 -2
- data/lib/puppet/type/user.rb +0 -19
- data/lib/puppet/util/at_fork.rb +1 -1
- data/lib/puppet/util/autoload.rb +3 -0
- data/lib/puppet/util/instance_loader.rb +14 -10
- data/lib/puppet/util/package/version/debian.rb +175 -0
- data/lib/puppet/util/package/version/gem.rb +15 -0
- data/lib/puppet/util/package/version/pip.rb +167 -0
- data/lib/puppet/util/package/version/range.rb +50 -0
- data/lib/puppet/util/package/version/range/gt.rb +14 -0
- data/lib/puppet/util/package/version/range/gt_eq.rb +14 -0
- data/lib/puppet/util/package/version/range/lt.rb +14 -0
- data/lib/puppet/util/package/version/range/lt_eq.rb +14 -0
- data/lib/puppet/util/package/version/range/min_max.rb +21 -0
- data/lib/puppet/util/package/version/range/simple.rb +11 -0
- data/lib/puppet/util/package/version/rpm.rb +73 -0
- data/lib/puppet/util/pidlock.rb +13 -7
- data/lib/puppet/util/platform.rb +5 -0
- data/lib/puppet/util/rpm_compare.rb +193 -0
- data/lib/puppet/util/windows/adsi.rb +2 -2
- data/lib/puppet/util/windows/process.rb +15 -14
- data/lib/puppet/util/windows/security.rb +1 -0
- data/lib/puppet/util/windows/sid.rb +3 -3
- data/lib/puppet/version.rb +1 -1
- data/locales/puppet.pot +207 -201
- data/man/man5/puppet.conf.5 +11 -3
- data/man/man8/puppet-agent.8 +1 -1
- data/man/man8/puppet-apply.8 +1 -1
- data/man/man8/puppet-catalog.8 +1 -1
- data/man/man8/puppet-config.8 +1 -1
- data/man/man8/puppet-describe.8 +1 -1
- data/man/man8/puppet-device.8 +1 -1
- data/man/man8/puppet-doc.8 +1 -1
- data/man/man8/puppet-epp.8 +1 -1
- data/man/man8/puppet-facts.8 +1 -1
- data/man/man8/puppet-filebucket.8 +1 -1
- data/man/man8/puppet-generate.8 +1 -1
- data/man/man8/puppet-help.8 +1 -1
- data/man/man8/puppet-key.8 +1 -1
- data/man/man8/puppet-lookup.8 +1 -1
- data/man/man8/puppet-man.8 +1 -1
- data/man/man8/puppet-module.8 +1 -1
- data/man/man8/puppet-node.8 +1 -1
- data/man/man8/puppet-parser.8 +1 -1
- data/man/man8/puppet-plugin.8 +1 -1
- data/man/man8/puppet-report.8 +1 -1
- data/man/man8/puppet-resource.8 +1 -1
- data/man/man8/puppet-script.8 +1 -1
- data/man/man8/puppet-ssl.8 +1 -1
- data/man/man8/puppet-status.8 +1 -1
- data/man/man8/puppet.8 +2 -2
- data/spec/fixtures/ssl/unknown-127.0.0.1-key.pem +67 -0
- data/spec/fixtures/ssl/unknown-127.0.0.1.pem +48 -0
- data/spec/fixtures/ssl/unknown-ca-key.pem +67 -0
- data/spec/fixtures/ssl/unknown-ca.pem +59 -0
- data/spec/fixtures/unit/provider/package/dnfmodule/{dnf-module-list-installed.txt → dnf-module-list-enabled.txt} +2 -0
- data/spec/fixtures/unit/provider/package/pkgng/pkg.version +2 -0
- data/spec/fixtures/unit/provider/package/yum/yum-check-update-subscription-manager.txt +9 -0
- data/spec/fixtures/unit/provider/service/systemd/list_unit_files_services +9 -0
- data/spec/integration/application/agent_spec.rb +329 -0
- data/spec/integration/application/apply_spec.rb +132 -3
- data/spec/integration/application/filebucket_spec.rb +190 -0
- data/spec/integration/application/plugin_spec.rb +50 -0
- data/spec/integration/http/client_spec.rb +34 -40
- data/spec/integration/indirector/report/yaml.rb +83 -0
- data/spec/integration/module_tool/forge_spec.rb +2 -15
- data/spec/integration/network/http_pool_spec.rb +11 -19
- data/spec/integration/node/environment_spec.rb +15 -0
- data/spec/integration/util/windows/adsi_spec.rb +1 -1
- data/spec/lib/puppet/test_ca.rb +2 -2
- data/spec/lib/puppet_spec/https.rb +10 -7
- data/spec/lib/puppet_spec/puppetserver.rb +119 -0
- data/spec/shared_contexts/https.rb +29 -0
- data/spec/unit/agent_spec.rb +33 -25
- data/spec/unit/application/agent_spec.rb +5 -1
- data/spec/unit/application/device_spec.rb +2 -2
- data/spec/unit/application/filebucket_spec.rb +22 -2
- data/spec/unit/configurer_spec.rb +1 -1
- data/spec/unit/defaults_spec.rb +24 -1
- data/spec/unit/environments_spec.rb +8 -0
- data/spec/unit/file_system_spec.rb +10 -0
- data/spec/unit/http/client_spec.rb +105 -46
- data/spec/unit/http/external_client_spec.rb +201 -0
- data/spec/unit/http/resolver_spec.rb +20 -0
- data/spec/unit/http/service/ca_spec.rb +25 -2
- data/spec/unit/http/service/compiler_spec.rb +184 -6
- data/spec/unit/http/service/file_server_spec.rb +35 -3
- data/spec/unit/http/service/report_spec.rb +3 -1
- data/spec/unit/http/service_spec.rb +3 -3
- data/spec/unit/http/session_spec.rb +56 -7
- data/spec/unit/indirector/file_bucket_file/rest_spec.rb +82 -2
- data/spec/unit/network/http/pool_spec.rb +3 -3
- data/spec/unit/node/environment_spec.rb +16 -0
- data/spec/unit/provider/group/windows_adsi_spec.rb +43 -10
- data/spec/unit/provider/package/apt_spec.rb +30 -0
- data/spec/unit/provider/package/dnfmodule_spec.rb +33 -14
- data/spec/unit/provider/package/gem_spec.rb +40 -0
- data/spec/unit/provider/package/pacman_spec.rb +6 -21
- data/spec/unit/provider/package/pip_spec.rb +26 -3
- data/spec/unit/provider/package/pkgdmg_spec.rb +1 -1
- data/spec/unit/provider/package/pkgng_spec.rb +38 -0
- data/spec/unit/provider/package/puppet_gem_spec.rb +8 -0
- data/spec/unit/provider/package/rpm_spec.rb +0 -212
- data/spec/unit/provider/package/yum_spec.rb +235 -1
- data/spec/unit/provider/service/systemd_spec.rb +10 -1
- data/spec/unit/provider/user/windows_adsi_spec.rb +3 -3
- data/spec/unit/puppet_pal_2pec.rb +0 -29
- data/spec/unit/reports/http_spec.rb +70 -52
- data/spec/unit/ssl/host_spec.rb +4 -2
- data/spec/unit/ssl/oids_spec.rb +1 -0
- data/spec/unit/ssl/state_machine_spec.rb +38 -6
- data/spec/unit/transaction/report_spec.rb +4 -0
- data/spec/unit/util/at_fork_spec.rb +2 -2
- data/spec/unit/util/package/version/debian_spec.rb +83 -0
- data/spec/unit/util/package/version/pip_spec.rb +464 -0
- data/spec/unit/util/package/version/range_spec.rb +154 -0
- data/spec/unit/util/package/version/rpm_spec.rb +121 -0
- data/spec/unit/util/pidlock_spec.rb +83 -47
- data/spec/unit/util/rpm_compare_spec.rb +196 -0
- data/spec/unit/util/windows/adsi_spec.rb +4 -4
- data/spec/unit/util/windows/sid_spec.rb +2 -2
- data/tasks/generate_cert_fixtures.rake +15 -1
- metadata +51 -6
- data/spec/integration/faces/plugin_spec.rb +0 -63
@@ -24,7 +24,7 @@ Puppet::Type.type(:group).provide :windows_adsi do
|
|
24
24
|
# since the default array_matching comparison is not commutative
|
25
25
|
|
26
26
|
# dupes automatically weeded out when hashes built
|
27
|
-
current_members = Puppet::Util::Windows::ADSI::Group.name_sid_hash(current)
|
27
|
+
current_members = Puppet::Util::Windows::ADSI::Group.name_sid_hash(current, true)
|
28
28
|
specified_members = Puppet::Util::Windows::ADSI::Group.name_sid_hash(should)
|
29
29
|
|
30
30
|
current_sids = current_members.keys.to_a
|
@@ -52,7 +52,7 @@ Puppet::Type.type(:group).provide :windows_adsi do
|
|
52
52
|
account = sid.account
|
53
53
|
end
|
54
54
|
resource.debug("#{sid.domain}\\#{account} (#{sid.sid})")
|
55
|
-
"#{sid.domain}\\#{account}"
|
55
|
+
sid.domain ? "#{sid.domain}\\#{account}" : account
|
56
56
|
end
|
57
57
|
return users.join(',')
|
58
58
|
end
|
@@ -66,7 +66,7 @@ Puppet::Type.type(:group).provide :windows_adsi do
|
|
66
66
|
end
|
67
67
|
|
68
68
|
def members
|
69
|
-
@members ||= Puppet::Util::Windows::ADSI::Group.name_sid_hash(group.members)
|
69
|
+
@members ||= Puppet::Util::Windows::ADSI::Group.name_sid_hash(group.members, true)
|
70
70
|
|
71
71
|
# @members.keys returns an array of SIDs. We need to convert those SIDs into
|
72
72
|
# names so that `puppet resource` prints the right output.
|
@@ -1,7 +1,11 @@
|
|
1
|
+
require 'puppet/util/package/version/range'
|
2
|
+
require 'puppet/util/package/version/debian'
|
3
|
+
|
1
4
|
Puppet::Type.type(:package).provide :apt, :parent => :dpkg, :source => :dpkg do
|
2
5
|
# Provide sorting functionality
|
3
6
|
include Puppet::Util::Package
|
4
|
-
|
7
|
+
DebianVersion = Puppet::Util::Package::Version::Debian
|
8
|
+
VersionRange = Puppet::Util::Package::Version::Range
|
5
9
|
desc "Package management via `apt-get`.
|
6
10
|
|
7
11
|
This provider supports the `install_options` attribute, which allows command-line flags to be passed to apt-get.
|
@@ -44,12 +48,41 @@ Puppet::Type.type(:package).provide :apt, :parent => :dpkg, :source => :dpkg do
|
|
44
48
|
end
|
45
49
|
end
|
46
50
|
|
51
|
+
def best_version(should_range)
|
52
|
+
available_versions = SortedSet.new
|
53
|
+
|
54
|
+
output = aptcache :madison, @resource[:name]
|
55
|
+
output.each_line do |line|
|
56
|
+
is = line.split('|')[1].strip
|
57
|
+
begin
|
58
|
+
is_version = DebianVersion.parse(is)
|
59
|
+
available_versions << is_version if should_range.include?(is_version)
|
60
|
+
rescue DebianVersion::ValidationFailure
|
61
|
+
Puppet.debug("Cannot parse #{is} as a debian version")
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
return available_versions.to_a.last unless available_versions.empty?
|
66
|
+
|
67
|
+
Puppet.debug("No available version for package #{@resource[:name]} is included in range #{should_range}")
|
68
|
+
should_range
|
69
|
+
end
|
70
|
+
|
47
71
|
# Install a package using 'apt-get'. This function needs to support
|
48
72
|
# installing a specific version.
|
49
73
|
def install
|
50
74
|
self.run_preseed if @resource[:responsefile]
|
51
75
|
should = @resource[:ensure]
|
52
76
|
|
77
|
+
if should.is_a?(String)
|
78
|
+
begin
|
79
|
+
should_range = VersionRange.parse(should, DebianVersion)
|
80
|
+
should = best_version(should_range)
|
81
|
+
rescue VersionRange::ValidationFailure, DebianVersion::ValidationFailure
|
82
|
+
Puppet.debug("Cannot parse #{should} as a debian version range, falling through")
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
53
86
|
checkforcdrom
|
54
87
|
cmd = %w{-q -y}
|
55
88
|
|
@@ -130,4 +163,31 @@ Puppet::Type.type(:package).provide :apt, :parent => :dpkg, :source => :dpkg do
|
|
130
163
|
def install_options
|
131
164
|
join_options(@resource[:install_options])
|
132
165
|
end
|
166
|
+
|
167
|
+
def insync?(is)
|
168
|
+
# this is called after the generic version matching logic (insync? for the
|
169
|
+
# type), so we only get here if should != is
|
170
|
+
|
171
|
+
return false unless is && is != :absent
|
172
|
+
|
173
|
+
#if 'should' is a range and 'is' a debian version we should check if 'should' includes 'is'
|
174
|
+
should = @resource[:ensure]
|
175
|
+
|
176
|
+
return false unless is.is_a?(String) && should.is_a?(String)
|
177
|
+
|
178
|
+
begin
|
179
|
+
should_range = VersionRange.parse(should, DebianVersion)
|
180
|
+
rescue VersionRange::ValidationFailure, DebianVersion::ValidationFailure
|
181
|
+
Puppet.debug("Cannot parse #{should} as a debian version range")
|
182
|
+
return false
|
183
|
+
end
|
184
|
+
|
185
|
+
begin
|
186
|
+
is_version = DebianVersion.parse(is)
|
187
|
+
rescue DebianVersion::ValidationFailure
|
188
|
+
Puppet.debug("Cannot parse #{is} as a debian version")
|
189
|
+
return false
|
190
|
+
end
|
191
|
+
should_range.include?(is_version)
|
192
|
+
end
|
133
193
|
end
|
@@ -34,14 +34,22 @@ Puppet::Type.type(:package).provide :dnfmodule, :parent => :dnf do
|
|
34
34
|
|
35
35
|
def self.instances
|
36
36
|
packages = []
|
37
|
-
cmd = "#{command(:dnf)} module list --
|
37
|
+
cmd = "#{command(:dnf)} module list --enabled -d 0 -e #{error_level}"
|
38
38
|
execute(cmd).each_line do |line|
|
39
|
-
|
40
|
-
line
|
39
|
+
# select only lines with actual packages since DNF clutters the output
|
40
|
+
next unless line =~ /\[[ei]\][, ]/
|
41
|
+
line.gsub!(/\[d\]/, '') # we don't care about the default flag
|
42
|
+
|
43
|
+
flavor = if line.include?('[i]')
|
44
|
+
line.split('[i]').first.split.last
|
45
|
+
else
|
46
|
+
:absent
|
47
|
+
end
|
48
|
+
|
41
49
|
packages << new(
|
42
50
|
name: line.split[0],
|
43
51
|
ensure: line.split[1],
|
44
|
-
flavor:
|
52
|
+
flavor: flavor,
|
45
53
|
provider: name
|
46
54
|
)
|
47
55
|
end
|
@@ -55,28 +63,43 @@ Puppet::Type.type(:package).provide :dnfmodule, :parent => :dnf do
|
|
55
63
|
pkg ? pkg.properties : nil
|
56
64
|
end
|
57
65
|
|
58
|
-
def reset
|
59
|
-
execute([command(:dnf), 'module', 'reset', '-d', '0', '-e', self.class.error_level, '-y', @resource[:name]])
|
60
|
-
end
|
61
|
-
|
62
66
|
# to install specific streams and profiles:
|
63
67
|
# $ dnf module install module-name:stream/profile
|
64
68
|
# $ dnf module install perl:5.24/minimal
|
65
69
|
# if unspecified, they will be defaulted (see [d] param in dnf module list output)
|
66
70
|
def install
|
67
|
-
args = @resource[:name]
|
68
71
|
# ensure we start fresh (remove existing stream)
|
69
72
|
uninstall unless [:absent, :purged].include?(@property_hash[:ensure])
|
73
|
+
|
74
|
+
args = @resource[:name].dup
|
70
75
|
case @resource[:ensure]
|
71
76
|
when true, false, Symbol
|
72
77
|
# pass
|
73
78
|
else
|
74
79
|
args << ":#{@resource[:ensure]}"
|
75
80
|
end
|
76
|
-
if @resource[:flavor]
|
77
|
-
|
81
|
+
args << "/#{@resource[:flavor]}" if @resource[:flavor]
|
82
|
+
|
83
|
+
if @resource[:enable_only] == true
|
84
|
+
enable(args)
|
85
|
+
else
|
86
|
+
begin
|
87
|
+
execute([command(:dnf), 'module', 'install', '-d', '0', '-e', self.class.error_level, '-y', args])
|
88
|
+
rescue Puppet::ExecutionFailure => e
|
89
|
+
# module has no default profile and no profile was requested, so just enable the stream
|
90
|
+
# DNF versions prior to 4.2.8 do not need this workaround
|
91
|
+
# see https://bugzilla.redhat.com/show_bug.cgi?id=1669527
|
92
|
+
if @resource[:flavor] == nil && e.message =~ /^missing groups or modules: #{Regexp.quote(@resource[:name])}$/
|
93
|
+
enable(args)
|
94
|
+
else
|
95
|
+
raise
|
96
|
+
end
|
97
|
+
end
|
78
98
|
end
|
79
|
-
|
99
|
+
end
|
100
|
+
|
101
|
+
def enable(args = @resource[:name])
|
102
|
+
execute([command(:dnf), 'module', 'enable', '-d', '0', '-e', self.class.error_level, '-y', args])
|
80
103
|
end
|
81
104
|
|
82
105
|
def uninstall
|
@@ -84,6 +107,10 @@ Puppet::Type.type(:package).provide :dnfmodule, :parent => :dnf do
|
|
84
107
|
reset # reset module to the default stream
|
85
108
|
end
|
86
109
|
|
110
|
+
def reset
|
111
|
+
execute([command(:dnf), 'module', 'reset', '-d', '0', '-e', self.class.error_level, '-y', @resource[:name]])
|
112
|
+
end
|
113
|
+
|
87
114
|
def flavor
|
88
115
|
@property_hash[:flavor]
|
89
116
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
require 'puppet/util/package/version/gem'
|
2
|
+
require 'puppet/util/package/version/range'
|
1
3
|
require 'puppet/provider/package_targetable'
|
2
4
|
require 'uri'
|
3
5
|
|
@@ -15,7 +17,10 @@ Puppet::Type.type(:package).provide :gem, :parent => Puppet::Provider::Package::
|
|
15
17
|
These options should be specified as an array where each element is either a
|
16
18
|
string or a hash."
|
17
19
|
|
18
|
-
has_feature :versionable, :install_options, :uninstall_options, :targetable
|
20
|
+
has_feature :versionable, :install_options, :uninstall_options, :targetable, :version_ranges
|
21
|
+
|
22
|
+
GEM_VERSION = Puppet::Util::Package::Version::Gem
|
23
|
+
GEM_VERSION_RANGE = Puppet::Util::Package::Version::Range
|
19
24
|
|
20
25
|
# Override the specificity method to return 1 if gem is not set as default provider
|
21
26
|
def self.specificity
|
@@ -125,16 +130,35 @@ Puppet::Type.type(:package).provide :gem, :parent => Puppet::Provider::Package::
|
|
125
130
|
|
126
131
|
def insync?(is)
|
127
132
|
return false unless is && is != :absent
|
133
|
+
is = [is] unless is.is_a? Array
|
134
|
+
should = @resource[:ensure]
|
128
135
|
|
136
|
+
unless should =~ Regexp.union(/,/, Gem::Requirement::PATTERN)
|
137
|
+
begin
|
138
|
+
should_range = GEM_VERSION_RANGE.parse(should, GEM_VERSION)
|
139
|
+
rescue GEM_VERSION_RANGE::ValidationFailure, GEM_VERSION::ValidationFailure
|
140
|
+
Puppet.debug("Cannot parse #{should} as a ruby gem version range")
|
141
|
+
return false
|
142
|
+
end
|
143
|
+
|
144
|
+
return is.any? do |version|
|
145
|
+
begin
|
146
|
+
should_range.include?(GEM_VERSION.parse(version))
|
147
|
+
rescue GEM_VERSION::ValidationFailure
|
148
|
+
Puppet.debug("Cannot parse #{version} as a ruby gem version")
|
149
|
+
false
|
150
|
+
end
|
151
|
+
end
|
152
|
+
end
|
153
|
+
|
129
154
|
begin
|
130
|
-
|
155
|
+
# Range intersections are not supported by Gem::Requirement, so just split by comma.
|
156
|
+
dependency = Gem::Dependency.new('', should.split(','))
|
131
157
|
rescue ArgumentError
|
132
158
|
# Bad requirements will cause an error during gem command invocation, so just return not in sync
|
133
159
|
return false
|
134
160
|
end
|
135
161
|
|
136
|
-
is = [is] unless is.is_a? Array
|
137
|
-
|
138
162
|
# Check if any version matches the dependency
|
139
163
|
is.any? { |version| dependency.match?('', version) }
|
140
164
|
end
|
@@ -148,12 +172,22 @@ Puppet::Type.type(:package).provide :gem, :parent => Puppet::Provider::Package::
|
|
148
172
|
command = resource_or_provider_command
|
149
173
|
command_options = ["install"]
|
150
174
|
command_options += install_options if resource[:install_options]
|
175
|
+
should = resource[:ensure]
|
176
|
+
|
177
|
+
unless should =~ Regexp.union(/,/, Gem::Requirement::PATTERN)
|
178
|
+
begin
|
179
|
+
should_range = GEM_VERSION_RANGE.parse(should, GEM_VERSION)
|
180
|
+
should = should_range.to_gem_version
|
181
|
+
useversion = true
|
182
|
+
rescue GEM_VERSION_RANGE::ValidationFailure, GEM_VERSION::ValidationFailure
|
183
|
+
Puppet.debug("Cannot parse #{should} as a ruby gem version range. Falling through.")
|
184
|
+
end
|
185
|
+
end
|
151
186
|
|
152
187
|
if Puppet::Util::Platform.windows?
|
153
|
-
|
154
|
-
command_options << "-v" << %Q["#{version}"] if (! resource[:ensure].is_a? Symbol) and useversion
|
188
|
+
command_options << "-v" << %Q["#{should}"] if useversion && !should.is_a?(Symbol)
|
155
189
|
else
|
156
|
-
command_options << "-v" <<
|
190
|
+
command_options << "-v" << should if useversion && !should.is_a?(Symbol)
|
157
191
|
end
|
158
192
|
|
159
193
|
if Puppet::Util::Package.versioncmp(rubygem_version(command), '2.0.0') == -1
|
@@ -132,9 +132,6 @@ Puppet::Type.type(:package).provide :pacman, :parent => Puppet::Provider::Packag
|
|
132
132
|
|
133
133
|
# We rescue the main check from Pacman with a check on the AUR using yaourt, if installed
|
134
134
|
def latest
|
135
|
-
# Synchronize the database
|
136
|
-
pacman "-Sy"
|
137
|
-
|
138
135
|
resource_name = @resource[:name]
|
139
136
|
|
140
137
|
# If target is a group, construct the group version
|
@@ -243,7 +240,7 @@ Puppet::Type.type(:package).provide :pacman, :parent => Puppet::Provider::Packag
|
|
243
240
|
else
|
244
241
|
fail _("Source %{source} is not supported by pacman") % { source: source }
|
245
242
|
end
|
246
|
-
pacman "--noconfirm", "--noprogressbar", "-
|
243
|
+
pacman "--noconfirm", "--noprogressbar", "-S"
|
247
244
|
pacman "--noconfirm", "--noprogressbar", "-U", source
|
248
245
|
end
|
249
246
|
|
@@ -255,7 +252,7 @@ Puppet::Type.type(:package).provide :pacman, :parent => Puppet::Provider::Packag
|
|
255
252
|
|
256
253
|
cmd = %w{--noconfirm --needed --noprogressbar}
|
257
254
|
cmd += install_options if @resource[:install_options]
|
258
|
-
cmd << "-
|
255
|
+
cmd << "-S" << resource_name
|
259
256
|
|
260
257
|
if self.class.yaourt?
|
261
258
|
yaourt(*cmd)
|
@@ -1,6 +1,8 @@
|
|
1
1
|
# Puppet package provider for Python's `pip` package management frontend.
|
2
2
|
# <http://pip.pypa.io/>
|
3
3
|
|
4
|
+
require 'puppet/util/package/version/pip'
|
5
|
+
require 'puppet/util/package/version/range'
|
4
6
|
require 'puppet/provider/package_targetable'
|
5
7
|
require 'puppet/util/http_proxy'
|
6
8
|
|
@@ -11,7 +13,10 @@ Puppet::Type.type(:package).provide :pip, :parent => ::Puppet::Provider::Package
|
|
11
13
|
This provider supports the `install_options` attribute, which allows command-line flags to be passed to pip.
|
12
14
|
These options should be specified as an array where each element is either a string or a hash."
|
13
15
|
|
14
|
-
has_feature :installable, :uninstallable, :upgradeable, :versionable, :install_options, :targetable
|
16
|
+
has_feature :installable, :uninstallable, :upgradeable, :versionable, :version_ranges, :install_options, :targetable
|
17
|
+
|
18
|
+
PIP_VERSION = Puppet::Util::Package::Version::Pip
|
19
|
+
PIP_VERSION_RANGE = Puppet::Util::Package::Version::Range
|
15
20
|
|
16
21
|
# Override the specificity method to return 1 if pip is not set as default provider
|
17
22
|
def self.specificity
|
@@ -25,7 +30,6 @@ Puppet::Type.type(:package).provide :pip, :parent => ::Puppet::Provider::Package
|
|
25
30
|
|
26
31
|
# Define the default provider package command name when the provider is targetable.
|
27
32
|
# Required by Puppet::Provider::Package::Targetable::resource_or_provider_command
|
28
|
-
|
29
33
|
def self.provider_command
|
30
34
|
# Ensure pip can upgrade pip, which usually puts pip into a new path /usr/local/bin/pip (compared to /usr/bin/pip)
|
31
35
|
self.cmd.map { |c| which(c) }.find { |c| c != nil }
|
@@ -58,7 +62,6 @@ Puppet::Type.type(:package).provide :pip, :parent => ::Puppet::Provider::Package
|
|
58
62
|
|
59
63
|
# Return an array of structured information about every installed package
|
60
64
|
# that's managed by `pip` or an empty array if `pip` is not available.
|
61
|
-
|
62
65
|
def self.instances(target_command = nil)
|
63
66
|
if target_command
|
64
67
|
command = target_command
|
@@ -72,7 +75,7 @@ Puppet::Type.type(:package).provide :pip, :parent => ::Puppet::Provider::Package
|
|
72
75
|
|
73
76
|
command_options = ['freeze']
|
74
77
|
command_version = self.pip_version(command)
|
75
|
-
if
|
78
|
+
if compare_pip_versions(command_version, '8.1.0') >= 0
|
76
79
|
command_options << '--all'
|
77
80
|
end
|
78
81
|
|
@@ -88,7 +91,7 @@ Puppet::Type.type(:package).provide :pip, :parent => ::Puppet::Provider::Package
|
|
88
91
|
# Pip can also upgrade pip, but it's not listed in freeze so need to special case it
|
89
92
|
# Pip list would also show pip installed version, but "pip list" doesn't exist for older versions of pip (E.G v1.0)
|
90
93
|
# Not needed when "pip freeze --all" is available.
|
91
|
-
if
|
94
|
+
if compare_pip_versions(command_version, '8.1.0') == -1
|
92
95
|
packages << new({:ensure => command_version, :name => File.basename(command), :provider => name, :command => command})
|
93
96
|
end
|
94
97
|
|
@@ -105,7 +108,6 @@ Puppet::Type.type(:package).provide :pip, :parent => ::Puppet::Provider::Package
|
|
105
108
|
|
106
109
|
# Return structured information about a particular package or `nil`
|
107
110
|
# if the package is not installed or `pip` itself is not available.
|
108
|
-
|
109
111
|
def query
|
110
112
|
command = resource_or_provider_command
|
111
113
|
self.class.validate_command(command)
|
@@ -116,24 +118,43 @@ Puppet::Type.type(:package).provide :pip, :parent => ::Puppet::Provider::Package
|
|
116
118
|
return nil
|
117
119
|
end
|
118
120
|
|
119
|
-
#
|
120
|
-
# honoring local pip config such as custom repositories.
|
121
|
-
|
121
|
+
# Return latest version available for current package
|
122
122
|
def latest
|
123
123
|
command = resource_or_provider_command
|
124
124
|
self.class.validate_command(command)
|
125
125
|
|
126
126
|
command_version = self.class.pip_version(command)
|
127
|
-
if
|
128
|
-
|
127
|
+
if self.class.compare_pip_versions(command_version, '1.5.4') == -1
|
128
|
+
available_versions_with_old_pip.last
|
129
129
|
else
|
130
|
-
|
130
|
+
available_versions_with_new_pip.last
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
def self.compare_pip_versions(x, y)
|
135
|
+
begin
|
136
|
+
Puppet::Util::Package::Version::Pip.compare(x, y)
|
137
|
+
rescue PIP_VERSION::ValidationFailure => ex
|
138
|
+
Puppet.debug("Cannot compare #{x} and #{y}. #{ex.message} Falling through default comparison mechanism.")
|
139
|
+
Puppet::Util::Package.versioncmp(x, y)
|
131
140
|
end
|
132
141
|
end
|
133
142
|
|
134
|
-
#
|
143
|
+
# Use pip CLI to look up versions from PyPI repositories,
|
144
|
+
# honoring local pip config such as custom repositories.
|
145
|
+
def available_versions
|
146
|
+
command = resource_or_provider_command
|
147
|
+
self.class.validate_command(command)
|
148
|
+
|
149
|
+
command_version = self.class.pip_version(command)
|
150
|
+
if self.class.compare_pip_versions(command_version, '1.5.4') == -1
|
151
|
+
available_versions_with_old_pip
|
152
|
+
else
|
153
|
+
available_versions_with_new_pip
|
154
|
+
end
|
155
|
+
end
|
135
156
|
|
136
|
-
def
|
157
|
+
def available_versions_with_new_pip
|
137
158
|
command = resource_or_provider_command
|
138
159
|
self.class.validate_command(command)
|
139
160
|
|
@@ -142,21 +163,18 @@ Puppet::Type.type(:package).provide :pip, :parent => ::Puppet::Provider::Package
|
|
142
163
|
execpipe command_and_options do |process|
|
143
164
|
process.collect do |line|
|
144
165
|
# PIP OUTPUT: Could not find a version that satisfies the requirement example==versionplease (from versions: 1.2.3, 4.5.6)
|
145
|
-
if line =~ /from versions: /
|
146
|
-
|
147
|
-
|
148
|
-
Puppet::Util::Package.versioncmp(x, y)
|
166
|
+
if line =~ /from versions: (.+)\)/
|
167
|
+
versionList = $1.split(', ').sort do |x,y|
|
168
|
+
self.class.compare_pip_versions(x, y)
|
149
169
|
end
|
150
|
-
return versionList
|
170
|
+
return versionList
|
151
171
|
end
|
152
172
|
end
|
153
|
-
return nil
|
154
173
|
end
|
174
|
+
[]
|
155
175
|
end
|
156
176
|
|
157
|
-
|
158
|
-
|
159
|
-
def latest_with_old_pip
|
177
|
+
def available_versions_with_old_pip
|
160
178
|
command = resource_or_provider_command
|
161
179
|
self.class.validate_command(command)
|
162
180
|
|
@@ -166,38 +184,73 @@ Puppet::Type.type(:package).provide :pip, :parent => ::Puppet::Provider::Package
|
|
166
184
|
execpipe command_and_options do |process|
|
167
185
|
process.collect do |line|
|
168
186
|
# PIP OUTPUT: Using version 0.10.1 (newest of versions: 1.2.3, 4.5.6)
|
169
|
-
if line =~ /Using version
|
170
|
-
|
187
|
+
if line =~ /Using version .+? \(newest of versions: (.+?)\)/
|
188
|
+
versionList = $1.split(', ').sort do |x,y|
|
189
|
+
self.class.compare_pip_versions(x, y)
|
190
|
+
end
|
191
|
+
return versionList
|
171
192
|
end
|
172
193
|
end
|
173
|
-
return nil
|
174
194
|
end
|
195
|
+
return []
|
175
196
|
end
|
176
197
|
end
|
177
198
|
|
199
|
+
# Finds the most suitable version available in a given range
|
200
|
+
def best_version(should_range)
|
201
|
+
included_available_versions = []
|
202
|
+
available_versions.each do |version|
|
203
|
+
version = PIP_VERSION.parse(version)
|
204
|
+
included_available_versions.push(version) if should_range.include?(version)
|
205
|
+
end
|
206
|
+
|
207
|
+
included_available_versions.sort!
|
208
|
+
return included_available_versions.last unless included_available_versions.empty?
|
209
|
+
|
210
|
+
Puppet.debug("No available version for package #{@resource[:name]} is included in range #{should_range}")
|
211
|
+
should_range
|
212
|
+
end
|
213
|
+
|
178
214
|
# Install a package. The ensure parameter may specify installed,
|
179
215
|
# latest, a version number, or, in conjunction with the source
|
180
216
|
# parameter, an SCM revision. In that case, the source parameter
|
181
217
|
# gives the fully-qualified URL to the repository.
|
182
|
-
|
183
218
|
def install
|
184
219
|
command = resource_or_provider_command
|
185
220
|
self.class.validate_command(command)
|
186
221
|
|
222
|
+
should = @resource[:ensure]
|
187
223
|
command_options = %w{install -q}
|
188
224
|
command_options += install_options if @resource[:install_options]
|
189
225
|
if @resource[:source]
|
190
|
-
if String ===
|
191
|
-
command_options << "#{@resource[:source]}@#{
|
226
|
+
if String === should
|
227
|
+
command_options << "#{@resource[:source]}@#{should}#egg=#{@resource[:name]}"
|
192
228
|
else
|
193
229
|
command_options << "#{@resource[:source]}#egg=#{@resource[:name]}"
|
194
230
|
end
|
195
231
|
else
|
196
|
-
case
|
197
|
-
when String
|
198
|
-
command_options << "#{@resource[:name]}==#{@resource[:ensure]}"
|
232
|
+
case should
|
199
233
|
when :latest
|
200
234
|
command_options << "--upgrade" << @resource[:name]
|
235
|
+
when String
|
236
|
+
begin
|
237
|
+
should_range = PIP_VERSION_RANGE.parse(should, PIP_VERSION)
|
238
|
+
should = best_version(should_range)
|
239
|
+
|
240
|
+
unless should == should_range
|
241
|
+
command_options << "#{@resource[:name]}==#{should}"
|
242
|
+
else
|
243
|
+
# when no suitable version for the given range was found, let pip handle
|
244
|
+
if should.is_a?(PIP_VERSION_RANGE::MinMax)
|
245
|
+
command_options << "#{@resource[:name]} #{should.split.join(',')}"
|
246
|
+
else
|
247
|
+
command_options << "#{@resource[:name]} #{should}"
|
248
|
+
end
|
249
|
+
end
|
250
|
+
rescue PIP_VERSION_RANGE::ValidationFailure, PIP_VERSION::ValidationFailure
|
251
|
+
Puppet.debug("Cannot parse #{should} as a pip version range, falling through.")
|
252
|
+
command_options << "#{@resource[:name]}==#{should}"
|
253
|
+
end
|
201
254
|
else
|
202
255
|
command_options << @resource[:name]
|
203
256
|
end
|
@@ -208,7 +261,6 @@ Puppet::Type.type(:package).provide :pip, :parent => ::Puppet::Provider::Package
|
|
208
261
|
|
209
262
|
# Uninstall a package. Uninstall won't work reliably on Debian/Ubuntu unless this issue gets fixed.
|
210
263
|
# http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=562544
|
211
|
-
|
212
264
|
def uninstall
|
213
265
|
command = resource_or_provider_command
|
214
266
|
self.class.validate_command(command)
|
@@ -226,6 +278,26 @@ Puppet::Type.type(:package).provide :pip, :parent => ::Puppet::Provider::Package
|
|
226
278
|
join_options(@resource[:install_options])
|
227
279
|
end
|
228
280
|
|
281
|
+
def insync?(is)
|
282
|
+
return false unless is && is != :absent
|
283
|
+
begin
|
284
|
+
should = @resource[:ensure]
|
285
|
+
should_range = PIP_VERSION_RANGE.parse(should, PIP_VERSION)
|
286
|
+
rescue PIP_VERSION_RANGE::ValidationFailure, PIP_VERSION::ValidationFailure
|
287
|
+
Puppet.debug("Cannot parse #{should} as a pip version range")
|
288
|
+
return false
|
289
|
+
end
|
290
|
+
|
291
|
+
begin
|
292
|
+
is_version = PIP_VERSION.parse(is)
|
293
|
+
rescue PIP_VERSION::ValidationFailure
|
294
|
+
Puppet.debug("Cannot parse #{is} as a pip version")
|
295
|
+
return false
|
296
|
+
end
|
297
|
+
|
298
|
+
should_range.include?(is_version)
|
299
|
+
end
|
300
|
+
|
229
301
|
def self.quote(path)
|
230
302
|
if path.include?(" ")
|
231
303
|
"\"#{path}\""
|