Akom's Tech Ruminations

Various tech outbursts - code and solutions to practical problems

Simple puppet update-alternatives Linux

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.

To prevent automated Bots from commentspamming, please enter the string you see in the image below in the appropriate input box. Your comment will only be submitted if the strings match. Please ensure that your browser supports and accepts cookies, or your comment cannot be verified correctly.
CAPTCHA

What is the primary language of this blog? (Anti-SPAM question)


Submitted comments will be subject to moderation before being displayed.