So here's a Makefile to install foo.conf, based on a master copy called foo.conf.master. It installs it to the currently directory rather than /etc, just for testing purposes:
all: foo.conf.copied
foo.conf.copied: foo.conf.master foo.conf
cp foo.conf.master foo.conf
touch $@
# Recipe to tell make that it is okay for foo.conf not to exist beforehand.
foo.conf:
So then create foo.conf.master:
$ touch foo.conf.master
$
and you're ready to test:
$ make
cp foo.conf.master foo.conf
touch foo.conf.copied
$
The point is that if I (with my "trusted" sysadmin hat on) modify foo.conf.master then make (possibly called by cron) will roll out the update:
$ touch foo.conf.master
$ make
cp foo.conf.master foo.conf
touch foo.conf.copied
$
But equally important: if I (with my "rogue" sysadmin hat on) modify the installed version then make will back out the update:
$ touch foo.conf
$ make
cp foo.conf.master foo.conf
touch foo.conf.copied
$
Woohoo.
Okay, so now the problem: obviously foo.conf isn't the only file I want do this for, so I need to change my static rules to pattern rules. Okay, that's easy: substitute foo.conf for % in targets and dependencies, substitute foo.conf for $* in the commands, and make a minor modification to the last recipe (which would otherwise become only '%:') so that it doesn't look like I'm trying to cancel a builtin pattern rule.
So clean up and create this Makefile:
all: foo.conf.copied
%.copied: %.master %
cp $*.master $*
touch $@
# Recipe to tell make that it is okay for foo.conf not to exist beforehand.
# Nop tells make that I'm not *cancelling* a pattern rule here
# (see http://ift.tt/29qn9qr).
%: ;
But this doesn't work:
$ make
make: *** No rule to make target `foo.conf.copied', needed by `all'. Stop.
$
The error message is misleading; it is really foo.conf that it doesn't know how to make, which can be demonstrated by adding the following at the bottom of the Makefile:
foo.conf:
touch $@
But then that's a static rule again, which I don't want.
There are a couple of requirements I would like to satisfy, which the above example doesn't demonstrate, which are:
- foo.conf should be installable anywhere in the filesystem (e.g. /etc/foo/server/foo.conf)
- foo.conf.master should be in a central directory, or subdirectly thereof, for all master versions, preferably without the '.master' extension (e.g. ~/poor-mans-puppet/master-files/etc/foo/foo.conf)
- foo.conf.copied should be in a central directory, not in the same directory as foo.conf (e.g. ~/poor-mans-puppet/timestamp-files/etc/foo/foo.conf)
After much googling, hair pulling, I'm asking here! Any ideas please? (PS: if copying Makefiles from here, remember to change indentation back to tabs.)
Aucun commentaire:
Enregistrer un commentaire