THX
THX

Reputation: 573

Puppet: "iterate" over all rpms in a dir and install

I am not a real puppet expert and am now looking for a 'propper puppet' way to install a set of local RPMs?

So, I have a local directory where I put a number RPMs, which I would like to get installed - thus I defined a resource to copy a rpm file and install it

define package_local(
$source = $name,
$rpmdirpuppet = "puppet:///modules/my_lib/rpmdir",
$rpmdirlocal = "/var/package/"
)
{
file{"${rpmdirlocal}":
  path => $rpmdirlocal,
  ensure => "directory",
}->
  file {"${rpmdirlocal}/${source}":
    source => "${rpmdirpuppet}/${source}",
path => "${rpmdirlocal}/${source}",
  }->
  package {"${rpmdirlocal}/${source}":
    provider => "rpm",
    source => "${rpmdirlocal}/${source}",
    require => File["${rpmdirlocal}/${source}"],
    }
}

Now I would like to 'iterate' over all the RPMs in the dirextory and copy/install them in one go. I could defined the files all in hiera and 'walk' with create_resources through them. But since I have anyway only the rpms in my rpm-dir, I guess I do not really need to name all files on their own. So, I wonder what would be the best way to get all rpms in my_lib/{files}/rpmdir copied and installed?

Cheers and thanks for ideas, Thomas

Upvotes: 0

Views: 963

Answers (1)

John
John

Reputation: 573

I've done something similar to this in the past.

You need to write a parser on the server to define a new function. Something like this in modules/extras/lib/puppet/parser/functions/get_files.rb

module Puppet::Parser::Functions
  newfunction(:get_files, :type => :rvalue) do |args|
    raise ArgumentError, ("get_files(): wrong number of arguments (#{args.length}; must be path on master)") if args.length != 1
    dir = args[0]
    files = Dir.glob("#{dir}/**/*").select {|f| File.file? f}.map!{|f| f.sub!("#{dir}/","")}
    p files
    files
  end
end

Then in your manifest you can get an array of files on the puppet servers directory with :

$module_path=get_module_path(${caller_module_name})
$rpms=get_files("${module_path}/files")

next you need a defined type or to iterate. (the following is freehand, may or may not compile)

define localrpm (
  $rpm,
  $localdir = '/tmp'
) {
  $package_name = regsubst($rpm,'.rpm$','')
  file {"$localdir/$rpm":
    ensure => file,
    source => "puppet:///modules/${caller_module_name}/$rpm"
  } ->
  package {"$package_name":
    ensure   => installed,
    provider => rpm,
    source   => "$localdir/$rpm"
  }

}

Then you do the installs :

localrpm{$rpms: }

The reality however, is that this sucks as a solution. The rpms could be named anything. So you'd have to make sure that the file name on the puppetserver EXACTLY matches the package name (no versions or anything in the filename).

Its also not going to resolve any dependencies.

A more robust solution would be to recursively copy the directory to the agents (as you imply), and have an exec with refreshonly that runs 'createrepo' and add a new repository with a url of 'dir:///path/to/local/rpms'

Then you can install packages as normal.

Of course, the best solution would be to just add the rpms to a proper repository.

There's nothing stopping you hosting the files on your puppetserver and adding a vhost to apache on port 80.

Upvotes: 2

Related Questions