2

I'm developer of a java software and try to find a smart way to get my app distributed and configured in our datacenter. For that, I build an rpm package and we have set up a satellite. Target OS is Red Hat Enterprise. For configuration management we use puppet.

Until now, everything is running fine. We are setting DB connection strings and hostnames based on node configurations in puppet. These go into erb template files that we also have in the puppet master.

But now, I need to patch a single file that is part of the RPM. This is a file that is generated on build and changes with every build, so we do not like to put it into puppet. There is an identifier in (freely chosen, like <% baseURL %>). Unfortunately, we need to set a base URL in this file which depends on the node where it goes. I thought about putting our file in the RPM as .erb, but it seems that puppet can not use local files from the target system as templates, in all examples I've seen the templates are located on the puppet master.

The other problem is, that the transformation from the template into the real config file must happen if either the package is updated or the baseUrl configuration changes.

I would like to utilize the puppet templating for this, but I'm not sure if this works.

My current solution is: I use puppet to create a node-dependent file on every machine in /etc/myapp/webstart_baseurl. It looks like:

MYAPP_WEBSTART_BASEURL=http\\:\\/\\/10.12.1.42\\/myapp_ws\\/
export MYAPP_WEBSTART_BASEURL

Then I wrote a shell script, that I included in my RPM. This is placed in /usr/bin/patchHostnameForWebstart.sh

#!/bin/sh

#the file where to load the baseUrl from (in property $MYAPP_WEBSTART_BASEURL)
MYAPP_WEBSTART_SERVERCONFIG=/etc/myapp/webstart_baseurl

MYAPP_JNLP_TOKEN=@@myapp.webstart.baseurl@@

if [ -f $MYAPP_WEBSTART_SERVERCONFIG ]
then
    source $MYAPP_WEBSTART_SERVERCONFIG
    echo "found config for webstart server, baseUrl is $MYAPP_WEBSTART_BASEURL"
    echo "replacing tokens MYAPP_JNLP_TOKEN .."

    find /var/www/html/myapp_ws -name *.jnlp -print -exec sed -i  "s/${MYAPP_JNLP_TOKEN}/${MYAPP_WEBSTART_BASEURL}/g" {} \;
    echo "url tokens of all .jnlp files in /var/www/html/myapp_ws have been processed"

else
    echo "WARNING! no config for webstart server found, baseUrl of .jnlp files might not be set"
    exit 1

fi

To separate the script from puppet has the advantage that it can be run directly in rpm install as well as from puppet in case the baseUrl config changes.

However, the downsides of this solution are that I had to implement the substitution on my onw and that I need to write the baseUrl config in this very ugly, double quoted way with lots of backslashes. I think this is quite error-prone if somebody else should change it.

Any improvement suggestions would be great. Thanks in advance

Michel

mkraemerx
  • 123
  • 4

2 Answers2

3

puppet can use local information.. If you write a facter script that sets a fact.. you can reference that value from inside puppet.

Example

$ facter puppetversion
2.6.4

I can use $puppetversion in my template or pp file to get 2.6.4. Writing a facter script is pretty easy and you can use puppet to distribute the facter script to place it in the correct location so when you run facter it will add it to the list.

http://projects.puppetlabs.com/projects/1/wiki/Adding_Facts

Mike
  • 22,310
  • 7
  • 56
  • 79
  • Thanks for that hint. But I`m not sure if this is sufficient. Is it possible to provide the facter output as a template for a config file substition like in: `my_config_file { "/etc/myapp/config.properties": content => template("myapp/config.properties.erb"), } }` – mkraemerx Sep 19 '11 at 12:47
  • 2
    You can reference any facter fact in a template like <%= fact %> – Mike Sep 19 '11 at 18:02
  • when you suggested this I found it much too complicated. But now I think, this is the solution :) – mkraemerx Jan 31 '12 at 12:02
0

Why not exec a perl script to patch it?

$baseURL = "/path/with/$fact/inside"
exec { "perl -p -i.bak -e 's^\Q<% baseURL %>\E^$baseURL^' /path/to/file/":
    onlyif  => "grep -q '<% baseURL %>' /path/to/file",
    require => Package['yourrpm'],
}
Daniel C. Sobral
  • 5,713
  • 6
  • 34
  • 48
  • unfortunately, this way I need to write the substitution logic by myself, but this would work. – mkraemerx Sep 20 '11 at 08:16
  • @mkimd You could use Augeas, but my experience is that it is more trouble than it is worth. You could also have the entire file on the puppet server as a template, but my understanding is that you do not wish to keep the file on the puppet server up-to-date. – Daniel C. Sobral Sep 20 '11 at 14:30