You might want to write code that can tell how many iterations have passed since some action occurred. Alternatively, you might want to know if it’s the first time a machine has run Puppet. To do these types of things, you might wish to have a monotonically increasing counter in your Puppet manifest. Since one did not exist, I set out to build one!
The code:
If you just want to try the code, and skip the ramble, you can include common::counter into your manifest. The entire class is part of my puppet-common module:
git clone https://github.com/purpleidea/puppet-common
Usage:
Usage notes are hardly even necessary. Here is how the code is commonly used:
include ::common::counter # that's it!
# NOTE: we only see the notify message. no other exec/change is shown!
notify { 'counter':
message => "Value is: ${::common_counter_simple}",
}
Increasing a variable:
At the heart of any counter, you’ll need to have a value store, a way to read the value, and a way to increment the value. For simplicity, the value store we’ll use will be a file on disk. This file is located by default at ${vardir}/common/counter/simple
. To read the value, we use a puppet fact. The fact has a key name of $::common_counter_simple
. To increment the value, a simple python script is used.
Noise:
To cause an increment of the value on each puppet run, an exec would have to be used. The downside of this is that this causes noise in your puppet logs, even if nothing else is happening! This noise is unwanted, so we work around this with the following code:
exec { 'counter':
# echo an error message and be false, if the incrementing fails
command => '/bin/echo "common::counter failed" && /bin/false',
unless => "${vardir}/counter/increment.py '${vardir}/counter/simple'",
logoutput => on_failure,
}
Complex example:
If you want to do something more complicated using this technique, you might want to write something like this:
$max = 8
exec { "/bin/echo this is run #: ${::common_counter_simple}":
logoutput => on_failure,
onlyif => [
"/usr/bin/test ${::common_counter_simple} -lt ${max}",
"/usr/bin/test ${::common_counter_simple} -gt 0",
],
#notify => ..., # do some action
}
Make sure not to use the counter fact in a $name or somewhere that would cause frequent unwanted catalog changes, as it could cause a lot of changes each run.
Module pairings:
You might want to pair this module with my “Finite State Machine” concept, or my Exec[‘again’] module. If you come up with some cool use cases, please let me know!
Future work:
If you’d like to extend this work, two features come to mind:
Happy hacking!
James
You can follow James on Mastodon for more frequent updates and other random thoughts.
You can follow James on Twitter for more frequent updates and other random thoughts.
You can support James on GitHub if you'd like to help sustain this kind of content.
You can support James on Patreon if you'd like to help sustain this kind of content.
Your comment has been submitted and will be published if it gets approved.
Click here to see the patch you generated.
Comments
Nothing yet.
Post a comment