PageRenderTime 49ms CodeModel.GetById 23ms RepoModel.GetById 1ms app.codeStats 0ms

/managed-scripts/shell/provision_jenkins.sh

http://github.com/jenkinsci/jenkins-scripts
Shell | 502 lines | 404 code | 39 blank | 59 comment | 22 complexity | 2ef9a0cda27917b2e9c2a6d41b80206f MD5 | raw file
  1. #!/bin/bash
  2. #Created by Sam Gleske (https://github.com/samrocketman/home)
  3. #Wed May 20 11:09:18 EDT 2015
  4. #Mac OS X 10.9.5
  5. #Darwin 13.4.0 x86_64
  6. #GNU bash, version 3.2.53(1)-release (x86_64-apple-darwin13)
  7. #curl 7.30.0 (x86_64-apple-darwin13.0) libcurl/7.30.0 SecureTransport zlib/1.2.5
  8. #awk version 20070501
  9. #java version "1.7.0_55"
  10. #Java(TM) SE Runtime Environment (build 1.7.0_55-b13)
  11. #Java HotSpot(TM) 64-Bit Server VM (build 24.55-b03, mixed mode)
  12. #DESCRIPTION
  13. # Provisions a fresh Jenkins on a local laptop, updates the plugins, and runs
  14. # it.
  15. # 1. Creates a JENKINS_HOME.
  16. # 2. Downloads Jenkins.
  17. # 3. Updates the Jenkins plugins to the latest version.
  18. #USAGE
  19. # Automatically provision and start Jenkins on your laptop.
  20. # mkdir ~/jenkins_testing
  21. # cd ~/jenkins_testing
  22. # provision_jenkins.sh bootstrap
  23. # Kill and completely delete your provisioned Jenkins.
  24. # cd ~/jenkins_testing
  25. # provision_jenkins.sh purge
  26. # Update all plugins to the latest version using jenkins-cli
  27. # cd ~/jenkins_testing
  28. # provision_jenkins.sh update-plugins
  29. # Start or restart Jenkins.
  30. # cd ~/jenkins_testing
  31. # provision_jenkins.sh start
  32. # provision_jenkins.sh restart
  33. # Stop Jenkins.
  34. # provision_jenkins.sh stop
  35. #
  36. # USER CUSTOMIZED VARIABLES
  37. #
  38. #Latest Release
  39. jenkins_url="${jenkins_url:-http://mirrors.jenkins-ci.org/war/latest/jenkins.war}"
  40. #LTS Jenkins URL
  41. #jenkins_url="${jenkins_url:-http://mirrors.jenkins-ci.org/war-stable/latest/jenkins.war}"
  42. JENKINS_HOME="${JENKINS_HOME:-my_jenkins_home}"
  43. JENKINS_WEB="${JENKINS_WEB:-http://localhost:8080/}"
  44. JENKINS_CLI="${JENKINS_CLI:-java -jar ./jenkins-cli.jar -s ${JENKINS_WEB} -noKeyAuth}"
  45. JENKINS_START="${JENKINS_START:-java -jar jenkins.war}"
  46. #remove trailing slash
  47. JENKINS_WEB="${JENKINS_WEB%/}"
  48. CURL="${CURL:-curl}"
  49. #Get JAVA_HOME for java on Mac OS X
  50. #will only run if OS X is detected
  51. if uname -rms | grep Darwin &> /dev/null; then
  52. JAVA_HOME="$(/usr/libexec/java_home)"
  53. PATH="${JAVA_HOME}/bin:${PATH}"
  54. echo "JAVA_HOME=${JAVA_HOME}"
  55. java -version
  56. fi
  57. export jenkins_url JENKINS_HOME JAVA_HOME PATH JENKINS_CLI CURL
  58. #
  59. # SCRIPT CONSOLE SCRIPTS
  60. #
  61. function script_skip_wizard() {
  62. cat <<'EOF'
  63. import hudson.util.PluginServletFilter
  64. def j=Jenkins.instance
  65. if('getSetupWizard' in j.metaClass.methods*.name.sort().unique()) {
  66. def w=j.getSetupWizard()
  67. if(w != null) {
  68. try {
  69. w.completeSetup()
  70. }
  71. catch(Exception e) {
  72. //pre Jenkins 2.6
  73. w.completeSetup(j)
  74. PluginServletFilter.removeFilter(w.FORCE_SETUP_WIZARD_FILTER)
  75. }
  76. j.save()
  77. println 'Wizard skipped.'
  78. }
  79. }
  80. EOF
  81. }
  82. function script_disable_usage_stats() {
  83. echo 'Jenkins.instance.setNoUsageStatistics(true)'
  84. }
  85. function script_upgrade_plugins() {
  86. cat <<'EOF'
  87. import hudson.model.UpdateSite
  88. def j = Jenkins.instance
  89. /*
  90. Install Jenkins plugins
  91. */
  92. def install(Collection c, Boolean dynamicLoad, UpdateSite updateSite) {
  93. c.each {
  94. println "Installing ${it} plugin."
  95. UpdateSite.Plugin plugin = updateSite.getPlugin(it)
  96. Throwable error = plugin.deploy(dynamicLoad).get().getError()
  97. if(error != null) {
  98. println "ERROR installing ${it}, ${error}"
  99. }
  100. }
  101. null
  102. }
  103. //upgrade plugins
  104. UpdateSite s = (UpdateSite) j.getUpdateCenter().getSite(UpdateCenter.ID_DEFAULT)
  105. //download latest JSON update data
  106. s.updateDirectlyNow(true)
  107. install(s.getUpdates()*.getInstalled()*.getShortName(), false, s)
  108. EOF
  109. }
  110. function script_install_plugins() {
  111. cat <<EOF
  112. def plugins = "$@".split('[, ]') as ArrayList
  113. /*
  114. Install Jenkins plugins
  115. */
  116. def install(Collection c, Boolean dynamicLoad, UpdateSite updateSite) {
  117. c.each {
  118. println "Installing \${it} plugin."
  119. UpdateSite.Plugin plugin = updateSite.getPlugin(it)
  120. Throwable error = plugin.deploy(dynamicLoad).get().getError()
  121. if(error != null) {
  122. println "ERROR installing \${it}, \${error}"
  123. }
  124. }
  125. null
  126. }
  127. def j = Jenkins.instance
  128. //upgrade plugins
  129. UpdateSite s = (UpdateSite) j.getUpdateCenter().getSite(UpdateCenter.ID_DEFAULT)
  130. //only install plugins if they're missing
  131. install(plugins - j.pluginManager.getPlugins()*.getShortName(), true, s)
  132. EOF
  133. }
  134. #
  135. # FUNCTIONS
  136. #
  137. function jenkins_script_console() {
  138. echo "Calling jenkins_script_console $1"
  139. ${CURL} --data-urlencode "script=$(eval "$@")" ${JENKINS_WEB}/scriptText
  140. }
  141. #CSRF protection support
  142. function is_crumbs_enabled() {
  143. 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"' )"
  144. if [ "${use_crumbs}" = "true" ]; then
  145. return 0
  146. fi
  147. return 1
  148. }
  149. #CSRF protection support
  150. function get_crumb() {
  151. ${CURL} -s ${JENKINS_WEB}/crumbIssuer/api/json | python -c 'import sys,json;j=json.load(sys.stdin);print j["crumbRequestField"] + "=" + j["crumb"]'
  152. }
  153. #CSRF protection support
  154. function csrf_set_curl() {
  155. if is_crumbs_enabled; then
  156. if [ ! "${CSRF_CRUMB}" = "$(get_crumb)" ]; then
  157. if [ -n "${CSRF_CRUMB}" ]; then
  158. #remove existing crumb value from curl command
  159. CURL="$(echo "${CURL}" | sed "s/ -d ${CSRF_CRUMB}//")"
  160. fi
  161. export CSRF_CRUMB="$(get_crumb)"
  162. export CURL="${CURL} -d ${CSRF_CRUMB}"
  163. echo "Using crumbs for CSRF support."
  164. elif ! echo "${CURL}" | grep -F "${CSRF_CRUMB}" &> /dev/null; then
  165. export CURL="${CURL} -d ${CSRF_CRUMB}"
  166. echo "Using crumbs for CSRF support."
  167. fi
  168. fi
  169. }
  170. function is_auth_enabled() {
  171. 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"' )"
  172. #check if authentication is required.;
  173. #if the value of no_authentication is anything but false; then assume authentication
  174. if [ ! "${no_authentication}" = "false" ]; then
  175. echo -n "Authentication required..."
  176. if [ -e "${JENKINS_HOME}/secrets/initialAdminPassword" ]; then
  177. echo "DONE"
  178. return 0
  179. else
  180. echo "FAILED"
  181. echo "Could not set authentication."
  182. echo "Missing file: ${JENKINS_HOME}/secrets/initialAdminPassword"
  183. exit 1
  184. fi
  185. fi
  186. return 1
  187. }
  188. function url_ready() {
  189. url="$1"
  190. echo -n "Waiting for ${url} to become available."
  191. while [ ! "200" = "$(curl -sLiI -w "%{http_code}\\n" -o /dev/null ${url})" ]; do
  192. echo -n '.'
  193. sleep 1
  194. done
  195. echo 'ready.'
  196. }
  197. function download_file() {
  198. #see bash man page and search for Parameter Expansion
  199. if [ "$#" = 1 ]; then
  200. url="$1"
  201. file="${1##*/}"
  202. else
  203. url="$1"
  204. file="$2"
  205. fi
  206. url_ready "${url}"
  207. if [ ! -e "${file}" ]; then
  208. curl -SLo "${file}" "${url}"
  209. fi
  210. }
  211. function jenkins_status() {
  212. #check to see if jenkins is running
  213. #will return exit status 0 if running or 1 if not running
  214. STATUS=1
  215. if [ -e "jenkins.pid" ]; then
  216. ps aux | grep -v 'grep' | grep 'jenkins\.war' | grep "$(cat jenkins.pid)" &> /dev/null
  217. STATUS=$?
  218. fi
  219. return ${STATUS}
  220. }
  221. function start_or_restart_jenkins() {
  222. #start Jenkins, if it's already running then stop it and start it again
  223. if [ -e "jenkins.pid" ]; then
  224. echo -n 'Jenkins might be running so attempting to stop it.'
  225. kill $(cat jenkins.pid)
  226. #wait for jenkins to stop
  227. while jenkins_status; do
  228. echo -n '.'
  229. sleep 1
  230. done
  231. rm jenkins.pid
  232. echo 'stopped.'
  233. fi
  234. echo 'Starting Jenkins.'
  235. ${JENKINS_START} >> console.log 2>&1 &
  236. echo "$!" > jenkins.pid
  237. }
  238. function stop_jenkins() {
  239. if [ -e "jenkins.pid" ]; then
  240. echo -n 'Jenkins might be running so attempting to stop it.'
  241. kill $(cat jenkins.pid)
  242. #wait for jenkins to stop
  243. while ps aux | grep -v 'grep' | grep "$(cat jenkins.pid)" &> /dev/null; do
  244. echo -n '.'
  245. sleep 1
  246. done
  247. rm jenkins.pid
  248. echo 'stopped.'
  249. fi
  250. }
  251. function update_jenkins_plugins() {
  252. #download the jenkins-cli.jar client
  253. download_file "${JENKINS_WEB}/jnlpJars/jenkins-cli.jar"
  254. echo 'Updating Jenkins Plugins using jenkins-cli.'
  255. UPDATE_LIST="$( ${JENKINS_CLI} list-plugins | awk '$0 ~ /\)$/ { print $1 }' )"
  256. if [ ! -z "${UPDATE_LIST}" ]; then
  257. ${JENKINS_CLI} install-plugin ${UPDATE_LIST}
  258. fi
  259. }
  260. function jenkins_cli() {
  261. #download the jenkins-cli.jar client
  262. download_file "${JENKINS_WEB}/jnlpJars/jenkins-cli.jar"
  263. echo "Executing: ${JENKINS_CLI} $@"
  264. ${JENKINS_CLI} $@
  265. }
  266. function force-stop() {
  267. if [ -e 'jenkins.pid' ]; then
  268. kill -9 $(cat jenkins.pid) 2> /dev/null
  269. rm -f jenkins.pid
  270. fi
  271. }
  272. #
  273. # main execution
  274. #
  275. case "$1" in
  276. bootstrap)
  277. shift
  278. skip_restart='false'
  279. while [ "$#" -gt '0' ]; do
  280. case $1 in
  281. --skip-restart)
  282. skip_restart='true'
  283. shift
  284. ;;
  285. *)
  286. echo "Error invalid arument provided to bootstrap command: $1"
  287. exit 1
  288. ;;
  289. esac
  290. done
  291. #provision Jenkins by default
  292. #download jenkins.war
  293. download_file ${jenkins_url} jenkins.war
  294. echo "JENKINS_HOME=${JENKINS_HOME}"
  295. start_or_restart_jenkins
  296. url_ready "${JENKINS_WEB}/jnlpJars/jenkins-cli.jar"
  297. #try enabling authentication
  298. if is_auth_enabled; then
  299. export CURL="${CURL} -u admin:$(<${JENKINS_HOME}/secrets/initialAdminPassword)"
  300. fi
  301. #try enabling CSRF protection support
  302. csrf_set_curl
  303. jenkins_script_console script_skip_wizard
  304. jenkins_script_console script_disable_usage_stats
  305. jenkins_script_console script_upgrade_plugins
  306. jenkins_script_console script_install_plugins "credentials-binding,git,github,github-oauth,job-dsl,matrix-auth,matrix-project,pipeline-stage-view,ssh-slaves,workflow-aggregator"
  307. if ! ${skip_restart}; then
  308. start_or_restart_jenkins
  309. url_ready "${JENKINS_WEB}/jnlpJars/jenkins-cli.jar"
  310. fi
  311. echo "Jenkins is ready. Visit ${JENKINS_WEB}/"
  312. if is_auth_enabled &> /dev/null; then
  313. echo "User: admin"
  314. echo "Password: $(<${JENKINS_HOME}/secrets/initialAdminPassword)"
  315. fi
  316. ;;
  317. download-file)
  318. shift
  319. download_file "$1"
  320. ;;
  321. clean)
  322. force-stop
  323. rm -f console.log jenkins.pid
  324. rm -rf "${JENKINS_HOME}"
  325. ;;
  326. cli)
  327. shift
  328. jenkins_cli $@
  329. ;;
  330. install-plugins)
  331. shift
  332. #try enabling authentication
  333. if is_auth_enabled; then
  334. export CURL="${CURL} -u admin:$(<${JENKINS_HOME}/secrets/initialAdminPassword)"
  335. fi
  336. #try enabling CSRF protection support
  337. csrf_set_curl
  338. jenkins_script_console script_install_plugins "$@"
  339. ;;
  340. update-plugins)
  341. update_jenkins_plugins
  342. echo 'Jenkins may need to be restarted.'
  343. ;;
  344. purge)
  345. force-stop
  346. rm -f console.log jenkins-cli.jar jenkins.pid jenkins.war
  347. rm -rf "${JENKINS_HOME}"
  348. ;;
  349. start|restart)
  350. start_or_restart_jenkins
  351. ;;
  352. status)
  353. if jenkins_status; then
  354. echo 'Jenkins is running.'
  355. exit 0
  356. else
  357. echo 'Jenkins is not running.'
  358. exit 1
  359. fi
  360. ;;
  361. stop)
  362. stop_jenkins
  363. ;;
  364. url-ready)
  365. shift
  366. url_ready "$1"
  367. ;;
  368. *)
  369. cat <<- "EOF"
  370. SYNOPSIS
  371. provision_jenkins.sh [command] [additional arguments]
  372. DESCRIPTION
  373. Additional arguments are only available for commands that support it.
  374. Otherwise, additional arguments will be ignored.
  375. Provisions a fresh Jenkins on a local laptop, updates the plugins, and runs
  376. it. Creates a JAVA_HOME. Downloads Jenkins. Updates the Jenkins plugins to
  377. the latest version.
  378. COMMANDS
  379. bootstrap The bootstrap behavior is to provision Jenkins.
  380. This command creates a JAVA_HOME, downloads
  381. Jenkins, and updates the plugins to the latest
  382. version. Additionally, it will install the git,
  383. github, and github-oauth plugins.
  384. cli [args] This command takes additional arguments. All
  385. arguments are passed through to jenkins-cli.jar.
  386. clean WARNING: destructive command. Kills the current
  387. instance of Jenkins, deletes JENKINS_HOME, removes
  388. the jenkins.pid file, and removes the console.log.
  389. Use this when you want start from scratch but don't
  390. want to download the latest Jenkins.
  391. download-file URL Wait for a file to become available and then
  392. download it. This command is useful for
  393. automation.
  394. install-plugins [args] This command takes additional arguments. The
  395. additional arguments are one or more Jenkins plugin
  396. IDs.
  397. purge WARNING: destructive command. Deletes all files
  398. related to the provisioned Jenkins including the
  399. war file and JENKINS_HOME. If Jenkins is running
  400. it will be sent SIGKILL.
  401. start or start and restart do the same thing. If Jenkins is
  402. restart not running then it will start it. If Jenkins is
  403. already running then it will stop Jenkins and start
  404. it again.
  405. stop Will gracefully shutdown Jenkins and leave the
  406. JENKINS_HOME intact.
  407. update-plugins Updates all unpinned plugins in Jenkins to their
  408. latest versions.
  409. url-ready URL Wait for a URL to become available. This command
  410. is useful for automation.
  411. EXAMPLE USAGE
  412. Automatically provision and start Jenkins on your laptop.
  413. mkdir ~/jenkins_testing
  414. cd ~/jenkins_testing
  415. provision_jenkins.sh bootstrap
  416. Kill and completely delete your provisioned Jenkins.
  417. cd ~/jenkins_testing
  418. provision_jenkins.sh purge
  419. Update all plugins to the latest version using jenkins-cli
  420. cd ~/jenkins_testing
  421. provision_jenkins.sh update-plugins
  422. Install additional plugins e.g. the slack plugin.
  423. cd ~/jenkins_testing
  424. provision_jenkins.sh install-plugins slack
  425. Start or restart Jenkins.
  426. cd ~/jenkins_testing
  427. provision_jenkins.sh start
  428. provision_jenkins.sh restart
  429. Stop Jenkins.
  430. provision_jenkins.sh stop
  431. See Jenkins CLI help documentation.
  432. provision_jenkins.sh cli help
  433. Create a Job using Jenkins CLI.
  434. provision_jenkins.sh cli create-job my_job < config.xml
  435. EOF
  436. esac