Puppet Tips&Tricks: Variable variables
Sometimes you want to use variable variables, for instance when you want to iterate over all the ipaddress_* facts that facter found. Using something like ${ipaddress_$if} doesn’t work, though. Inline_template to the rescue! Volcane on IRC suggested the following solution, which works great:
$ifs = split($interfaces,",")
define do_this {
$mule = "ipaddress_${name}"
$donkey = inline_template("<%= scope.lookupvar(mule) %>")
notify { "Found interface $donkey":; }
}
do_this { $ifs:; }
This will output:
$ sudo puppet net.pp notice: Found interface 172.29.121.22 notice: //Do_this[eth0]/Notify[Found interface 172.29.121.22]/message: defined 'message' as 'Found interface 172.29.121.22' notice: Found interface 213.207.83.56 notice: //Do_this[eth1]/Notify[Found interface 213.207.83.56]/message: defined 'message' as 'Found interface 213.207.83.56'
Hope this helps someone else! Leave a message if it does.
Twitter Weekly Updates for 2010-08-29
- Worked until 3am last night. Hope I don't need that much time today… #
- Got a postcard from Mongolia! How awesome is that?? #farfaraway #
- #Varnish is awesome. #
- @ariejan We use it to locally cache pictures stored on S3 for http://www.nationalebeeldbank.nl… works like a charm! in reply to ariejan #
- Moeite gedaan om op tijd op kantoor te zijn zodat collega niet alleen zit, mist hij zijn trein… *zucht* #
- I miss the sysadmins in here
http://i.imgur.com/G7WyP.gif # - @APechtold Bel ik liever @FemkeHalsema if you don't mind… #giro555 in reply to APechtold #
- Small little unix utils are awesome, but xmlstarlet should recognise for itself if a default namespace is set… Took me 45 minutes… #
Powered by Twitter Tools
GlassFish 3.0.1 on Debian Lenny, Puppet style
Recently, I found a way to make the GlassFish supplied pkg(5) tool run using Debian’s python interpreter and associated libs. I also spent a while trying to package it in a sane way, but I’m afraid I lack the knowledge of Java and Debian package internals to do this properly (I’ve requested the package, though). But in the meantime we still need a nice way to setup GlassFish on a Debian Lenny machine. So I’ve turned to puppet, as usual.
You can find the module here: glassfish.tar.bz2 (12.8kB)
It doesn’t contain everything, though. You still need to download the glassfish ZIP file from here and rename that file to glassfish.zip and add it in the files directory of the module. After that, you can just include glassfish and it gets set-up!
The module does several things, including installing a very small facter Fact. The fact just checks if several important files/directories exist and if so, it deems GlassFish ‘installed’. If not, the module includes the glassfish::initial_setup class, which does the initial setup of GlassFish. You don’t want to include this class on every run, because it adds some crud in your /tmp, including some touchstone files. The glassfish_installed was created for determining this (following an example given to me by Volcane on IRC, thanks man!). The check probably isn’t perfect, but it’s good enough for our purposes.
This module adds the Debian non-free repository to your APT’s sources.list and installs the sun-java6-jdk package. In the process it also agrees with the Sun DLJ License. If you prefer the openjdk package, those should work too. You’ll just have to remove the stuff needed for installing sun-java6-jdk from the module.
Because we’re not fond of the way the GlassFish developers packaged the pkg(5) tool in there, the installer applies the recipe described earlier on this blog. You can see these steps in the glassfish::initial_setup subclass. There are a lot of exec’s in there which do most of the important work.
Due to security concerns, the module creates a glassfish user and group and makes sure all the code is readable by that user and group. It also makes sure the code is writable by the group, so you can easily add the local accounts from developers to the group and give them access to the code. If you want to allow them to do administrative tasks on GlassFish, you can add these rules to your /etc/sudoers:
%glassfish ALL=(glassfish) NOPASSWD: /opt/glassfishv3/bin/asadmin %glassfish ALL=(glassfish) NOPASSWD: /opt/glassfishv3/bin/pkg %glassfish ALL=(glassfish) NOPASSWD: /opt/glassfishv3/glassfish/bin/appclient %glassfish ALL=(glassfish) NOPASSWD: /opt/glassfishv3/glassfish/bin/asadmin %glassfish ALL=(glassfish) NOPASSWD: /opt/glassfishv3/glassfish/bin/asupgrade %glassfish ALL=(glassfish) NOPASSWD: /opt/glassfishv3/glassfish/bin/capture-schema %glassfish ALL=(glassfish) NOPASSWD: /opt/glassfishv3/glassfish/bin/jspc %glassfish ALL=(glassfish) NOPASSWD: /opt/glassfishv3/glassfish/bin/package-appclient %glassfish ALL=(glassfish) NOPASSWD: /opt/glassfishv3/glassfish/bin/schemagen %glassfish ALL=(glassfish) NOPASSWD: /opt/glassfishv3/glassfish/bin/startserv %glassfish ALL=(glassfish) NOPASSWD: /opt/glassfishv3/glassfish/bin/stopserv %glassfish ALL=(glassfish) NOPASSWD: /opt/glassfishv3/glassfish/bin/wscompile %glassfish ALL=(glassfish) NOPASSWD: /opt/glassfishv3/glassfish/bin/wsdeploy %glassfish ALL=(glassfish) NOPASSWD: /opt/glassfishv3/glassfish/bin/wsgen %glassfish ALL=(glassfish) NOPASSWD: /opt/glassfishv3/glassfish/bin/wsimport %glassfish ALL=(glassfish) NOPASSWD: /opt/glassfishv3/glassfish/bin/xjc
For easy reinstall, we symlink the /opt/glassfishv3/glassfish/domains directory to /srv/glassfish/domains. This allows you to completely remove /opt/glassfishv3 to perform a reinstall with the puppet module (because the removal of that directory triggers the inclusion of glassfish::initial_setup without breaking developer code.
The second time you run the script, all the crud is removed, including some .bat files that are part of the distribution of GlassFish. We leave JavaDB and mq in place, even though we don’t use them at all. So you might want to create some customization for those yourself.
Because we prefer to compile a small .so file from source instead of installing the ia32 libs, several developer packages are installed. These are not automatically removed in glassfish::cleanup, because the module cannot know if these packages are needed by another module too. So you might want to manually do a sudo apt-get --purge remove python-dev gcc libc6-dev unzip patch if you’re sure you don’t need these packages anywhere else. (Note: If you install them anywhere else in your puppet modules too, you’ll probably get an error from puppet about duplicate definitions anyway…)
The glassfish::initial_setup class has a lot of ordering added, but we’ve taken care of only requiring those resources that are actually needed, so the install isn’t broken if one thing doesn’t work. You’ll have to take care of the stuff that doesn’t work yourself, though.
Finally, on a second puppet run after the installation, the glassfish::cleanup class is included, which removes the crud we needed for the initial setup.
Some areas still need a little work, for example the initscript. It currently relies on sudo, which is not the nicest solution. That will be fixed eventually and I’ll update the tarball here. For now, enjoy and I hope this helps someone!
Do let us know if you have improvements to this puppet recipe!
Fluffy died :(
I bought her from a pet shop about 5,5 years ago and we’ve been through a lot together since then. But yesterday evening, when I went out to take care of the bunnies, I noticed Fluffy was not moving anymore. She didn’t even come to greet me when I opened the cage. So I prodded her a little and found her stone cold. Apparantly, she died somewhere during the day
I’ll remember her as my little bunny-dog, since she could fetch and come sit on my lap when I called out to her. She was always there when I opened her little house, because she wanted some petting. I’ll miss her.
Tags: 64bit, debian, glassfish, howto, java, opensolaris, pkg, python
leave a comment
GlassFish 3.0.1′s pkg tool using Debian’s Python packages
While setting up GlassFish 3.0.1 for a customer on Debian Lenny using 64 bit machines, I ran into the problem that the update tool shipped with GlassFish (OpenSolaris‘s pkg tool) uses a Python interpreter which is part of the package. That Python interpreter however is 32 bit, which requires the ia32 libraries to be installed. Worse, it requires lididn in 32 bit, which is not part of the default Debian packages, so I had to get that one from the (very nice) Debian Multimedia repository. Although that’s a quick fix to get stuff working, we rather not use these repositories on production machines, due to security concerns and the like. Also, upgrades are easier if you only use the standard Debian repositories.
So I decided to see if I could get it working with the Debian supplied Python interpreter. One problem is that there’s a shared object file written in C which is part of the pkg application. That file is a 32 bit ELF too. So we’re going to download that source and recompile it for 64 bit. If you’re on a 32 bit system, you can skip that step (although it doesn’t hurt to do it anyway). First, we need to install the following packages:
apt-get install python2.5 python2.5-dev gcc python-cherrypy python-mako python-openssl python-ply python-pycurl python-simplejson
Now download the source for the _actions.c file from here (link to webpage, press download in the top).
Compile it with the following command:
gcc -I/usr/include/python2.5 -shared -fpic -O2 _actions.c -o _actions.so
Keep the resulting .so file, we’re going to replace it once we’ve downloaded GlassFish. Which is the next step, actually. So download GlassFish and set it up somewhere. I downloaded the tarball and unzipped it into /opt/glassfish.
The resulting directory contains several directories, including a pkg and a glassfish directory. The /opt/glassfish/glassfish directory is the actual GlassFish application. The pkg directory contains the pkg tool which is used to upgrade the GlassFish addons and systems and stuff (don’t ask me about the details, I’m not a Java developer, only a sysadmin). The first time you start it, it installs some stuff. So just run the following:
/opt/glassfish/bin/pkg
Next, mv the file /opt/glassfish/pkg/bin/pkg to /opt/glassfish/pkg/bin/pkg.orig. We do this since this script does all kinds of magic which we do not need. Also, it runs the pkg python code with the python2.4 interpreter that’s part of the package. We don’t want that. Let’s fix it.
Make a simple script to replace the one we moved away. I use the following, which works for me:
#!/bin/sh python /opt/glassfish/pkg/bin/client.py
If you start it now, you’ll get an error:
$ python /opt/glassfish/pkg/bin/client.py Traceback (most recent call last): File "/opt/glassfish/pkg/bin/client.py", line 60, inimport pkg ImportError: No module named pkg
Ok, let’s fix that! Start with creating a directory called /opt/glassfish/pkg/custom-lib. You can change the name into anything you want, of course, as long as it’s clear that this is where you’re going to put the pkg python module. Actually, let’s do that immediatly: cp -r /opt/glassfish/pkg/vendor-packages/pkg /opt/glassfish/pkg/custom-lib
Change our script which we setup to run pkg into the following:
#!/bin/sh PYTHONPATH="/opt/glassfish/pkg/custom-lib" python /opt/glassfish/pkg/bin/client.py
You need to have only the pkg module in there, because the PYTHONPATH variable takes precedence over the other modules installed via the Debian packages. Run the script and you’ll get a new error:
Traceback (most recent call last): File "/opt/glassfish/pkg/bin/client.py", line 61, inimport pkg.actions as actions File "/opt/glassfish/pkg/custom-lib/pkg/actions/__init__.py", line 144, in from _actions import _fromstr ImportError: /opt/glassfish/pkg/custom-lib/pkg/actions/_actions.so: wrong ELF class: ELFCLASS32
If you don’t get this error, you’re on a 32 bit system and you’re done! Congratulations! Otherwise, we’re going to copy the _actions.so file we compiled earlier over the one that’s packaged with GlassFish 3.0.1. Just copy it over the other file, like so: cp _actions.so /opt/glassfish/pkg/custom-lib/pkg/actions/_actions.so
Now we’re really done! You should be able to run /opt/glassfish/bin/pkg image-update now and update your currently installed GlassFish 3.0.1 with the latest modules and stuff. Awesome!
I’m in the process of creating a Debian package for GlassFish 3.0.1 which incorporated this fix. So if you’re not in a hurry or you’re reading this way after it was posted, you might want to check out debian.kumina.nl to see if the package is available.
Hope this helps someone!
Comments Off
WordPress MU and /etc/hosts file
Due to a silly networking problem originating from the LVS installation we’re using, we’re stuck with a setup in which machines in the DMZ cannot access themselves via their external addresses. This is a problem for several scripts which refer to their own URL when doing some maintenance. Especially with a certain WordPress MU installation managed by our friends from Interconnect IT, we ran into trouble when they tried to update their WordPress code.
Puppet to the rescue. Although not something I’m especially proud of, I can imagine other using this as an example to fix other problems. What we do is use the wp-config.php from the WordPress installation to get data from the database that WordPress MU connects to. We use a PHP script to retrieve that data and format it in a comma-separated-value list. We then use this output to create a Facter fact, which we use in puppet to create entries in the /etc/hosts file.
You could eliminate the bash scripting by making sure the PHP script copies the files and outputs in the correct format, but it’s been ages since I’ve written anything remotely PHPish, so I decided to only do the bare minimum in PHP and do the rest in bash. YMMV.
Now without further a-do, here’s the shell script we run:
#!/bin/sh
# We want to change to the directory where this script is installed.
OLDDIR=`pwd`
cd /opt/wp-domain
# Make sure we have an empty wp-settings.php, because wp-config.php includes
# it.
touch wp-settings.php
# Copy wp-config.php from the WordPress MU installation.
# CHANGEME You want to change this path, I'm sure...
cp /srv/www/wordpress-mu/wp-config.php .
# Get the output from the script.
# Some strange stuff to make sure we don't get an error
php output-list.php > /dev/null 2>&1
# FIXME Too lazy to think of a way to do this in one step...
if [ $? -gt 0 ]; then
cd $OLDDIR
exit 1
else
php output-list.php | rev | cut -c 2- | rev
cd $OLDDIR
exit 0
fi
This is the (very simple) PHP script we use:
<?
require_once('wp-config.php');
$db = mysql_connect(DB_HOST, DB_USER, DB_PASSWORD);
if (!$db) {
echo "Could not connect: " . mysql_error();
die(1);
}
mysql_select_db(DB_NAME, $db);
$query = "select domain from wp_blogs";
$result = mysql_query($query);
if (!$result) {
echo "Query failed: " . mysql_error();
die(1);
}
$ret = "";
while ($row = mysql_fetch_assoc($result)) {
$ret = $ret . $row['domain'] . ";";
}
echo $ret;
?>
This is the very small Fact I’ve written for it:
unless not FileTest.file?("/opt/wp-domain/getdomains.sh")
Facter.add("wordpressdomains") do
setcode do
%x{/opt/wp-domain/getdomains.sh}.chomp
end
end
end
And last but not least, the puppet code:
class kbp-wordpressmu {
file {
"/opt/wp-domain":
ensure => directory;
"/opt/wp-domain/getdomains.sh":
source => "puppet://puppet/kbp-wordpressmu/getdomains.sh",
mode => "755";
"/opt/wp-domain/output-list.php":
source => "puppet://puppet/kbp-wordpressmu/output-list.php";
}
$domains = split($wordpressdomains,";")
if $domains != [] and $domains != "" {
host { $domains:
ip => $ipaddress,
}
}
}
Do let me know if you think this can be way cleaner!
Comments Off
Puppet Tips&Tricks: checking if a value is present in an array
I tend to create fairly ubiquitous defines, which allow for a lot of functionality. For that, it would be nice if you could tell puppet “if value X is present in array Y, do this”. I made it a feature request for puppet (#3871), which was luckily accepted and will be implemented in the next version of puppet. However, for the time being I needed this fixed. So I spend some time creating an ugly solution for this in older versions of puppet. Hope it helps someone!
# Setup additional services for this vhost, if any are required.
# Start with a general check to prevent a lot of work when it's
# not needed.
if $allow != "" {
# FIXME Ideally we want something that simply does
# for i in allow do include $http::allow_$i
# but that doesn't work (yet?).
# W00t! That's going to be added in 2.6! #3871
if inline_template("<%= allow.include?('php5') %>") == "true" {
include allow_php5
}
if inline_template("<%= allow.include?('rewrite') %>") == "true" {
include allow_rewrite
}
if inline_template("<%= allow.include?('ruby') %>") == "true" {
include allow_ruby
}
if inline_template("<%= allow.include?('python') %>") == "true" {
include allow_python
}
}
Comments Off
Tips&Tricks: Get long running queries from PostgreSQL
Was looking for a method of getting queries that are running longer than 5 minutes out of a PostgreSQL. This solution needs stats_command_string enabled in the postgresql.conf, though. The query you can run:
echo "select procpid,datname,current_query,now() - pg_stat_activity.query_start as duration from pg_stat_activity where pg_stat_activity.current_query <> '
Hope this helps someone!
Automatic lawnmower
Ah man, I want one!
(via There I Fixed It)
Why high fps matters
I just watched “Time: Daytime”, part 1 of the BBC series “Time”, presented by the awesome Michio Kaku, a physicist. A very interesting search into time, with some very exciting and interesting discoveries. Being a IT guy, one thing struck me in particular: The test in which time seems to slow when you’re in a life-threatening situation. For me, this explains way better why gamers want the highest fps possible.
The test, in which a guy falls from a 12-story construction, shows that adrenaline (or another hormone that influences us when we’re stressed) actually has an effect on how we perceive time. Even better, adrenaline seems not only to increase our heart rate and breathing, it also increases the speed in which our brain processes signals! The test included a high framerate LED display which was showing a number and it’s negative in a very high oscillation. So high that normally, the guy the test was conducted on, couldn’t read it. When he was falling down with the display attached to his arm, he could actually read the number (or at least close enough to indicate his brain sped up).
There we have our conclusion to why framerate matters for gamers. Actually, the question always intrigued me, since we know form television and movies that anything above a framerate of 24fps is not detected. Although there are some other reasons why a high framerate matters, I think this test actually showed us one of the most important reasons. Gamers tend to be high on adrenaline, after all!
Sorting Apache log files
Last week I had to sort several months worth of Apache log files to feed them to Webalizer. These came from several servers, so it was fairly difficult to get the data together and in the correct format. I ended up using a small python sorting script, especially written for this. Maybe it’ll help someone else, so I’m sharing it here. Just pipe the logs through the script and direct the output to a file.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 | import sys data = sys.stdin.readlines() def compare_apache_dates (date1, date2): str1 = date1.split()[3] str2 = date2.split()[3] months = ["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"] if str1[8:12] > str2[8:12]: return 1 elif str1[8:12] < str2[8:12]: return -1 elif months.index(str1[4:7]) > months.index(str2[4:7]): return 1 elif months.index(str1[4:7]) < months.index(str2[4:7]): return -1 elif str1[1:3] > str2[1:3]: return 1 elif str1[1:3] < str2[1:3]: return -1 elif str1[13:15] > str2[13:15]: return 1 elif str1[13:15] < str2[13:15]: return -1 elif str1[16:18] > str2[16:18]: return 1 elif str1[16:18] < str2[16:18]: return -1 elif str1[19:21] > str2[19:21]: return 1 elif str1[19:21] < str2[19:21]: return -1 else: return 0 data.sort(compare_apache_dates) for line in data: if line[1:4] == "var": # Small hack to fix output lines from egrep sys.stdout.write( line.split(":",1)[1] ) else: sys.stdout.write( line ) |
Puppet Tips&Tricks: testing your regsubst replacings
This is part of an ongoing series. Check this for the complete series!
Regular Expressions are important for us. We use them a lot, mostly because it’s such a powerful tool. So our puppet recipes contain several regsubst calls too. One problem is usually that regex can be fairly complex and you’d like a nice way to check it out. After some talk on IRC (#puppet on freenode), monarchus gave me some tips for this. Simply use the interactive Ruby shell, irb, for this.
Now, I wanted to check whether a certain string ended in “:ssl” or not. I tested my regex replacement as follows:
$ irb >> s1="www.kumina.nl:ssl" => "www.kumina.nl:ssl" >> s2="www.kumina.nl" => "www.kumina.nl" >> s1.sub(/.*:(ssl)$/, "\\1") => "ssl" >> s2.sub(/.*:(ssl)$/, "\\1") => "www.kumina.nl" >>
From this I gathered that the resulting regsubst call would be something like this:
if regsubst($name, '.*:(ssl)$', '\1') == "ssl" { ... do stuff ... }
Awesome! Now, if you want to try out a global replace, instead of sub, use gsub.
If you want to use regex in your selector, you can simply use egrep on the commandline, like so:
echo "foo" | egrep "foo|bar"
You can also try it in irb, with the following:
>> a = "foo"
=> "foo"
>> a.match("foo|bar")
=> #
>> b = "beastieboys"
=> "beastieboys"
>> b.match("foo|bar")
=> nil
>>
Hope this helps someone!
Checking visitor IPs with apachetop
We have one customer’s site that’s running on a, well, let’s call it a not-so-very-good platform. If it gets too many hits, the database tends to get slow very quickly, which results in a severe congestion. I was looking for a way to easily check if a certain IP has been hitting the same site a lot, since that’s usually the cause (someone who wants to download the entire site or something). Thanks to a tip on IRC, I finally found the tool for that and it turns out it was installed already!
The solution: apachetop. I tend to start it as follows: apachetop -H 5000 -d 2 and when it has started, I press ‘d’ once, which will make it show me the source ip addresses. Nice!
PS. Another solution: tail -10000 access.log | cut -d ' ' -f 1 | sort | uniq -c | sort -nr | head -n 10
Puppet Tips&Tricks: Converting booleans to numbers
This post is a part of my series about tips and tricks for puppet, the configuration management tool we prefer to use here at Kumina.
Puppet has nice support for Nagios via its Nagios-specific resources. However, this requires you to use “0″ and “1″ instead of “true” and “false” for booleans in Nagios. Because we like uniformity, I’ve created a little function that simply converts a named boolean to a numerical. Check it out:
module Puppet::Parser::Functions
newfunction(:bool2num, :type => :rvalue) do |args|
case args[0]
when "true" then "1"
when "false" then "0"
when "1" then "1"
when "0" then "0"
when true then "1"
when false then "0"
else raise Puppet::ParseError, "Either specify true, false, 1 or 0."
end
end
end
Hope this helps someone!
Puppet Tips&Tricks: Getting the version from a package
Sometimes you need to know the version of a package before you can do anything useful. For example, we need to make sure the augeas-lenses package is 0.6.0 or newer, otherwise it doesn’t include the aptpreferences lens. We need that lens to modify /etc/apt/preferences in a nice way.
It would be very nice if there was some sort of function that could check on the client which version a certain package was, but during the design of puppet it was decided that puppet is not allowed to execute functions on a client, all functions are executed on the puppetmaster. So that’s not a valid option.
Another solution would be to create puppet facts for every package installed containing their version. Although that would help, it would clutter the facts a bit and probably make each puppetd run quite a bit longer. Also, all those facts would have to be stored in the database, if you’re using storeconfigs, which would add a lot of useless data there (although I can imagine setups which would actually appreciate this). So I chose for a simpler way, creating a fact specifically for augeas-lenses.
Getting the version from the commandline is easy on Debian, simply execute dpkg-query -W -f='${Version}' augeas-lenses. Creating a fact from that, is in its turn easy too:
if FileTest.exists?("/usr/bin/dpkg-query")
Facter.add("augeas_version") do
setcode do
%x{/usr/bin/dpkg-query -W -f='${Version}' augeas-lenses}
end
end
end
I created a file in our common module, lib/facter/augeas_version.rb, since that module is included on every host and the fact isn’t specific for a certain module. Preferably, you should add the fact to the module which uses it, of course, to keep things separated.
Now I can simply do:
# We need to compare the current augeas version, to see if we have the
# aptpreferences lens available. It's only been included since 0.6.0.
if versioncmp($augeas_version, '0.6.0') < 0 {
# Work with templates and concatenated files
notify { "Using concatenated files, augeas-lenses version $augeas_version":; }
} else {
# Work with augeas
notify { "Using augeas, augeas-lenses version $augeas_version":; }
}
Awesome puppet! Hope this helps someone.
Puppet Tips&Tricks: debugging includes and inheritance
This is the second post in a series of mine, describing some of the methods I use while developing our new Puppet modules. Read the first post in the series here: Variable variables.
Even though there are lots of interesting tools these days for debugging running code and even scripted code, I still seem to grab at the old method of printing random stuff in between my code. Especially when debugging my puppet modules. Some stuff to keep in mind when you also do this:
- All functions (like err, debug or warning) are server side only. This means you’ll have to search the log on your puppetmaster if you want to see the output from those.
- If you want to have output on your client, which is usually more convenient for me, use the notify resource. Use it like so:
notify { "Yes, we really arrived at this class.":; }
Which will output on the client something like this:
notice: //nagios::client/Notify[Yes, we really arrived at this class.]/message: defined 'message' as 'Yes, we really arrived at this class.'
Which at least shows you that a certain class is loaded. - Keep in mind that you can also include variables in the string you add! Very helpful to see if you get what you were expecting. I use that a lot to see if inline_templates give the output I expect.
Hope this helped someone!
Puppet Tips&Tricks: Variable variables
[Repost of my post on the Kumina blog.]
This is the first post in a series of mine, while I’m reinventing our puppet modules. Puppet is the tool we use to maintain most machines in our care. We make it a point to share our modules as much as possible, so others might benefit from them.
Today I was working on our kbp_firewall module, which sets some variables that other modules can use via qualified variables. We differentiate between “protected”, “public” and “management” network interfaces on each host. These are always separate (virtual) interfaces, to make our life a little easier. I wanted to make both the interface and the IP address for these easily available, but I wanted most of it to happen automagically after puppet has determined which interface is connected to which network. I wanted to use the facter fact $ipaddress_(interface name), which is created for each interface, like for example $ipaddress_eth0.
Currently, there’s no way to use something like $ipaddress_${interface}, although I’ve been told on the #puppet IRC channel that this will be implemented in the next major version. So I had to create a more hackish solution. Inline_template to the rescue!
What I currently do:
$protected_ip = inline_template("<%= ipaddress_${protected_if} %>")
This will probably work in future versions too, so I feel confortable implementing it like this. Once we’ve fully switched to the next major release, I can slowly work through the code to make it all a bit better readable.
Hope this helps someone!
Shit happens
Blatantly stolen from the Shit Happens website. It’s funny though. Too bad it’s in Dutch. The doctor is operating on a guy hit by firework in the face. They had to use another body part to fix his face…



















