Akom's Tech Ruminations

Various tech outbursts - code and solutions to practical problems
Linux

Simple puppet update-alternatives

Posted by Admin • Thursday, June 11. 2015 • Category: DevOps, Linux

This is a quick and dirty interface to update-alternatives on Centos/Redhat/Ubuntu for puppet. Seems to work well and doesn't require any modules.
Usage example: alternatives_update { 'java': versiongrep => '1.8' }

class my_alternatives {


  # Manipulates alternatives using update-alternatives.
  # Supports RHEL, Centos and Suse.
  # Ubuntu not tested (yet).
  #
  # If multiple matches are available, picks the first one.
  #
  # There is rudimentary alternatives support in the java class,
  # but it's rather limited and doesn't support most platforms and java versions.
  define update (
    $item = $title,   # the item to manage, ie "java"
    $versiongrep,     # string to pass to grep to select an alternative, ie '1.8' (1.8.*openjdk would also work)
    $optional = true,  # if false, execution will fail if the version is not found
    $altcmd   = 'update-alternatives' # command to use
  ) {

    case $::osfamily {
      'RedHat','SuSE': {


        if ! $optional {
          # verify that we have exactly 1 matching alternatives, unless it's optional
          exec { "check alternatives for ${item}":
            path    => ['/sbin','/bin','/usr/bin','/usr/sbin'],
            command => "echo Alternative for ${item} version containing ${versiongrep} was not found, or multiple found ; false",
            unless  => "test $(${altcmd} --display ${item} | grep '^/' | grep -- '$versiongrep' | wc -l) -eq 1",
            before  => Exec["update alternatives for ${item} to ${versiongrep}"],
          }
        }

        # Runs the update alternatives command
        #  - unless it reports that it's already set to that version
        #  - unless that version is not found via grep
        exec { "update alternatives for ${item} to ${versiongrep}":
          path    => ['/sbin','/bin','/usr/bin','/usr/sbin'],
          command => "${altcmd} --set ${item} $( ${altcmd} --display ${item} | grep '^/' | grep -- '$versiongrep' | head -n 1 | sed 's/ .*$//' ) ",
          unless  => "test -x \"$(${altcmd} --display ${item} | grep 'currently points' | grep -- '$versiongrep' | awk '{print \$NF}')\"",
          onlyif  => "${altcmd} --display ${item} | grep '^/' | grep -- '$versiongrep' ", # check that there is one (if optional and not found, this won't run)
        }

      }

      # Leave Ubuntu alone, this probably won't work there anyway


    }
  }

}
 

0 Trackbacks

  1. No Trackbacks

2 Comments

Display comments as (Linear | Threaded)
  1. Hi,

    thanks for the very nice snippet. However, there are certain circumstances where this will not work, e.g. if your regexp matches the priority level... Consider this example:

    myhost ~ $ update-alternatives --display java | grep '^/' | grep -- 1.6 /usr/lib/jvm/jre-1.6.0-openjdk.x86_64/bin/java - priority 16000 /usr/lib/jvm/jre-1.8.0-openjdk.x86_64/bin/java - priority 1865

    In this case the "grep -- 1.6" will find both alternatives, 1.6 and 1.8, b/c the "1865" priority reading also matches the "1.6" regexp. So your code will fail b/c it does not know what version to create the link for.

    I found two solutions to this problem (only relevant code):

    • replace the "--" with "-w" to have grep look for the word-regexp "1.6":

      myhost ~ $ update-alternatives --display java | grep '^/' | grep -w 1.6 /usr/lib/jvm/jre-1.6.0-openjdk.x86_64/bin/java - priority 16000

    • remove everything but the package name prior to grep:

      myhost ~ $ update-alternatives --display java | grep '^/' | awk -F "priority" '{print $1}' | grep -- 1.6 /usr/lib/jvm/jre-1.6.0-openjdk.x86_64/bin/java -

    This needs to be corrected in BOTH exec commands for this Puppet "module" to work under any circumstances.

    Cheers!

  2. Thanks!

    I updated the commands with "-w". I checked it on Redhat/Centos 6 and 7 and on Suse 11/12, looks good.

    On Ubuntu, openjdk paths don't even have a dot (java-7-openjdk-amd64) so that's not an issue.

Add Comment


You can use [geshi lang=lang_name [,ln={y|n}]][/geshi] tags to embed source code snippets.
Enclosing asterisks marks text as bold (*word*), underscore are made via _word_.
Standard emoticons like :-) and ;-) are converted to images.
Markdown format allowed


Submitted comments will be subject to moderation before being displayed.