Skip to content

Commit 9ee955f

Browse files
committed
Bootstrap jenkins from scratch -- the oy vey! edition
This functionality had bitrotted because we've never really re-installed jenkins from scratch With this PR, I'm able to bootstrap and fully configure Jenkins ver. 1.611 on a ubuntu utopic vagrant box. The provision has three phases: init, config, jenkins. The config phase is needed when bootstrapping on EC2, where chef vault is not yet available. After the instance is up and authorized with chef-server for vault access, we can go to the config phase. Once Jenkins has the github oauth plugin and is restarted, we can run the master-jenkins recipe. NOTES: - switch to chef_vault_item for development in vagrant - Pass `hudson.model.User.allowNonExistentUserToLogin` to JVM to open jenkins up a bit for provisioning - Also need `org.eclipse.jetty.server.Request.maxFormContentSize=1000000` to allow plugin installs (??)
1 parent 16a51ef commit 9ee955f

20 files changed

+189
-117
lines changed

.chef/Vagrantfile

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,16 @@
66
# centos: vagrant box add chef/centos-7.0
77
Vagrant.configure("2") do |config|
88
config.vm.box = "utopic-daily"
9-
config.vm.provision :chef_solo do |chef|
10-
chef.cookbooks_path = ["~/git/cookbooks"]
9+
config.vm.provision :chef_zero do |chef|
10+
chef.cookbooks_path = "~/git/cookbooks"
11+
# after a long struggle tring to get chef-zero/solo to work with chef-vault, dumped the databags in plain text from admin account using:
12+
# for item in $(knife data bag show master); do knife vault show --format json master $item > .chef/data_bags/master/$item.json; done
13+
chef.data_bags_path = "data_bags"
1114
chef.node_name = "jenkins-master"
15+
# TODO: chef.encrypted_data_bag_secret_key_path
1216
chef.add_recipe("scala-jenkins-infra::master-init")
13-
chef.add_recipe("scala-jenkins-infra::_master-config-proxy")
17+
chef.add_recipe("scala-jenkins-infra::master-config")
18+
chef.add_recipe("scala-jenkins-infra::master-jenkins") # do not run on first provision -- must run up to master-config and allow jenkins to restart
1419
end
1520
config.vm.network "public_network"
1621
config.vm.provider "virtualbox" do |v|

README.md

Lines changed: 55 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -178,42 +178,64 @@ hub clone scala/scala-jenkins-infra
178178
cd scala-jenkins-infra
179179
ln -sh ~/git/cookbooks $PWD/.chef/
180180
181-
knife site install cron
182-
knife site install logrotate
183-
knife site install chef_handler
184-
knife site install windows
185-
knife site install chef-client
186-
knife site install aws
187-
knife site install delayed_evaluator
188-
knife site install ebs
189-
knife site install java
190-
knife site install apt
191-
knife site install packagecloud
192-
knife site install runit
193-
knife site install yum
194-
knife site install jenkins
195-
knife site install 7-zip
196-
knife site install ark
197-
knife site install artifactory
198-
knife site install build-essential
199-
knife site install dmg
200-
knife site install yum-epel
201-
knife site install git
202-
knife site install user
203-
knife site install partial_search
204-
knife site install ssh_known_hosts
205-
knife site install git_user
206-
knife site install chef-sbt
207-
knife site install sbt-extras
208-
```
181+
knife cookbook site install cron
182+
knife cookbook site install logrotate
183+
knife cookbook site install chef_handler
184+
knife cookbook site install windows
185+
knife cookbook site install chef-client
186+
knife cookbook site install aws
187+
knife cookbook site install delayed_evaluator
188+
knife cookbook site install ebs
189+
knife cookbook site install apt
190+
knife cookbook site install packagecloud
191+
knife cookbook site install runit
192+
knife cookbook site install yum
193+
knife cookbook site install 7-zip
194+
knife cookbook site install ark
195+
knife cookbook site install artifactory
196+
knife cookbook site install build-essential
197+
knife cookbook site install dmg
198+
knife cookbook site install yum-epel
199+
knife cookbook site install git
200+
knife cookbook site install user
201+
knife cookbook site install partial_search
202+
knife cookbook site install ssh_known_hosts
203+
knife cookbook site install git_user
204+
205+
knife cookbook site install chef-vault
206+
```
207+
208+
### Current cookbooks
209+
- 7-zip == 1.0.2
210+
- apt == 2.7.0
211+
- ark == 0.9.0
212+
- artifactory == 0.1.1
213+
- aws == 2.7.0
214+
- build-essential == 2.2.3
215+
- chef-client == 4.3.0
216+
- chef_handler == 1.1.6
217+
- cron == 1.6.1
218+
- delayed_evaluator == 0.2.0
219+
- dmg == 2.2.2
220+
- ebs == 0.3.6
221+
- git == 4.2.2
222+
- git_user == 0.3.1
223+
- logrotate == 1.9.1
224+
- packagecloud == 0.0.17
225+
- partial_search == 1.0.8
226+
- runit == 1.6.0
227+
- sbt == 0.1.0
228+
- sbt-extras == 0.4.0
229+
- ssh_known_hosts == 2.0.0
230+
- user == 0.4.2
231+
- windows == 1.36.6
232+
- yum == 3.6.0
233+
- yum-epel == 0.6.0
209234

