-
Notifications
You must be signed in to change notification settings - Fork 8
/
puppet-git-receiver-update-hook
executable file
·200 lines (161 loc) · 5.11 KB
/
puppet-git-receiver-update-hook
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
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
#!/bin/bash
function msg { echo -e "\E[${COLOUR}m$@\E[0m" >&2 ; }
function notice { COLOUR="0;36" msg "notice: $@" ; }
function error { COLOUR="0;31" msg "err: $@" ; }
function cleanup {
if [[ "$DEST" != "" ]] && [ -d "$DEST" ] ; then
rm -rf $DEST || true
fi
}
function cleanup_and_error {
cleanup
error $2
exit $1
}
set -o pipefail
# shell variable config file
config_file=/etc/puppet-git-receiver.conf
# Act as an external node classifier if necessary
if env | grep --quiet "PUPPET_ENC_FILE" ; then
sleep 1 # Without this sleep, puppet randomly hangs
if [ -e "$PUPPET_ENC_FILE" ] ; then
cat $PUPPET_ENC_FILE
else
echo -e "classes:\n"
fi
exit 0
fi
DEST=
# git branch to consider for puppet
BRANCH=master
# extra options passed to puppet agent
PUPPET_OPTIONS=
# Override variables with those in the config file, if it exists
test -f "${config_file}" && source "${config_file}"
full_puppet_options="$PUPPET_OPTIONS $(git config puppet-receiver.args)"
# --- Command line
refname="$1"
oldrev="$2"
newrev="$3"
# --- Safety check
if [ -z "$GIT_DIR" ] ; then
echo "Don't run this script from the command line." >&2
echo " (if you want, you could supply GIT_DIR then run" >&2
echo " $0 <ref> <oldrev> <newrev>)" >&2
exit 1
fi
if [ -z "$refname" -o -z "$oldrev" -o -z "$newrev" ] ; then
echo "Usage: $0 <ref> <oldrev> <newrev>" >&2
exit 1
fi
if [ "$refname" != "refs/heads/$BRANCH" ] ; then
exit 0
fi
notice "puppet-git-receiver running on `hostname -f`"
if ! which puppet >/dev/null ; then
cleanup_and_error 1 "Cannot find puppet"
fi
if ! which facter >/dev/null ; then
cleanup_and_error 1 "Cannot find facter utility"
fi
puppetver=$(facter puppetversion)
if [[ $puppetver == 2.6.* || $puppetver == 0.2* ]] ; then
validate_command="xargs --no-run-if-empty -n1 puppet --parseonly"
else
validate_command="xargs --no-run-if-empty puppet parser validate"
fi
DEST=$(mktemp -d --suffix=.puppet-git-receiver)
module_path="${DEST}/modules"
if ! git archive --format=tar $newrev | (cd $DEST && tar xf -) ; then
cleanup_and_error 1 "Encountered a problem extracting the incoming git tree $newrev"
fi
skip_validation=$(git config --bool puppet-receiver.skip-validation)
if [ "$skip_validation" == "true" ] ; then
notice "Skipping puppet validation due to config option puppet-receiver.skip-validation"
else
notice "Validating puppet manifests for $refname"
if ! find $DEST -name "*.pp" | $validate_command |& sed -u "s,$DEST/,,g" ; then
cleanup_and_error 1 "Encountered a problem validating the puppet manifests"
fi
fi
pf_file="${DEST}/.puppetforge-modules"
pf_path="${DEST}/puppetforge-modules"
if [ -e $pf_file ] ; then
# FIXME: Check puppet version
notice "Installing puppet forge modules"
mkdir -p $pf_path || cleanup_and_error 1 "Couldn't create puppet forge modules directory: $pf_path"
while read -r module_name module_version ; do
if [[ "$module_name" != "" && ! "$module_name" =~ ^# ]] ; then
if [[ "$module_version" != "" ]] ; then
pf_version_arg="--version $module_version"
fi
puppet module install --force --target-dir $pf_path $pf_version_arg $module_name |& sed -u "s,$pf_path,,g"
if [ $? -ne 0 ] ; then
cleanup_and_error 1 "Error installing puppet forge module $module_name $module_version"
fi
fi
done < $pf_file
module_path="$module_path:$pf_path"
fi
if [ -e "${DEST}/Puppetfile" ] ; then
if ! which librarian-puppet >/dev/null ; then
error 'Puppetfile found in repo but librarian-puppet not installed.'
else
notice "Installing librarian-puppet modules"
lp_options=$(git config puppet-receiver.librarian-puppet-args)
(cd $DEST; librarian-puppet install $lp_options)
fi
fi
manifest_file="${DEST}/manifests/site.pp"
fqdn=`facter fqdn`
enc_file="${DEST}/manifests/nodes/${fqdn}.yml"
if [ ! -e $enc_file ] ; then
enc_file="${DEST}/manifests/site.yml"
fi
if [ ! -e $enc_file ] ; then
enc_file=""
fi
if [ ! -e $manifest_file -a ! -e "$enc_file" ] ; then
notice "No puppet manifest detected"
cleanup
exit 0
fi
# Make a blank manifest if necessary
if [ ! -e $manifest_file ] ; then
touch $manifest_file
fi
if [ -e "$enc_file" ] ; then
notice "Using external node classification file ${enc_file//$DEST\/}"
fi
confdir="${DEST}/puppet-confdir"
mkdir -p $confdir/ssl
cat <<EOF > "${confdir}/puppet.conf"
[main]
node_terminus = exec
external_nodes = `pwd`/$0
templatedir=${DEST}/templates
EOF
if [ -e "${DEST}/hiera" ] ; then
cat <<EOF > "${confdir}/hiera.yaml"
---
:backends: - yaml
- puppet
:hierarchy: - %{hostname}
- %{fqdn}
- %{domain}
- %{ec2_placement_availability_zone}
- default
:yaml:
:datadir: ${DEST}/hiera
:puppet:
:datasource: data
EOF
fi
notice "Applying puppet manifests"
sudo -H PUPPET_ENC_FILE=$enc_file puppet apply --confdir=${confdir} $full_puppet_options --detailed-exitcodes --modulepath=${module_path} $manifest_file |& sed -u "s,$DEST/,,g"
PUPRET=$?
if ! [ $PUPRET -eq 0 -o $PUPRET -eq 2 ] ; then
cleanup_and_error 1 "Encountered a problem applying the puppet manifest, rejecting update"
fi
notice "Puppet manifests applied successfully"
cleanup