Reputation: 2004
Is there any way to declare in Puppet's language that packages in an array should installed in the order they are given in the array?
I want to automate the installation of CUDA, which requires nvidia-driver-latest-dkms
, cuda
and cuda-drivers
(on RHEL7 as an example) to be installed in that order. I do not want to hard-code the array of packages, because I need to support different distributions, which require different packages. Therefore, an array holding the packages provided via Hiera seemed to be a good idea.
My first solution was ensure_packages($packages_parameter_filled_via_hiera)
, which stopped working recently (probably due to changes in NVIDIA's packages). The problem seems to be that this code installs the packages in a random order, and you cannot install nvidia-driver-latest-dkms
(any more) if any of the other packages is already installed.
My next approach,
$packages.each | $package | {
ensure_packages($package)
}
has the very same problem as does
$packages.each | $package | {
package { "cuda-${package}":
name => $package
}
}
What I am looking for is something that is equivalent to the ->
or ~>
operator between the loop instances, or alternatively, some "dangling-pointer" construct that would give me access to the previous $package
such that I can write require => Package[$magic_previous_instance]
in the package resource. That is, I want to create something equivalent to
package { 'cuda-epel-release':
name => 'epel-release'
}
-> package { 'cuda-nvidia-driver-latest-dkms':
name => 'nvidia-driver-latest-dkms'
}
-> package { 'cuda-cuda':
name => 'cuda'
}
-> package { 'cuda-cuda-drivers':
name => 'cuda-drivers'
}
(which actually works, but exactly for RHEL 7) dynamically from Hiera data.
Upvotes: 4
Views: 196
Reputation: 28739
Yes, this is actually possible with a "wrapper" defined resource type:
define custom::install(Hash $pkg_hash) {
# iterates through the packages in the hash using their keys, and creates a package default where each requires the previous package
# index > 0 ensures the first package does not attempt to require a nonexistent previous package
keys($pkg_hash).each |Integer $index, String $pkg| { if $index > 0 { Package[keys($pkg_hash)[$index - 1]] -> Package[$pkg] } }
create_resources(package, $pkg_hash)
}
To give credit where credit is due, I was originally pointed in this direction by Henrik Lindberg, so it is not entirely my creation. The input Hash $pkg_hash
for the defined resource type is a package hash
type analogous to the input argument structure for the create_resources
function second argument. For example:
$pkg_hash = {
'cuda-epel-release' => { ensure => installed },
'cuda-nvidia-driver-latest-dkms' => { ensure => installed }
}
or in Hiera data YAML format:
pkg_hash:
'cuda-epel-release':
ensure: installed
'cuda-nvidia-driver-latest-dkms':
ensure: installed
and then custom::install($pkg_hash)
as expected.
Note that create_resources
in the DRT can be replaced as per normal:
$pkg_hash.each |String $package, Hash $attributes| {
package { $package: *=> $attributes }
}
as described in the bottom of the documentation (Puppet doc quick link not working).
Upvotes: 2