diff options
author | Ismaël Bouya <ismael.bouya@normalesup.org> | 2018-07-01 15:35:43 +0200 |
---|---|---|
committer | Ismaël Bouya <ismael.bouya@normalesup.org> | 2018-07-08 13:29:25 +0200 |
commit | d8f933bd00a5cc416da00cd26c9d13f7a1c02486 (patch) | |
tree | 6f8773b69418463485d1196389a6c264f3cf3a6e /modules/base_installation | |
parent | 25c99a635507abfe6af4a1f0a9fc5a103d1880c0 (diff) | |
download | Puppet-d8f933bd00a5cc416da00cd26c9d13f7a1c02486.tar.gz Puppet-d8f933bd00a5cc416da00cd26c9d13f7a1c02486.tar.zst Puppet-d8f933bd00a5cc416da00cd26c9d13f7a1c02486.zip |
Add monitoring
Diffstat (limited to 'modules/base_installation')
3 files changed, 306 insertions, 0 deletions
diff --git a/modules/base_installation/lib/puppet/provider/package/pacman.rb b/modules/base_installation/lib/puppet/provider/package/pacman.rb new file mode 100644 index 0000000..0a5e5d0 --- /dev/null +++ b/modules/base_installation/lib/puppet/provider/package/pacman.rb | |||
@@ -0,0 +1,283 @@ | |||
1 | require 'puppet/provider/package' | ||
2 | require 'set' | ||
3 | require 'uri' | ||
4 | |||
5 | Puppet::Type.type(:package).provide :pacman, :parent => Puppet::Provider::Package do | ||
6 | desc "Support for the Package Manager Utility (pacman) used in Archlinux. | ||
7 | |||
8 | This provider supports the `install_options` attribute, which allows command-line flags to be passed to pacman. | ||
9 | These options should be specified as a string (e.g. '--flag'), a hash (e.g. {'--flag' => 'value'}), | ||
10 | or an array where each element is either a string or a hash." | ||
11 | |||
12 | # If aura is installed, we can make use of it | ||
13 | def self.aura? | ||
14 | @aura ||= Puppet::FileSystem.exist?('/usr/bin/aura') | ||
15 | end | ||
16 | |||
17 | commands :pacman => "/usr/bin/pacman" | ||
18 | # Aura is a common AUR helper which, if installed, we can use to query the AUR | ||
19 | commands :aura => "/usr/bin/aura" if aura? | ||
20 | |||
21 | confine :operatingsystem => [:archlinux, :manjarolinux] | ||
22 | defaultfor :operatingsystem => [:archlinux, :manjarolinux] | ||
23 | has_feature :install_options | ||
24 | has_feature :uninstall_options | ||
25 | has_feature :upgradeable | ||
26 | has_feature :virtual_packages | ||
27 | |||
28 | # Checks if a given name is a group | ||
29 | def self.group?(name) | ||
30 | begin | ||
31 | !pacman("-Sg", name).empty? | ||
32 | rescue Puppet::ExecutionFailure | ||
33 | # pacman returns an expected non-zero exit code when the name is not a group | ||
34 | false | ||
35 | end | ||
36 | end | ||
37 | |||
38 | # Install a package using 'pacman', or 'aura' if available. | ||
39 | # Installs quietly, without confirmation or progress bar, updates package | ||
40 | # list from servers defined in pacman.conf. | ||
41 | def install | ||
42 | if @resource[:source] | ||
43 | install_from_file | ||
44 | else | ||
45 | install_from_repo | ||
46 | end | ||
47 | |||
48 | unless self.query | ||
49 | fail(_("Could not find package '%{name}'") % { name: @resource[:name] }) | ||
50 | end | ||
51 | end | ||
52 | |||
53 | # Fetch the list of packages and package groups that are currently installed on the system. | ||
54 | # Only package groups that are fully installed are included. If a group adds packages over time, it will not | ||
55 | # be considered as fully installed any more, and we would install the new packages on the next run. | ||
56 | # If a group removes packages over time, nothing will happen. This is intended. | ||
57 | def self.instances | ||
58 | instances = [] | ||
59 | |||
60 | # Get the installed packages | ||
61 | installed_packages = get_installed_packages | ||
62 | installed_packages.sort_by { |k, _| k }.each do |package, version| | ||
63 | instances << new(to_resource_hash(package, version)) | ||
64 | end | ||
65 | |||
66 | # Get the installed groups | ||
67 | get_installed_groups(installed_packages).each do |group, version| | ||
68 | instances << new(to_resource_hash(group, version)) | ||
69 | end | ||
70 | |||
71 | instances | ||
72 | end | ||
73 | |||
74 | # returns a hash package => version of installed packages | ||
75 | def self.get_installed_packages | ||
76 | begin | ||
77 | packages = {} | ||
78 | execpipe([command(:pacman), "-Q"]) do |pipe| | ||
79 | # pacman -Q output is 'packagename version-rel' | ||
80 | regex = %r{^(\S+)\s(\S+)} | ||
81 | pipe.each_line do |line| | ||
82 | if match = regex.match(line) | ||
83 | packages[match.captures[0]] = match.captures[1] | ||
84 | else | ||
85 | warning(_("Failed to match line '%{line}'") % { line: line }) | ||
86 | end | ||
87 | end | ||
88 | end | ||
89 | packages | ||
90 | rescue Puppet::ExecutionFailure | ||
91 | fail(_("Error getting installed packages")) | ||
92 | end | ||
93 | end | ||
94 | |||
95 | # returns a hash of group => version of installed groups | ||
96 | def self.get_installed_groups(installed_packages, filter = nil) | ||
97 | groups = {} | ||
98 | begin | ||
99 | # Build a hash of group name => list of packages | ||
100 | command = [command(:pacman), "-Sgg"] | ||
101 | command << filter if filter | ||
102 | execpipe(command) do |pipe| | ||
103 | pipe.each_line do |line| | ||
104 | name, package = line.split | ||
105 | packages = (groups[name] ||= []) | ||
106 | packages << package | ||
107 | end | ||
108 | end | ||
109 | |||
110 | # Remove any group that doesn't have all its packages installed | ||
111 | groups.delete_if do |_, packages| | ||
112 | !packages.all? { |package| installed_packages[package] } | ||
113 | end | ||
114 | |||
115 | # Replace the list of packages with a version string consisting of packages that make up the group | ||
116 | groups.each do |name, packages| | ||
117 | groups[name] = packages.sort.map {|package| "#{package} #{installed_packages[package]}"}.join ', ' | ||
118 | end | ||
119 | rescue Puppet::ExecutionFailure | ||
120 | # pacman returns an expected non-zero exit code when the filter name is not a group | ||
121 | raise unless filter | ||
122 | end | ||
123 | groups | ||
124 | end | ||
125 | |||
126 | # Because Archlinux is a rolling release based distro, installing a package | ||
127 | # should always result in the newest release. | ||
128 | def update | ||
129 | # Install in pacman can be used for update, too | ||
130 | self.install | ||
131 | end | ||
132 | |||
133 | # We rescue the main check from Pacman with a check on the AUR using aura, if installed | ||
134 | def latest | ||
135 | # Synchronize the database | ||
136 | pacman "-Sy" | ||
137 | |||
138 | resource_name = @resource[:name] | ||
139 | |||
140 | # If target is a group, construct the group version | ||
141 | return pacman("-Sp", "--print-format", "%n %v", resource_name).lines.map{ |line| line.chomp }.sort.join(', ') if self.class.group?(resource_name) | ||
142 | |||
143 | # Start by querying with pacman first | ||
144 | # If that fails, retry using aura against the AUR | ||
145 | pacman_check = true | ||
146 | begin | ||
147 | if pacman_check | ||
148 | output = pacman "-Sp", "--print-format", "%v", resource_name | ||
149 | return output.chomp | ||
150 | else | ||
151 | output = aura "-Ai", resource_name | ||
152 | output.split("\n").each do |line| | ||
153 | return line.split[2].chomp if line.split[0] =~ /Version/ | ||
154 | end | ||
155 | end | ||
156 | rescue Puppet::ExecutionFailure | ||
157 | if pacman_check and self.class.aura? | ||
158 | pacman_check = false # now try the AUR | ||
159 | retry | ||
160 | else | ||
161 | raise | ||
162 | end | ||
163 | end | ||
164 | end | ||
165 | |||
166 | # Queries information for a package or package group | ||
167 | def query | ||
168 | installed_packages = self.class.get_installed_packages | ||
169 | resource_name = @resource[:name] | ||
170 | |||
171 | # Check for the resource being a group | ||
172 | version = self.class.get_installed_groups(installed_packages, resource_name)[resource_name] | ||
173 | |||
174 | if version | ||
175 | unless @resource.allow_virtual? | ||
176 | warning(_("%{resource_name} is a group, but allow_virtual is false.") % { resource_name: resource_name }) | ||
177 | return nil | ||
178 | end | ||
179 | else | ||
180 | version = installed_packages[resource_name] | ||
181 | end | ||
182 | |||
183 | # Return nil if no package or group found | ||
184 | return nil unless version | ||
185 | |||
186 | self.class.to_resource_hash(resource_name, version) | ||
187 | end | ||
188 | |||
189 | def self.to_resource_hash(name, version) | ||
190 | { | ||
191 | :name => name, | ||
192 | :ensure => version, | ||
193 | :provider => self.name | ||
194 | } | ||
195 | end | ||
196 | |||
197 | # Removes a package from the system. | ||
198 | def uninstall | ||
199 | resource_name = @resource[:name] | ||
200 | |||
201 | is_group = self.class.group?(resource_name) | ||
202 | |||
203 | fail(_("Refusing to uninstall package group %{resource_name}, because allow_virtual is false.") % { resource_name: resource_name }) if is_group && !@resource.allow_virtual? | ||
204 | |||
205 | cmd = %w{--noconfirm --noprogressbar} | ||
206 | cmd += uninstall_options if @resource[:uninstall_options] | ||
207 | cmd << "-R" | ||
208 | cmd << '-s' if is_group | ||
209 | cmd << resource_name | ||
210 | |||
211 | if self.class.aura? | ||
212 | aura(*cmd) | ||
213 | else | ||
214 | pacman(*cmd) | ||
215 | end | ||
216 | end | ||
217 | |||
218 | private | ||
219 | |||
220 | def install_with_aura? | ||
221 | resource_name = @resource[:name] | ||
222 | if !self.class.aura? | ||
223 | return false | ||
224 | end | ||
225 | |||
226 | begin | ||
227 | pacman "-Sp", resource_name | ||
228 | return false | ||
229 | rescue Puppet::ExecutionFailure | ||
230 | return true | ||
231 | end | ||
232 | end | ||
233 | |||
234 | def install_options | ||
235 | join_options(@resource[:install_options]) | ||
236 | end | ||
237 | |||
238 | def uninstall_options | ||
239 | join_options(@resource[:uninstall_options]) | ||
240 | end | ||
241 | |||
242 | def install_from_file | ||
243 | source = @resource[:source] | ||
244 | begin | ||
245 | source_uri = URI.parse source | ||
246 | rescue => detail | ||
247 | self.fail Puppet::Error, _("Invalid source '%{source}': %{detail}") % { source: source, detail: detail }, detail | ||
248 | end | ||
249 | |||
250 | source = case source_uri.scheme | ||
251 | when nil then source | ||
252 | when /https?/i then source | ||
253 | when /ftp/i then source | ||
254 | when /file/i then source_uri.path | ||
255 | when /puppet/i | ||
256 | fail _("puppet:// URL is not supported by pacman") | ||
257 | else | ||
258 | fail _("Source %{source} is not supported by pacman") % { source: source } | ||
259 | end | ||
260 | pacman "--noconfirm", "--noprogressbar", "-Sy" | ||
261 | pacman "--noconfirm", "--noprogressbar", "-U", source | ||
262 | end | ||
263 | |||
264 | def install_from_repo | ||
265 | resource_name = @resource[:name] | ||
266 | |||
267 | # Refuse to install if not allowing virtual packages and the resource is a group | ||
268 | fail(_("Refusing to install package group %{resource_name}, because allow_virtual is false.") % { resource_name: resource_name }) if self.class.group?(resource_name) && !@resource.allow_virtual? | ||
269 | |||
270 | cmd = %w{--noconfirm --needed} | ||
271 | cmd += install_options if @resource[:install_options] | ||
272 | |||
273 | if install_with_aura? | ||
274 | cmd << "-Aq" << resource_name | ||
275 | aura(*cmd) | ||
276 | else | ||
277 | cmd << "--noprogressbar" | ||
278 | cmd << "-Sy" << resource_name | ||
279 | pacman(*cmd) | ||
280 | end | ||
281 | end | ||
282 | |||
283 | end | ||
diff --git a/modules/base_installation/lib/puppet/provider/package/pip2.rb b/modules/base_installation/lib/puppet/provider/package/pip2.rb new file mode 100644 index 0000000..27cc0c4 --- /dev/null +++ b/modules/base_installation/lib/puppet/provider/package/pip2.rb | |||
@@ -0,0 +1,17 @@ | |||
1 | require 'puppet/provider/package/pip' | ||
2 | |||
3 | Puppet::Type.type(:package).provide :pip2, | ||
4 | :parent => :pip do | ||
5 | |||
6 | desc "Python packages via `pip2`. | ||
7 | |||
8 | This provider supports the `install_options` attribute, which allows command-line flags to be passed to pip2. | ||
9 | These options should be specified as a string (e.g. '--flag'), a hash (e.g. {'--flag' => 'value'}), | ||
10 | or an array where each element is either a string or a hash." | ||
11 | |||
12 | has_feature :installable, :uninstallable, :upgradeable, :versionable, :install_options | ||
13 | |||
14 | def self.cmd | ||
15 | ["pip2"] | ||
16 | end | ||
17 | end | ||
diff --git a/modules/base_installation/manifests/package_managers.pp b/modules/base_installation/manifests/package_managers.pp index c5c8485..a03085d 100644 --- a/modules/base_installation/manifests/package_managers.pp +++ b/modules/base_installation/manifests/package_managers.pp | |||
@@ -18,6 +18,12 @@ class base_installation::package_managers inherits base_installation { | |||
18 | include => '/etc/pacman.d/mirrorlist' | 18 | include => '/etc/pacman.d/mirrorlist' |
19 | } | 19 | } |
20 | 20 | ||
21 | pacman::repo { 'immae': | ||
22 | order => 0, | ||
23 | server => 'https://git.immae.eu/releases/packages/', | ||
24 | siglevel => 'Optional' | ||
25 | } | ||
26 | |||
21 | class { 'aur': } | 27 | class { 'aur': } |
22 | 28 | ||
23 | contain "pacman" | 29 | contain "pacman" |