Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Puppet, how to use the exec return value as a trigger?

Tags:

exit

puppet

I have a bash script that perform a check and return a boolean 0|1. Example of such script below :

# less /path/to/script/check_kernel.sh
#! /bin/bash
# Check if running kernel match default=0 kernel in grub.conf
KERNEL_RUNN=`/bin/uname -r | /bin/sed -e 's/^//' -e 's/[[:space:]]*$//'`
KERNEL_GRUB=`/bin/grep kernel /boot/grub/menu.lst | /bin/grep -v '#' \
| /bin/awk '{print $2}' | /bin/sed -e 's/\/vmlinuz-//g' | /usr/bin/head -1 \
| /bin/sed -e 's/^//' -e 's/[[:space:]]*$//'`

if [ "$KERNEL_RUNN" == "$KERNEL_GRUB" ]; then
  exit 0
else
  exit 1
fi

To run the above shell script in Puppet I would use the following code :

$check_kernel_cmd="/path/to/script/check_kernel.sh"
exec {'check_kernel':
  provider => shell,
  returns => [ "0", "1", ],
  command => "$check_kernel_cmd",
}

So now I need to use the returned exit status of above exec resource Exec['check_kernel'] as a trigger to another exec resource Exec['reboot_node'], something like :

if $check_kernel == '1' {
  $reboot = "/sbin/runuser - root -s /bin/bash -c '/sbin/shutdown -r'"
  exec {'reboot_node':
    provider => shell,
    command => "$reboot",
  }
}

or maybe another style approach would be to use unless as follows :

$reboot = "/sbin/runuser - root -s /bin/bash -c '/sbin/shutdown -r'"
exec {'reboot_node':
  provider => shell,
  command => "$reboot",
  unless => "/bin/echo $check_kernel",
  require => Exec['check_kernel'],
}

What would the recommended approach/code be to use the exit status of an exec resource as a trigger to another exec resource in the same manifest ?

like image 468
fmaree Avatar asked Feb 12 '23 06:02

fmaree


1 Answers

TL;DR this cannot work. Make your first script an external fact so that you can query its result from a variable in your manifests. Alternatively, if that is valid, call the prior script through the latter's onlyif or unless parameter, instead of as its own exec resource.


Long answer

The scheme you have in mind is not compatible with Puppet's master/agent paradigm. The complete manifest is compiled in one go, leading to an abstract representation, the catalog. This whole catalog is sent to the agent for evaluation. Only then will the agent start and sync resources, including both exec resources. The information about the return value of any of them cannot be used in the manifest, because the manifest is no longer available at that point.

The canonical way for the master to use information from the agent machine are Custom Facts. You place code on the master which the agent consumes and runs prior to compilation. All fact values can be used in the manifest as variables.

In a simple case such as your's, using an exec for the check script is likely unnecessary. I believe the following would work.

exec {
    '/sbin/shutdown -r':
        unless => '/path/to/script/check_kernel.sh';
}

Final note: Programming your Puppet agent to reboot your nodes by some homegrown logic could be rather dangerous - the agent runs at startup by default, so it may end up in a vicious cycle if that logic breaks (you can likely fix that on the master, but it's still not a cheerful perspective).

like image 186
Felix Frank Avatar answered Mar 03 '23 00:03

Felix Frank