forked from samrocketman/jenkins-bootstrap-shared
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathprovision_jenkins.sh
executable file
·504 lines (438 loc) · 14.3 KB
/
provision_jenkins.sh
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
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
#!/bin/bash
#Created by Sam Gleske (https://github.com/samrocketman)
#Wed May 20 11:09:18 EDT 2015
#Mac OS X 10.9.5
#Darwin 13.4.0 x86_64
#GNU bash, version 3.2.53(1)-release (x86_64-apple-darwin13)
#curl 7.30.0 (x86_64-apple-darwin13.0) libcurl/7.30.0 SecureTransport zlib/1.2.5
#awk version 20070501
#java version "1.7.0_55"
#Java(TM) SE Runtime Environment (build 1.7.0_55-b13)
#Java HotSpot(TM) 64-Bit Server VM (build 24.55-b03, mixed mode)
#DESCRIPTION
# Provisions a fresh Jenkins on a local laptop, updates the plugins, and runs
# it.
# 1. Creates a JAVA_HOME.
# 2. Downloads Jenkins.
# 3. Updates the Jenkins plugins to the latest version.
#USAGE
# Automatically provision and start Jenkins on your laptop.
# mkdir ~/jenkins_testing
# cd ~/jenkins_testing
# provision_jenkins.sh bootstrap
# Kill and completely delete your provisioned Jenkins.
# cd ~/jenkins_testing
# provision_jenkins.sh purge
# Update all plugins to the latest version using jenkins-cli
# cd ~/jenkins_testing
# provision_jenkins.sh update-plugins
# Start or restart Jenkins.
# cd ~/jenkins_testing
# provision_jenkins.sh start
# provision_jenkins.sh restart
# Stop Jenkins.
# provision_jenkins.sh stop
#
# USER CUSTOMIZED VARIABLES
#
#Latest Release
jenkins_url="${jenkins_url:-http://mirrors.jenkins-ci.org/war/latest/jenkins.war}"
#LTS Jenkins URL
#jenkins_url="${jenkins_url:-http://mirrors.jenkins-ci.org/war-stable/latest/jenkins.war}"
JENKINS_HOME="${JENKINS_HOME:-../my_jenkins_home}"
JENKINS_WEB="${JENKINS_WEB:-http://localhost:8080/}"
JENKINS_CLI="${JENKINS_CLI:-java -jar ./jenkins-cli.jar -s ${JENKINS_WEB} -noKeyAuth}"
JENKINS_START="${JENKINS_START:-java -Xms4g -Xmx4g -jar jenkins.war}"
#remove trailing slash
JENKINS_WEB="${JENKINS_WEB%/}"
CURL="${CURL:-curl}"
#Get JAVA_HOME for java on Mac OS X
#will only run if OS X is detected
if uname -rms | grep Darwin &> /dev/null; then
if [ -z "${JAVA_HOME:-}" ]; then
JAVA_HOME="$(/usr/libexec/java_home)"
PATH="${JAVA_HOME}/bin:${PATH}"
fi
echo "JAVA_HOME=${JAVA_HOME}"
java -version
fi
export jenkins_url JENKINS_HOME JAVA_HOME PATH JENKINS_CLI CURL
#
# SCRIPT CONSOLE SCRIPTS
#
function script_skip_wizard() {
cat <<'EOF'
import hudson.util.PluginServletFilter
def j=Jenkins.instance
if('getSetupWizard' in j.metaClass.methods*.name.sort().unique()) {
def w=j.getSetupWizard()
if(w != null) {
try {
w.completeSetup()
}
catch(Exception e) {
//pre Jenkins 2.6
w.completeSetup(j)
PluginServletFilter.removeFilter(w.FORCE_SETUP_WIZARD_FILTER)
}
j.save()
println 'Wizard skipped.'
}
}
EOF
}
function script_disable_usage_stats() {
echo 'Jenkins.instance.setNoUsageStatistics(true)'
}
function script_upgrade_plugins() {
cat <<'EOF'
import hudson.model.UpdateSite
def j = Jenkins.instance
/*
Install Jenkins plugins
*/
def install(Collection c, Boolean dynamicLoad, UpdateSite updateSite) {
c.each {
println "Installing ${it} plugin."
UpdateSite.Plugin plugin = updateSite.getPlugin(it)
Throwable error = plugin.deploy(dynamicLoad).get().getError()
if(error != null) {
println "ERROR installing ${it}, ${error}"
}
}
null
}
//upgrade plugins
UpdateSite s = (UpdateSite) j.getUpdateCenter().getSite(UpdateCenter.ID_DEFAULT)
//download latest JSON update data
s.updateDirectlyNow(true)
install(s.getUpdates()*.getInstalled()*.getShortName(), false, s)
EOF
}
function script_install_plugins() {
cat <<EOF
def plugins = "$@".split('[, ]') as ArrayList
/*
Install Jenkins plugins
*/
def install(Collection c, Boolean dynamicLoad, UpdateSite updateSite) {
c.each {
println "Installing \${it} plugin."
UpdateSite.Plugin plugin = updateSite.getPlugin(it)
Throwable error = plugin.deploy(dynamicLoad).get().getError()
if(error != null) {
println "ERROR installing \${it}, \${error}"
}
}
null
}
def j = Jenkins.instance
//upgrade plugins
UpdateSite s = (UpdateSite) j.getUpdateCenter().getSite(UpdateCenter.ID_DEFAULT)
//only install plugins if they're missing
install(plugins - j.pluginManager.getPlugins()*.getShortName(), true, s)
EOF
}
#
# FUNCTIONS
#
function jenkins_script_console() {
echo "Calling jenkins_script_console $1"
${CURL} --data-urlencode "script=$(eval "$@")" ${JENKINS_WEB}/scriptText
}
#CSRF protection support
function is_crumbs_enabled() {
use_crumbs="$( $CURL -s ${JENKINS_WEB}/api/json?pretty=true 2> /dev/null | python -c 'import sys,json;exec "try:\n j=json.load(sys.stdin)\n print str(j[\"useCrumbs\"]).lower()\nexcept:\n pass"' )"
if [ "${use_crumbs}" = "true" ]; then
return 0
fi
return 1
}
#CSRF protection support
function get_crumb() {
${CURL} -s ${JENKINS_WEB}/crumbIssuer/api/json | python -c 'import sys,json;j=json.load(sys.stdin);print j["crumbRequestField"] + "=" + j["crumb"]'
}
#CSRF protection support
function csrf_set_curl() {
if is_crumbs_enabled; then
if [ ! "${CSRF_CRUMB}" = "$(get_crumb)" ]; then
if [ -n "${CSRF_CRUMB}" ]; then
#remove existing crumb value from curl command
CURL="$(echo "${CURL}" | sed "s/ -d ${CSRF_CRUMB}//")"
fi
export CSRF_CRUMB="$(get_crumb)"
export CURL="${CURL} -d ${CSRF_CRUMB}"
echo "Using crumbs for CSRF support."
elif ! echo "${CURL}" | grep -F "${CSRF_CRUMB}" &> /dev/null; then
export CURL="${CURL} -d ${CSRF_CRUMB}"
echo "Using crumbs for CSRF support."
fi
fi
}
function is_auth_enabled() {
no_authentication="$( $CURL -s ${JENKINS_WEB}/api/json?pretty=true 2> /dev/null | python -c 'import sys,json;exec "try:\n j=json.load(sys.stdin)\n print str(j[\"useSecurity\"]).lower()\nexcept:\n pass"' )"
#check if authentication is required.;
#if the value of no_authentication is anything but false; then assume authentication
if [ ! "${no_authentication}" = "false" ]; then
echo -n "Authentication required..."
if [ -e "${JENKINS_HOME}/secrets/initialAdminPassword" ]; then
echo "DONE"
return 0
else
echo "FAILED"
echo "Could not set authentication."
echo "Missing file: ${JENKINS_HOME}/secrets/initialAdminPassword"
exit 1
fi
fi
return 1
}
function url_ready() {
url="$1"
echo -n "Waiting for ${url} to become available."
while [ ! "200" = "$(curl -sLiI -w "%{http_code}\\n" -o /dev/null ${url})" ]; do
echo -n '.'
sleep 1
done
echo 'ready.'
}
function download_file() {
#see bash man page and search for Parameter Expansion
if [ "$#" = 1 ]; then
url="$1"
file="${1##*/}"
else
url="$1"
file="$2"
fi
url_ready "${url}"
if [ ! -e "${file}" ]; then
curl -SLo "${file}" "${url}"
fi
}
function jenkins_status() {
#check to see if jenkins is running
#will return exit status 0 if running or 1 if not running
STATUS=1
if [ -e "jenkins.pid" ]; then
ps aux | grep -v 'grep' | grep 'jenkins\.war' | grep "$(cat jenkins.pid)" &> /dev/null
STATUS=$?
fi
return ${STATUS}
}
function start_or_restart_jenkins() {
#start Jenkins, if it's already running then stop it and start it again
if [ -e "jenkins.pid" ]; then
echo -n 'Jenkins might be running so attempting to stop it.'
kill $(cat jenkins.pid)
#wait for jenkins to stop
while jenkins_status; do
echo -n '.'
sleep 1
done
rm jenkins.pid
echo 'stopped.'
fi
echo 'Starting Jenkins.'
${JENKINS_START} >> console.log 2>&1 &
echo "$!" > jenkins.pid
}
function stop_jenkins() {
if [ -e "jenkins.pid" ]; then
echo -n 'Jenkins might be running so attempting to stop it.'
kill $(cat jenkins.pid)
#wait for jenkins to stop
while ps aux | grep -v 'grep' | grep "$(cat jenkins.pid)" &> /dev/null; do
echo -n '.'
sleep 1
done
rm jenkins.pid
echo 'stopped.'
fi
}
function update_jenkins_plugins() {
#download the jenkins-cli.jar client
download_file "${JENKINS_WEB}/jnlpJars/jenkins-cli.jar"
echo 'Updating Jenkins Plugins using jenkins-cli.'
UPDATE_LIST="$( ${JENKINS_CLI} list-plugins | awk '$0 ~ /\)$/ { print $1 }' )"
if [ ! -z "${UPDATE_LIST}" ]; then
${JENKINS_CLI} install-plugin ${UPDATE_LIST}
fi
}
function jenkins_cli() {
#download the jenkins-cli.jar client
download_file "${JENKINS_WEB}/jnlpJars/jenkins-cli.jar"
echo "Executing: ${JENKINS_CLI} $@"
${JENKINS_CLI} $@
}
function force-stop() {
if [ -e 'jenkins.pid' ]; then
kill -9 $(cat jenkins.pid) 2> /dev/null
rm -f jenkins.pid
fi
}
#
# main execution
#
case "$1" in
bootstrap)
shift
skip_restart='false'
while [ "$#" -gt '0' ]; do
case $1 in
--skip-restart)
skip_restart='true'
shift
;;
*)
echo "Error invalid arument provided to bootstrap command: $1"
exit 1
;;
esac
done
#provision Jenkins by default
#download jenkins.war
download_file ${jenkins_url} jenkins.war
echo "JENKINS_HOME=${JENKINS_HOME}"
start_or_restart_jenkins
url_ready "${JENKINS_WEB}/jnlpJars/jenkins-cli.jar"
#try enabling authentication
if is_auth_enabled; then
export CURL="${CURL} -u admin:$(<${JENKINS_HOME}/secrets/initialAdminPassword)"
fi
#try enabling CSRF protection support
csrf_set_curl
jenkins_script_console script_skip_wizard
jenkins_script_console script_disable_usage_stats
jenkins_script_console script_upgrade_plugins
jenkins_script_console script_install_plugins "credentials-binding,git,github,github-oauth,job-dsl,matrix-auth,matrix-project,ssh-slaves,workflow-aggregator"
if ! ${skip_restart}; then
start_or_restart_jenkins
url_ready "${JENKINS_WEB}/jnlpJars/jenkins-cli.jar"
fi
echo "Jenkins is ready. Visit ${JENKINS_WEB}/"
if is_auth_enabled &> /dev/null; then
echo "User: admin"
echo "Password: $(<${JENKINS_HOME}/secrets/initialAdminPassword)"
fi
;;
download-file)
shift
download_file "$1"
;;
clean)
force-stop
rm -f console.log jenkins.pid
rm -rf "${JENKINS_HOME}"
;;
cli)
shift
jenkins_cli $@
;;
install-plugins)
shift
#try enabling authentication
if is_auth_enabled; then
export CURL="${CURL} -u admin:$(<${JENKINS_HOME}/secrets/initialAdminPassword)"
fi
#try enabling CSRF protection support
csrf_set_curl
jenkins_script_console script_install_plugins "$@"
;;
update-plugins)
update_jenkins_plugins
echo 'Jenkins may need to be restarted.'
;;
purge)
force-stop
rm -f console.log jenkins-cli.jar jenkins.pid jenkins.war
rm -rf "${JENKINS_HOME}"
;;
start|restart)
start_or_restart_jenkins
;;
status)
if jenkins_status; then
echo 'Jenkins is running.'
exit 0
else
echo 'Jenkins is not running.'
exit 1
fi
;;
stop)
stop_jenkins
;;
url-ready)
shift
url_ready "$1"
;;
*)
cat <<- "EOF"
SYNOPSIS
provision_jenkins.sh [command] [additional arguments]
DESCRIPTION
Additional arguments are only available for commands that support it.
Otherwise, additional arguments will be ignored.
Provisions a fresh Jenkins on a local laptop, updates the plugins, and runs
it. Creates a JAVA_HOME. Downloads Jenkins. Updates the Jenkins plugins to
the latest version.
COMMANDS
bootstrap The bootstrap behavior is to provision Jenkins.
This command creates a JAVA_HOME, downloads
Jenkins, and updates the plugins to the latest
version. Additionally, it will install the git,
github, and github-oauth plugins.
cli [args] This command takes additional arguments. All
arguments are passed through to jenkins-cli.jar.
clean WARNING: destructive command. Kills the current
instance of Jenkins, deletes JENKINS_HOME, removes
the jenkins.pid file, and removes the console.log.
Use this when you want start from scratch but don't
want to download the latest Jenkins.
download-file URL Wait for a file to become available and then
download it. This command is useful for
automation.
install-plugins [args] This command takes additional arguments. The
additional arguments are one or more Jenkins plugin
IDs.
purge WARNING: destructive command. Deletes all files
related to the provisioned Jenkins including the
war file and JENKINS_HOME. If Jenkins is running
it will be sent SIGKILL.
start or start and restart do the same thing. If Jenkins is
restart not running then it will start it. If Jenkins is
already running then it will stop Jenkins and start
it again.
stop Will gracefully shutdown Jenkins and leave the
JENKINS_HOME intact.
update-plugins Updates all unpinned plugins in Jenkins to their
latest versions.
url-ready URL Wait for a URL to become available. This command
is useful for automation.
EXAMPLE USAGE
Automatically provision and start Jenkins on your laptop.
mkdir ~/jenkins_testing
cd ~/jenkins_testing
provision_jenkins.sh bootstrap
Kill and completely delete your provisioned Jenkins.
cd ~/jenkins_testing
provision_jenkins.sh purge
Update all plugins to the latest version using jenkins-cli
cd ~/jenkins_testing
provision_jenkins.sh update-plugins
Install additional plugins e.g. the slack plugin.
cd ~/jenkins_testing
provision_jenkins.sh install-plugins slack
Start or restart Jenkins.
cd ~/jenkins_testing
provision_jenkins.sh start
provision_jenkins.sh restart
Stop Jenkins.
provision_jenkins.sh stop
See Jenkins CLI help documentation.
provision_jenkins.sh cli help
Create a Job using Jenkins CLI.
provision_jenkins.sh cli create-job my_job < config.xml
EOF
esac