210235
### Switch to unreleased versions from github
211236
```
212-
//fixed: knife cookbook github install opscode-cookbooks/windows # fix nosuchmethoderror (#150)
213-
//knife cookbook github install adriaanm/jenkins/fix305 # ssl fail on windows -- fix pending: https://github.com/opscode-cookbooks/jenkins/pull/313
214-
knife cookbook github install b-dean/jenkins/http_ca_fixes # pending fix for above ^^^
215-
216-
knife cookbook github install adriaanm/java/windows-jdk1.6 # jdk 1.6 installer barfs on re-install -- wipe its INSTALLDIR
237+
knife cookbook github install adriaanm/jenkins/fix305 # custom fixes + https://github.com/opscode-cookbooks/jenkins/pull/313 (b-dean/jenkins/http_ca_fixes)
238+
knife cookbook github install adriaanm/java/windows-jdk1.6 # jdk 1.6 installer barfs on re-install -- wipe its INSTALLDIR
217239
knife cookbook github install adriaanm/chef-sbt
218240
knife cookbook github install gildegoma/chef-sbt-extras
219241
knife cookbook github install adriaanm/artifactory

attributes/master.rb

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,27 @@
1818
override['jenkins']['master']['listen_address'] = '127.0.0.1' # external traffic must go through nginx
1919
override['jenkins']['master']['user'] = 'jenkins'
2020
override['jenkins']['master']['group'] = 'jenkins'
21-
override['jenkins']['master']['jvm_options'] = '-server -Xmx4G -XX:MaxPermSize=512M -XX:+HeapDumpOnOutOfMemoryError' # -Dfile.encoding=UTF-8
21+
22+
# NOTES on override['jenkins']['master']['jvm_options']:
23+
# - org.eclipse.jetty.server.Request.maxFormContentSize is to fix:
24+
# WARNING: Caught exception evaluating: request.getParameter('q') in /updateCenter/byId/default/postBack. Reason: java.lang.IllegalStateException: Form too large 870330>500000
25+
26+
# - hudson.model.User.allowNonExistentUserToLogin resolves issue with installing plugins
27+
# on bootstrapping jenkins (https://github.com/jenkinsci/jenkins/commit/80e9f3f50c3425c9b9b2bfdb58b03a1f1bd10aa3)
28+
# more of the stacktrace:
29+
# java.io.EOFException
30+
# at java.io.DataInputStream.readBoolean(DataInputStream.java:244)
31+
# before that: # ================================================================================
32+
# Error executing action `install` on resource 'jenkins_plugin[notification]'
33+
# ================================================================================
34+
#
35+
# Mixlib::ShellOut::ShellCommandFailed
36+
# ------------------------------------
37+
# Expected process to exit with [0], but received '255'
38+
# ---- Begin output of "/usr/lib/jvm/java-7-openjdk-amd64/bin/java" -jar "/var/chef/cache/jenkins-cli.jar" -s http://localhost:8080 -i "/var/chef/cache/jenkins-key" install-plugin /var/chef/cache/notification-latest.plugin -name notification ----
39+
40+
override['jenkins']['master']['jvm_options'] = '-server -Xmx4G -XX:MaxPermSize=512M -XX:+HeapDumpOnOutOfMemoryError -Dhudson.model.User.allowNonExistentUserToLogin=true -Dorg.eclipse.jetty.server.Request.maxFormContentSize=1000000' #
41+
# -Dfile.encoding=UTF-8
2242

2343
# To pin the jenkins version, must also override override['jenkins']['master']['source'] !!!
2444
# override['jenkins']['master']['version'] = '1.555'
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
<?xml version='1.0' encoding='UTF-8'?>
2+
<jenkins.model.DownloadSettings>
3+
<useBrowser>true</useBrowser>
4+
</jenkins.model.DownloadSettings>

metadata.rb

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,9 @@
66
long_description IO.read(File.join(File.dirname(__FILE__), 'README.md'))
77
version '0.1.0'
88

9+
# for chef_vault_item, which allows loading from plain databags when developing with vagrant
10+
depends 'chef-vault'
11+
912
depends 'chef-client'
1013
depends 'cron'
1114

recipes/_master-config-jenkins.rb

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
#
2+
# Cookbook Name:: scala-jenkins-infra
3+
# Recipe:: _master-config-jenkins
4+
#
5+
# Copyright 2014, Typesafe, Inc.
6+
#
7+
# All rights reserved - Do Not Redistribute
8+
#
9+
10+
# Config base Jenkins setup and restart
11+
ruby_block 'set private key' do
12+
block do
13+
node.run_state[:jenkins_private_key] = chef_vault_item("master", "scala-jenkins-keypair")['private_key']
14+
end
15+
end
16+
17+
## set up chef user with public key from our master/scala-jenkins-keypair vault
18+
template "#{node['jenkins']['master']['home']}/users/chef/config.xml" do
19+
source 'chef-user-config.erb'
20+
user node['jenkins']['master']['user']
21+
group node['jenkins']['master']['group']
22+
23+
variables({
24+
:pubkey => chef_vault_item("master", "scala-jenkins-keypair")['public_key']
25+
})
26+
end
27+
28+
%w(notification ssh-credentials groovy cygpath job-dsl build-flow-plugin rebuild greenballs build-timeout copyartifact email-ext slack throttle-concurrents dashboard-view parameterized-trigger).each do |plugin|
29+
plugin, version = plugin.split('=') # in case we decide to pin versions later
30+
jenkins_plugin plugin
31+
end
32+
33+
jenkins_plugin "ec2-start-stop" do
34+
source node['master']['ec2-start-stop']['url']
35+
# doesn't support checksum
36+
end
37+
38+
jenkins_plugin "github-oauth" do
39+
notifies :restart, 'runit_service[jenkins]', :immediately
40+
end

recipes/_master-config-proxy.rb

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,10 +35,11 @@
3535
path "/etc/nginx/ssl/dhparam.pem"
3636
end
3737

38+
3839
file "/etc/nginx/ssl/scala-ci.key" do
3940
owner 'root'
4041
mode '600'
41-
content ChefVault::Item.load("master", "scala-ci-key")['private_key']
42+
content chef_vault_item("master", "scala-ci-key")['private_key']
4243
sensitive true
4344
end
4445

recipes/_master-config-scabot.rb

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
#
99

1010
include_recipe "git"
11-
include_recipe "chef-sbt"
11+
include_recipe "sbt-extras"
1212

1313
scabotHome = "/home/scabot"
1414
scabotCheckout = "/home/scabot/scabot"
@@ -38,14 +38,15 @@
3838
owner scabotUser
3939
end
4040

41+
4142
file "#{scabotHome}/.ssh/authorized_keys" do
4243
owner scabotUser
4344
mode '644'
44-
content ChefVault::Item.load("master", "scabot-keypair")['public_key']
45+
content chef_vault_item("master", "scabot-keypair")['public_key']
4546
end
4647

47-
node.set['scabot']['github']['token'] = ChefVault::Item.load("master", "scabot")['github']['token']
48-
node.set['scabot']['jenkins']['token'] = ChefVault::Item.load("master", "scabot")['jenkins']['token']
48+
node.set['scabot']['github']['token'] = chef_vault_item("master", "scabot")['github']['token']
49+
node.set['scabot']['jenkins']['token'] = chef_vault_item("master", "scabot")['jenkins']['token']
4950

5051
git_user scabotUser do
5152
home scabotHome

recipes/_master-init-jenkins.rb

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,4 +33,13 @@
3333
source 'jenkins.model.JenkinsLocationConfiguration.xml.erb'
3434
user node['jenkins']['master']['user']
3535
group node['jenkins']['master']['group']
36-
end
36+
end
37+
38+
# this is to allow plugin installation using jenkins-cli (needs to use REST to download update center json)
39+
cookbook_file "jenkins.model.DownloadSettings.xml" do
40+
path "#{node['jenkins']['master']['home']}/jenkins.model.DownloadSettings.xml"
41+
user node['jenkins']['master']['user']
42+
group node['jenkins']['master']['group']
43+
end
44+
45+

recipes/_master-config-auth-github.rb renamed to recipes/_master-jenkins-auth-github.rb

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,7 @@
77
# All rights reserved - Do Not Redistribute
88
#
99

10-
require "chef-vault"
11-
12-
apiVault = ChefVault::Item.load("master", "github-api")
10+
apiVault = chef_vault_item("master", "github-api")
1311

1412
# This adds Github oAuth security. (login with your github id.)
1513
jenkins_script 'add_gh_authentication' do

recipes/_master-config-jobs.rb renamed to recipes/_master-jenkins-jobs.rb

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,10 @@
77
# All rights reserved - Do Not Redistribute
88
#
99

10-
require "chef-vault"
1110

1211
ruby_block 'set private key' do
1312
block do
14-
node.run_state[:jenkins_private_key] = ChefVault::Item.load("master", "scala-jenkins-keypair")['private_key']
13+
node.run_state[:jenkins_private_key] = chef_vault_item("master", "scala-jenkins-keypair")['private_key']
1514
end
1615
end
1716

recipes/_master-config-workers.rb renamed to recipes/_master-jenkins-workers.rb

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,19 +7,18 @@
77
# All rights reserved - Do Not Redistribute
88
#
99

10-
require "chef-vault"
1110

1211
ruby_block 'set private key' do
1312
block do
14-
node.run_state[:jenkins_private_key] = ChefVault::Item.load("master", "scala-jenkins-keypair")['private_key']
13+
node.run_state[:jenkins_private_key] = chef_vault_item("master", "scala-jenkins-keypair")['private_key']
1514
end
1615
end
1716

1817
credentialsMap = {
1918
'jenkins' => '954dd564-ce8c-43d1-bcc5-97abffc81c57'
2019
}
2120

22-
privKey = ChefVault::Item.load("master", "scala-jenkins-keypair")['private_key']
21+
privKey = chef_vault_item("master", "scala-jenkins-keypair")['private_key']
2322

2423
# TODO: different keypairs to sandbox different workers better, just in case?
2524
credentialsMap.each do |userName, uniqId|

recipes/_worker-config-debian.rb

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -31,14 +31,14 @@
3131
owner jenkinsUser
3232
mode '600'
3333
sensitive true
34-
content ChefVault::Item.load("worker-publish", "chara-keypair")['private_key']
34+
content chef_vault_item("worker-publish", "chara-keypair")['private_key']
3535
end
3636

3737
execute 'accept chara host key' do
3838
command "ssh -oStrictHostKeyChecking=no [email protected] -i \"#{jenkinsHome}/.ssh/for_chara\" true"
3939
user jenkinsUser
4040
#
41-
# not_if "grep -qs \"#{ChefVault::Item.load("worker-publish", "chara-keypair")['public_key']}\" #{jenkinsHome}/.ssh/known_hosts"
41+
# not_if "grep -qs \"#{chef_vault_item("worker-publish", "chara-keypair")['public_key']}\" #{jenkinsHome}/.ssh/known_hosts"
4242
end
4343

4444
directory "#{jenkinsHome}/.gnupg" do
@@ -50,7 +50,7 @@
5050
owner jenkinsUser
5151
mode '600'
5252
sensitive true
53-
content Base64.decode64(ChefVault::Item.load("worker-publish", "gnupg")["#{kind}ring-base64"])
53+
content Base64.decode64(chef_vault_item("worker-publish", "gnupg")["#{kind}ring-base64"])
5454
end
5555
end
5656

@@ -70,12 +70,12 @@
7070
sensitive true
7171

7272
variables({
73-
:sonatypePass => ChefVault::Item.load("worker-publish", "sonatype")['pass'],
74-
:sonatypeUser => ChefVault::Item.load("worker-publish", "sonatype")['user'],
75-
:privateRepoPass => ChefVault::Item.load("worker-publish", "private-repo")['pass'],
76-
:privateRepoUser => ChefVault::Item.load("worker-publish", "private-repo")['user'],
77-
:s3DownloadsPass => ChefVault::Item.load("worker-publish", "s3-downloads")['pass'],
78-
:s3DownloadsUser => ChefVault::Item.load("worker-publish", "s3-downloads")['user']
73+
:sonatypePass => chef_vault_item("worker-publish", "sonatype")['pass'],
74+
:sonatypeUser => chef_vault_item("worker-publish", "sonatype")['user'],
75+
:privateRepoPass => chef_vault_item("worker-publish", "private-repo")['pass'],
76+
:privateRepoUser => chef_vault_item("worker-publish", "private-repo")['user'],
77+
:s3DownloadsPass => chef_vault_item("worker-publish", "s3-downloads")['pass'],
78+
:s3DownloadsUser => chef_vault_item("worker-publish", "s3-downloads")['user']
7979
})
8080
end
8181
end

recipes/_worker-config-rhel.rb

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
# All rights reserved - Do Not Redistribute
88
#
99

10+
1011
node["jenkinsHomes"].each do |jenkinsHome, workerConfig|
1112
jenkinsUser=workerConfig["jenkinsUser"]
1213

@@ -24,8 +25,8 @@
2425
sensitive true
2526

2627
variables({
27-
:privateRepoPass => ChefVault::Item.load("worker", "private-repo-public-jobs")['pass'],
28-
:privateRepoUser => ChefVault::Item.load("worker", "private-repo-public-jobs")['user']
28+
:privateRepoPass => chef_vault_item("worker", "private-repo-public-jobs")['pass'],
29+
:privateRepoUser => chef_vault_item("worker", "private-repo-public-jobs")['user']
2930
})
3031
end
3132
end

recipes/_worker-config-windows.rb

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@
77
# All rights reserved - Do Not Redistribute
88
#
99

10-
require "chef-vault"
1110

1211
node["jenkinsHomes"].each do |jenkinsHome, workerConfig|
1312
if workerConfig["publish"]
@@ -21,8 +20,8 @@
2120
user workerConfig["jenkinsUser"]
2221

2322
variables({
24-
:s3DownloadsPass => ChefVault::Item.load("worker-publish", "s3-downloads")['pass'],
25-
:s3DownloadsUser => ChefVault::Item.load("worker-publish", "s3-downloads")['user']
23+
:s3DownloadsPass => chef_vault_item("worker-publish", "s3-downloads")['pass'],
24+
:s3DownloadsUser => chef_vault_item("worker-publish", "s3-downloads")['user']
2625
})
2726
end
2827
end

0 commit comments

Comments
 (0)