-
Notifications
You must be signed in to change notification settings - Fork 33
/
2-jenkins.sh
executable file
·347 lines (300 loc) · 13.2 KB
/
2-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
#!/usr/bin/env bash
source ./auto/helper-logic
# Clear the screen and print the header
PrintHeader
# Ensure we are running as root
EnsureRoot
# Ensure stage 1 is complete
EnsureStageIsComplete 1
# Define variables
INITIAL_PASSWORD_FILE="/var/lib/jenkins/secrets/initialAdminPassword"
NETWORK_INTERFACES=`ls /sys/class/net/ -1 |grep -v -w "lo" |grep -v docker |grep -v dummy |grep -v veth`
#region Run SSH script
cp ./auto/ssh-script.sh /var/lib/jenkins
chown jenkins:jenkins /var/lib/jenkins/ssh-script.sh
# This script create the SSH key, adds it to the trusted keys and trusts the host itself.
echo "Running SSH script as jenkins user..."
runuser -l jenkins -c "./ssh-script.sh"
echo
rm /var/lib/jenkins/ssh-script.sh > /dev/null 2>&1
#endregion
#region Run GnuPG script
cp ./auto/gpg-script.sh /var/lib/jenkins
chown jenkins:jenkins /var/lib/jenkins/gpg-script.sh
# This script generates the GnuPG key pair.
echo "Running GnuPG script as jenkins user..."
runuser -l jenkins -c "./gpg-script.sh"
echo
rm /var/lib/jenkins/gpg-script.sh > /dev/null 2>&1
#endregion
#region Initial Jenkins user setup and ask for credentials
function PrintUrls {
echo
for INTERFACE in $NETWORK_INTERFACES; do
IP_ADDRESS=`ifconfig $INTERFACE | grep 'inet '| cut -d: -f2 | awk '{ print $2}'`
if [[ $IP_ADDRESS != "" ]]; then
echo -e "${GREEN}http://$IP_ADDRESS:8080$1${NOCOLOR}"
fi
done
echo
}
if [ -f $INITIAL_PASSWORD_FILE ]; then
# This is the first run (or the previous run never made it to finish creating an admin user).
INITIAL_PASSWORD=`cat /var/lib/jenkins/secrets/initialAdminPassword`
echo -e "Please open a web browser, and go to one of these URLs:"
PrintUrls
echo -e "Then, login using this password: ${GREEN}$INITIAL_PASSWORD${NOCOLOR}"
echo
read -p "Press enter when you are logged on."
echo
echo -e "Now click the \"${GREEN}Install suggested plugins${NOCOLOR}\" button"
echo
read -p "Press enter when the plugins are done installing."
echo
echo "When prompted, create the first admin user."
echo
read -p "Please enter the username you choose here, and press enter: " USERNAME
echo
echo "Just leave the default url, and continue until you are greeted with the Welcome page."
echo
else
# This is a re-run, so the admin user has already been created.
if ([ ! -f $USERNAME_FILE ] || [ ! -f $TOKEN_FILE ]); then
# There is no USERNAME_FILE or TOKEN_FILE, so we ask the user to provide the username.
echo -e "Please open a web browser, and go to one of these URLs:"
PrintUrls
echo -e "Then, login using the credentials you have created before."
echo
read -p "Please enter your username here: " USERNAME
echo
fi
fi
if ([ ! -f $USERNAME_FILE ] || [ ! -f $TOKEN_FILE ]); then
# There is no USERNAME_FILE or TOKEN_FILE, so we ask the user to provide the token.
echo
echo "If you already have generated a token, and know it, skip this step and just enter it below instead of creating a new one."
echo -e "Once you reach the Welcome page, please go to one of these URLs:"
PrintUrls "/user/$USERNAME/security"
echo -e "Here you click the \"${GREEN}Add new Token${NOCOLOR}\" button, followed by the \"${GREEN}Generate${NOCOLOR}\" button (leave the text field empty)."
echo
read -p "Please enter the generated token here, and press enter: " TOKEN
echo
fi
if ([ -f $USERNAME_FILE ] && [ -f $TOKEN_FILE ]); then
# If we get here, the files already exists (so the user wouldn't have been asked above)
# So we read them instead.
USERNAME=`cat $USERNAME_FILE`
TOKEN=`cat $TOKEN_FILE`
fi
#endregion
# Ensure the Jenkins CLI has been downloaded.
EnsureJenkinsCli
# Test the connection to make sure Jenkins is ready.
TestJenkinsConnection $USERNAME $TOKEN
#region Install needed plugins
# If we make it here, we know the username and token is valid, and Jenkins is running.
echo "Installing plugins..."
echo
declare -A plugins
plugins["docker-plugin"]="Docker"
plugins["docker-workflow"]="Docker Pipeline"
plugins["copyartifact"]="Copy Artifact"
plugins["ssh-agent"]="SSH Agent"
plugins["pipeline-utility-steps"]="Pipeline Utility Steps"
plugins["job-dsl"]="Job DSL"
for key in "${!plugins[@]}"
do
if (java -jar jenkins-cli.jar -s http://172.17.17.17:8080 -auth $USERNAME:$TOKEN list-plugins $key > /dev/null 2>&1); then
PrintOkIndicator "$key is already installed."
else
function InstallPlugin {
java -jar jenkins-cli.jar -s http://172.17.17.17:8080 -auth $USERNAME:$TOKEN install-plugin $1 -deploy
}
Run "InstallPlugin $key" \
"Installing $key plugin..." \
"Failed to install $key plugin." \
"Installed $key plugin."
fi
done
echo
#endregion
#region Configure number of executors
# Find the number of CPU cores available to the machine.
NUMBER_OF_CPU_CORES="$(nproc)"
# If the number is less than 4, we bump it up to 4.
NUMBER_OF_CPU_CORES=$(( $NUMBER_OF_CPU_CORES < 4 ? 4 : $NUMBER_OF_CPU_CORES))
# Does the number of exectutors match the number of CPU cores?
if [ "$(xmlstarlet sel -t -v '//numExecutors' -n /var/lib/jenkins/config.xml 2>/dev/null)" -eq $NUMBER_OF_CPU_CORES ]; then
# Yep.
PrintOkIndicator "Executors already set to ${NUMBER_OF_CPU_CORES}."
else
# Nope, so we stop Jenkins
StopJenkins
function ChangeExecutorCount {
# We need to send 2 to /dev/null, since xmlstarlet prints warnings about xml version to stderr.
xmlstarlet ed -L -u "/hudson/numExecutors" -v "$1" $JENKINS_CONFIG_FILE 2>/dev/null
}
# Then we update the config to match the number of CPU cores.
Run "ChangeExecutorCount ${NUMBER_OF_CPU_CORES}" \
"Changing executor count to ${NUMBER_OF_CPU_CORES}..." \
"Failed to change executor count to ${NUMBER_OF_CPU_CORES}." \
"Changed executor count to ${NUMBER_OF_CPU_CORES}."
fi
#endregion
#region Configure labels
# Has the labels been configured?
if grep -q ec2_amd64 $JENKINS_CONFIG_FILE; then
# Yep.
PrintOkIndicator "Labels are already configured."
else
# Nope, so we stop Jenkins
StopJenkins
function ConfigureLabels {
# We need to send 2 to /dev/null, since xmlstarlet prints warnings about xml version to stderr.
xmlstarlet ed -L -u "/hudson/label" -v "Docker docker ec2_amd64" $JENKINS_CONFIG_FILE 2>/dev/null
}
# Then we update the config to include the labels.
Run "ConfigureLabels" \
"Configuring labels..." \
"Failed to configure labels." \
"Configured labels."
fi
#endregion
#region Configure environment variables
# Does the config contain the environment variables?
if grep -q ARM64_BUILD_DISABLED $JENKINS_CONFIG_FILE; then
# Yep
PrintOkIndicator "Environment variables are already configured."
else
# Nope, so we stop Jenkins
StopJenkins
function ConfigureEnvironmentVariables {
# We need to send 2 to /dev/null, since xmlstarlet prints warnings about xml version to stderr.
xmlstarlet ed -L -s "/hudson/globalNodeProperties" -t elem -n "hudson.slaves.EnvironmentVariablesNodeProperty" -v "" \
-s "//hudson.slaves.EnvironmentVariablesNodeProperty" -t elem -n "envVars" -v "" \
-s "//envVars" -t attr -n "serialization" -v "custom" \
-s "//envVars" -t elem -n "unserializable-parents" -v "" \
-s "//envVars" -t elem -n "tree-map" -v "" \
-s "//tree-map" -t elem -n "default" -v "" \
-s "//default" -t elem -n "comparator" -v "" \
-i "//comparator" -t attr -n "class" -v "java.lang.String\$CaseInsensitiveComparator" \
-s "//tree-map" -t elem -n "int" -v "5" \
-s "//tree-map" -t elem -n "string" -v "ARM64_BUILD_DISABLED" \
-s "//tree-map" -t elem -n "string" -v "true" \
-s "//tree-map" -t elem -n "string" -v "CUSTOM_BUILD_CHECK_DISABLED" \
-s "//tree-map" -t elem -n "string" -v "true" \
-s "//tree-map" -t elem -n "string" -v "CUSTOM_DOCKER_REPO" \
-s "//tree-map" -t elem -n "string" -v "172.17.17.17:5000" \
-s "//tree-map" -t elem -n "string" -v "DEV_PACKAGES_VYOS_NET_HOST" \
-s "//tree-map" -t elem -n "string" -v "jenkins@172.17.17.17" \
-s "//tree-map" -t elem -n "string" -v "NOT_VYOS" \
-s "//tree-map" -t elem -n "string" -v "$NOT_VYOS" \
$JENKINS_CONFIG_FILE 2>/dev/null
}
# Then we update the config to include the environment variables.
Run "ConfigureEnvironmentVariables" \
"Configuring environment variables..." \
"Failed to configure environment variables." \
"Configured environment variables."
fi
#endregion
#region Configure Global Libraries
# Sometimes the GlobalLibraries config file isn't there yet.
if [ ! -f $JENKINS_GLOBALLIBRARIES_FILE ]; then
# If that is the case, we copy a clean config into where it should be.
cp ./auto/org.jenkinsci.plugins.workflow.libs.GlobalLibraries.xml $JENKINS_GLOBALLIBRARIES_FILE
fi
# Is the Global Libraries configured?
if grep -q "vyos-build" $JENKINS_GLOBALLIBRARIES_FILE; then
# Yep.
PrintOkIndicator "Global libraries are already configured."
else
# Nope, so we stop Jenkins
StopJenkins
function ConfigureGlobalLibraries {
# We need to send 2 to /dev/null, since xmlstarlet prints warnings about xml version to stderr.
xmlstarlet ed -L \
-d "/org.jenkinsci.plugins.workflow.libs.GlobalLibraries/libraries/@class" \
-s "/org.jenkinsci.plugins.workflow.libs.GlobalLibraries/libraries" -t elem -n "org.jenkinsci.plugins.workflow.libs.LibraryConfiguration" -v "" \
-s "//org.jenkinsci.plugins.workflow.libs.LibraryConfiguration" -t elem -n "name" -v "vyos-build" \
-s "//org.jenkinsci.plugins.workflow.libs.LibraryConfiguration" -t elem -n "retriever" \
-i "//retriever" -t attr -n "class" -v "org.jenkinsci.plugins.workflow.libs.SCMSourceRetriever" \
-s "//retriever" -t elem -n "clone" -v "false" \
-s "//retriever" -t elem -n "scm" \
-i "//scm" -t attr -n "class" -v "jenkins.plugins.git.GitSCMSource" \
-i "//scm" -t attr -n "plugin" -v "git@5.2.2" \
-s "//scm" -t elem -n "id" -v "9d202e32-1889-4391-91e5-1b3445f035fd" \
-s "//scm" -t elem -n "remote" -v "https://github.com/notvyos/vyos-build.git" \
-s "//scm" -t elem -n "credentialsId" \
-s "//scm" -t elem -n "traits" \
-s "//traits" -t elem -n "jenkins.plugins.git.traits.BranchDiscoveryTrait" \
-s "//org.jenkinsci.plugins.workflow.libs.LibraryConfiguration" -t elem -n "implicit" -v "false" \
-s "//org.jenkinsci.plugins.workflow.libs.LibraryConfiguration" -t elem -n "allowVersionOverride" -v "true" \
-s "//org.jenkinsci.plugins.workflow.libs.LibraryConfiguration" -t elem -n "includeInChangesets" -v "true" \
$JENKINS_GLOBALLIBRARIES_FILE 2>/dev/null
}
# Then we update the config to global libraries configuration.
Run "ConfigureGlobalLibraries" \
"Configuring global libraries..." \
"Failed to configure global libraries." \
"Configured global libraries."
fi
#endregion
#region Configure Docker Declarative Pipeline
# Sometimes the Docker Declarative config file isn't there yet.
if [ ! -f $JENKINS_DOCKERDECLARATIVE_FILE ]; then
# If that is the case, we copy a clean config into where it should be.
cp ./auto/org.jenkinsci.plugins.docker.workflow.declarative.GlobalConfig.xml $JENKINS_DOCKERDECLARATIVE_FILE
fi
# Is the Docker Declarative plugin configured?
if grep -q "172.17.17.17" $JENKINS_DOCKERDECLARATIVE_FILE; then
# Yep.
PrintOkIndicator "Docker Declarativ Pipeline is already configured."
else
# Nope, so we stop Jenkins
StopJenkins
function ConfigureDockerDeclarativePipeline {
# We need to send 2 to /dev/null, since xmlstarlet prints warnings about xml version to stderr.
xmlstarlet ed -L \
-s "/org.jenkinsci.plugins.docker.workflow.declarative.GlobalConfig/registry" -t elem -n "url" -v "http://172.17.17.17:5000" \
$JENKINS_DOCKERDECLARATIVE_FILE 2>/dev/null
}
# Then we update the config to global libraries configuration.
Run "ConfigureDockerDeclarativePipeline" \
"Configuring Docker Declarativ Pipeline..." \
"Failed to configure Docker Declarativ Pipeline." \
"Configured Docker Declarativ Pipeline."
fi
#endregion
# Restart Jenkins if it was stopped.
StartJenkins
#region Add SSH credentials
if (java -jar jenkins-cli.jar -s http://172.17.17.17:8080 -auth $USERNAME:$TOKEN get-credentials-as-xml system::system::jenkins _ SSH-dev.packages.vyos.net > /dev/null 2>&1); then
PrintOkIndicator "SSH key credential has already been created."
else
function CreateSshKeyCredential {
java -jar jenkins-cli.jar -s http://172.17.17.17:8080 -auth $USERNAME:$TOKEN create-credentials-by-xml system::system::jenkins _ << EOF
<com.cloudbees.jenkins.plugins.sshcredentials.impl.BasicSSHUserPrivateKey plugin="ssh-credentials@337.v395d2403ccd4">
<scope>GLOBAL</scope>
<id>SSH-dev.packages.vyos.net</id>
<description></description>
<username>jenkins</username>
<usernameSecret>false</usernameSecret>
<privateKeySource class="com.cloudbees.jenkins.plugins.sshcredentials.impl.BasicSSHUserPrivateKey\$DirectEntryPrivateKeySource">
<privateKey>`cat /var/lib/jenkins/.ssh/id_ed25519`</privateKey>
</privateKeySource>
</com.cloudbees.jenkins.plugins.sshcredentials.impl.BasicSSHUserPrivateKey>
EOF
}
# We have to create the credential, since it is missing.
Run "CreateSshKeyCredential" \
"Creating SSH key credential..." \
"Failed to create SSH key credential." \
"SSH key credential has been created."
fi
#endregion
echo
echo "Part 2 of the installer is now done."
echo "Please run part three (3-repositories.sh) to set up the reprepro repositories."
# Create marker file
CreateMarkerFile 2