summaryrefslogtreecommitdiff
path: root/files/concatfragments.sh
blob: aac827dfebe95c6a1536c1f0df0a81b2f0f26cdb (plain)
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
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
#!/bin/sh

# Script to concat files to a config file.
#
# Given a directory like this:
# /path/to/conf.d
# |-- fragments
# |   |-- 00_named.conf
# |   |-- 10_domain.net
# |   `-- zz_footer
#
# The script supports a test option that will build the concat file to a temp location and 
# use /usr/bin/cmp to verify if it should be run or not.  This would result in the concat happening
# twice on each run but gives you the option to have an unless option in your execs to inhibit rebuilds.
# 
# Without the test option and the unless combo your services that depend on the final file would end up 
# restarting on each run, or in other manifest models some changes might get missed.
#
# OPTIONS:
#  -o	The file to create from the sources
#  -d	The directory where the fragments are kept
#  -t	Test to find out if a build is needed, basically concats the files to a temp
#       location and compare with what's in the final location, return codes are designed
#       for use with unless on an exec resource
#  -w   Add a shell style comment at the top of the created file to warn users that it 
#       is generated by puppet
#  -f   Enables the creation of empty output files when no fragments are found
#  -n	Sort the output numerically rather than the default alpha sort
#  -g	Do NOT use the GNU entensions to find, xargs and sort; might cause problems on suitably funky filenames
#
# the command: 
#
#   concatfragments.sh -o /path/to/conffile.cfg -d /path/to/conf.d
#
# creates /path/to/conf.d/fragments.concat and copies the resulting 
# file to /path/to/conffile.cfg.  The files will be sorted alphabetically
# pass the -n switch to sort numerically.
# 
# The script does error checking on the various dirs and files to make
# sure things don't fail.

OUTFILE=""
WORKDIR=""
TEST=""
FORCE=""
WARN=""
SORT1="-z"
SORT2=""
FINDARG="-print0"
XARGSARG="-0"

PATH=/sbin:/usr/sbin:/bin:/usr/bin

while getopts "o:s:d:tnw:fg" options; do
	case $options in
		o ) OUTFILE=$OPTARG;;
		d ) WORKDIR=$OPTARG;;
		n ) SORT2="-n";;
		w ) WARNMSG="$OPTARG";;
		f ) FORCE="true";;
		t ) TEST="true";;
		g ) FINDARG="" ; XARGSARG="" ; SORT1="" ;;
		* ) echo "Specify output file with -o and fragments directory with -d"
		    exit 1;;
	esac
done

SORTARG="$SORT1 $SORT2"

# do we have -o?
if [ x${OUTFILE} = "x" ]; then
	echo "Please specify an output file with -o"
	exit 1
fi

# do we have -d?
if [ x${WORKDIR} = "x" ]; then
	echo "Please fragments directory with -d"
	exit 1
fi

# can we write to -o?
if [ -f ${OUTFILE} ]; then
	if [ ! -w ${OUTFILE} ]; then
		echo "Cannot write to ${OUTFILE}"
		exit 1
	fi
else
	if [ ! -w `dirname ${OUTFILE}` ]; then
		echo "Cannot write to `dirname ${OUTFILE}` to create ${OUTFILE}"
		exit 1
	fi
fi

# do we have a fragments subdir inside the work dir?
if [ ! -d "${WORKDIR}/fragments" ]  && [ ! -x "${WORKDIR}/fragments" ]; then
	echo "Cannot access the fragments directory"
	exit 1
fi

# are there actually any fragments?
if [ ! "$(ls -A ${WORKDIR}/fragments)" ]; then
	if [ x${FORCE} = "x" ]; then
		echo "The fragments directory is empty, cowardly refusing to make empty config files"
		exit 1
	fi
fi

cd ${WORKDIR}

if [ x${WARNMSG} = "x" ]; then
	: > "fragments.concat"
else
	printf '%s\n' "$WARNMSG" > "fragments.concat"
fi

# find all the files in the fragments directory, sort them numerically and concat to fragments.concat in the working dir
find fragments/ -type f -follow $FINDARG |sort ${SORTARG}|xargs $XARGSARG cat >>"fragments.concat"

if [ x${TEST} = "x" ]; then
	# This is a real run, copy the file to outfile
	cp fragments.concat ${OUTFILE}
	RETVAL=$?
else
	# Just compare the result to outfile to help the exec decide
	cmp ${OUTFILE} fragments.concat
	RETVAL=$?
fi

exit $RETVAL