How do I install a yum package group with puppet?

13,522

Solution 1

I've came across similar request today, but I'm not a fan of a exec if things can be solved by any other means. So I've chosen a different path and written a simple custom type for 'yumgroup'. Just put these files in any module in your modulepath and that's it:

"modulename/lib/puppet/provider/yumgroup/default.rb"

Puppet::Type.type(:yumgroup).provide(:default) do
  desc 'Support for managing the yum groups'

  commands :yum => '/usr/bin/yum'

  # TODO
  # find out how yum parses groups and reimplement that in ruby

  def self.instances
    groups = []

    # get list of all groups
    yum_content = yum('grouplist').split("\n")

    # turn of collecting to avoid lines like 'Loaded plugins'
    collect_groups = false

    # loop through lines of yum output
    yum_content.each do |line|
      # if we get to 'Available Groups:' string, break the loop
      break if line.chomp =~ /Available Groups:/

      # collect groups
      if collect_groups and line.chomp !~ /(Installed|Available)/
        current_name = line.chomp.sub(/^\s+/,'\1').sub(/ \[.*\]/,'')
        groups << new(
          :name   => current_name,
          :ensure => :present
        )
      end

      # turn on collecting when the 'Installed Groups:' is reached
      collect_groups = true if line.chomp =~ /Installed Groups:/
    end
    groups
  end

  def self.prefetch(resources)
    instances.each do |prov|
      if resource = resources[prov.name]
        resource.provider = prov
      end
    end
  end

  def create
    yum('-y', 'groupinstall', @resource[:name])
    @property_hash[:ensure] == :present
  end

  def destroy
    yum('-y', 'groupremove', @resource[:name])
    @property_hash[:ensure] == :absent
  end

  def exists?
    @property_hash[:ensure] == :absent
  end

end

"modulename/lib/puppet/type/yumgroup.rb"

Puppet::Type.newtype(:yumgroup) do
@doc = "Manage Yum groups

A typical rule will look like this:

yumgroup { 'Development tools':
  ensure => present,
}
"
    ensurable

    newparam(:name) do
       isnamevar
       desc 'The name of the group'
    end

end

And after that, run puppet agent with pluginsync enabled, and you can use custom type like this:

yumgroup {'Base': ensure => present, }

or:

yumgroup {'Development tools': ensure => absent, }

And you can see what groups are installed by running:

puppet resource yumgroup

enjoy!

Solution 2

Here's a definition of a 'yumgroup' puppet resource type. It installs default and mandatory packages by default, and can install optional packages.

This definition can't remove yum groups yet though it though it would be easy to make it happen. I didn't bother for myself because it can cause loops in puppet under certain circumstances.

This type requires the yum-downloadonly rpm to be installed and I think it only works on RHEL/CentOS/SL 6. At the time I wrote this, yum's exit statuses on previous versions were wrong so the 'unless' parameter wouldn't work without being extended to grep for output.

define yumgroup($ensure = "present", $optional = false) {
   case $ensure {
      present,installed: {
         $pkg_types_arg = $optional ? {
            true => "--setopt=group_package_types=optional,default,mandatory",
            default => ""
         }
         exec { "Installing $name yum group":
            command => "yum -y groupinstall $pkg_types_arg $name",
            unless => "yum -y groupinstall $pkg_types_arg $name --downloadonly",
            timeout => 600,
         }
      }
   }
}

I've deliberately omitted making yum-downloadonly a dependency as it might conflict with others' manifests. If you want to do this, declare the yum-downloadonly package in a separate manifest and include that within this define. Don't declare directly in this define otherwise puppet will give an error if you use this resource type more than once. The exec resource should then require Package['yum-downloadonly'].

Solution 3

You could handle this through an Puppet Exec Type to execute the necessary group install. I would be sure to include a good onlyif or unless option so that it only executes it when needed or set to refreshonly and trigger it via a Notify so that it is not run every time though. The Exec type will execute the command locally on the puppet client for you provided it is triggered.

Solution 4

I like the solution with a custom resource however it's not idempotent. My take on the exists? function:

Puppet::Type.type(:yumgroup).provide(:default) do
  desc 'Support for managing the yum groups'

  commands :yum => '/usr/bin/yum'

  # TODO
  # find out how yum parses groups and reimplement that in ruby

  def self.instances
    groups = []

    # get list of all groups
    yum_content = yum('grouplist')

    # turn of collecting to avoid lines like 'Loaded plugins'
    collect_groups = false

    # loop through lines of yum output
    yum_content.each do |line|
      # if we get to 'Available Groups:' string, break the loop
      break if line.chomp =~ /Available Groups:/

      # collect groups
      if collect_groups and line.chomp !~ /(Installed|Available)/
        current_name = line.chomp.sub(/^\s+/,'\1').sub(/ \[.*\]/,'')
        groups << new(
          :name   => current_name,
          :ensure => :present
        )
      end

      # turn on collecting when the 'Installed Groups:' is reached
      collect_groups = true if line.chomp =~ /Installed Groups:/
    end
    groups
  end

  def self.prefetch(resources)
    instances.each do |prov|
      if resource = resources[prov.name]
        resource.provider = prov
      end
    end
  end

  def create
    yum('-y', 'groupinstall', @resource[:name])
    @property_hash[:ensure] == :present
  end

  def destroy
    yum('-y', 'groupremove', @resource[:name])
    @property_hash[:ensure] == :absent
  end


  def exists?
    cmd = "/usr/bin/yum grouplist hidden \"" + @resource[:name] + "\" | /bin/grep \"^Installed\" > /dev/null"
    system(cmd)
    $?.success?
  end

end
Share:
13,522

Related videos on Youtube

joeforker
Author by

joeforker

How much rep do I need to get an epic mount?

Updated on September 17, 2022

Comments

  • joeforker
    joeforker over 1 year

    Does puppet have a way to install a yum package group (e.g. 'Development Tools'), besides exec?

  • Banjer
    Banjer almost 12 years
    Thanks for this! I created a module called yum_groupinstalls and created an init.pp manifest with your definition and a class to install the Development tools group. Note that I had to quote the group name: class yum_groupinstalls { yumgroup { '"Development tools"': } } In the definition I had to specify the full path to yum which was /usr/bin/yum for me on CentOS 6.2.
  • alex.pilon
    alex.pilon about 9 years
    I think that yum_content = yum('grouplist') needs a .split("\n") so that the .each doesn't cause errors.
  • Clément Perroud
    Clément Perroud almost 7 years
    @alex.pilon thanks for the tip. It was working like this in v3 though.