-
Notifications
You must be signed in to change notification settings - Fork 0
/
Jenkinsfile
344 lines (268 loc) · 14.2 KB
/
Jenkinsfile
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
//Requires the following plugins
//Email Extension Plugin
//SSH Pipeline Steps
//user build vars plugin
//Requires the following values under http://jenkinsHostname/scriptApproval - "Signatures already approved:"
//method groovy.lang.Binding getVariables
//method hudson.FilePath delete
//method hudson.FilePath read
//staticMethod org.codehaus.groovy.runtime.DefaultGroovyMethods getBytes java.io.InputStream
//staticMethod org.codehaus.groovy.runtime.EncodingGroovyMethods encodeBase64 byte[]
//Requires a single credentials entry with the following specifications
//ID = Remote Server Hostname
//Username = Remote Server SSH Username
//Password = Remote Server SSH Password
//Scope = Global, could probably be something else but haven't tested it otherwise
//Requires the Jenkins Build to have "This Project Is Parameterized" checked with a "Credentials Parameter" and the following values
//Name = Destination Server
//Credential Type = Username with password
//Required = Checked
//Default Value = One of the Remote Server Credentials - Sorta Optional
def global_remote = [:]
global_unallocatedPort = null
def global_archiveToDecompile = "archiveToDecompile.zip"
def global_archiveToDecompile_testArchive = "testArchive.jar"
def global_recursiveDecompileScript = "recursiveDecompile.sh"
def global_recursiveDecompileJar = "jd-cli.jar"
def global_dockerImage_repo = "codercom/code-server"
def global_dockerImage_tag = "2.preview.5-vsc1.37.0"
def global_dockerImage = "$global_dockerImage_repo:$global_dockerImage_tag"
def global_dockerContainer_id = null
def global_dockerImage_file = "codercom_code-server_2.preview.5-vsc1.37.0.tar.gz"
def global_remoteTempDirectory = "/opt"
def global_testMode = false
global_inputFile = null
pipeline {
agent any
stages {
stage('Upload File') {
steps {
script{
if(global_testMode == false)
{
email_notifyUploadRequirement()
global_inputFile = input message: 'Upload file', parameters: [file(name: global_archiveToDecompile)]
writeFile(file: global_archiveToDecompile, encoding: 'Base64', text: global_inputFile.read().getBytes().encodeBase64().toString())
global_inputFile.delete()
}
}
}
}
stage('Setup Credentials') {
steps {
//notifyStarted()
script {
withCredentials([usernamePassword(credentialsId: params['Destination Server'], passwordVariable: 'pass', usernameVariable: 'user')]) {
global_remote.name = params['Destination Server']
global_remote.host = params['Destination Server']
global_remote.user = "$user"
global_remote.password = "$pass"
global_remote.allowAnyHosts = true
}
}
}
}
stage('Perform') {
steps {
script {
try {
//Run the getFreePort.sh Script and retrieve an unallocated TCP Port to host the docker container on
global_unallocatedPort = sshScript remote: global_remote, script: "getFreePort.sh"
//Run the Docker Images command remotely to see if the image dependency for VS Code exists
currentImages = sshCommand remote: global_remote, command: "docker images"
//Check if the image dependency is in the output, if not then copy the archive to the server
//and load it into the docker daemon, then delete it after
if(!currentImages.contains(global_dockerImage_repo) && !currentImages.contains(global_dockerImage_tag))
{
transferOverSsh(global_dockerImage_file, null, global_remoteTempDirectory, global_remote)
sshCommand remote: global_remote, command: "docker load --input " + '"' + "$global_remoteTempDirectory/$global_dockerImage_file" + '"'
sshCommand remote: global_remote, command: "rm -f " + '"' + "$global_remoteTempDirectory/$global_dockerImage_file" + '"'
}
//Create Docker Container for the Visual Studio Code Workspace
createWorkspaceCommand = "docker run -d --rm -p $global_unallocatedPort:8080 " + '"' + "$global_dockerImage" + '"'
global_dockerContainer_id = sshCommand remote: global_remote, command: createWorkspaceCommand
//For Continuous Integration Testing
if(global_testMode == true)
{
global_archiveToDecompile = global_archiveToDecompile_testArchive
}
destinationDockerFolder = "/home/coder/project/"
//Transfer Archive to Decompile to Docker Container
transferOverSsh_copyToDockerContainer_removeFile(global_archiveToDecompile, global_remoteTempDirectory, global_remote, global_dockerContainer_id, destinationDockerFolder)
//Transfer Recursive Decompile Jar to Docker Container
transferOverSsh_copyToDockerContainer_removeFile(global_recursiveDecompileJar, global_remoteTempDirectory, global_remote, global_dockerContainer_id, destinationDockerFolder)
//Transfer Recursive Decompile Script to Docker Container
transferOverSsh_copyToDockerContainer_removeFile(global_recursiveDecompileScript, global_remoteTempDirectory, global_remote, global_dockerContainer_id, destinationDockerFolder)
//Update Linux Application Repository
command_updateRepository = "apt-get update"
runCommand_onDockerContainer(global_remote, command_updateRepository, global_dockerContainer_id, true)
//Install Java and Unzip Commands
command_installDependencies = "apt-get install -y default-jdk unzip"
runCommand_onDockerContainer(global_remote, command_installDependencies, global_dockerContainer_id, true)
//Run Recursive Decompile
command_recursiveDecompile = destinationDockerFolder + global_recursiveDecompileScript + " " + destinationDockerFolder + global_archiveToDecompile
runCommand_onDockerContainer(global_remote, command_recursiveDecompile, global_dockerContainer_id, false)
email_workspaceUrl(global_remote, global_unallocatedPort)
} catch(exception) {
removeContainerCommand = "docker stop $global_dockerContainer_id"
sshCommand remote: global_remote, command: removeContainerCommand
error exception.toString()
}
}
}
}
stage('Workspace Cleanup') {
steps {
script {
message = "Extension of Workspace Life"
warningMessage = "Termination, deletion, and cleanup of Workspace"
hoursToSleep = 24
hoursToWaitBeforeTimeout = 1
extendWorkspace = timeout(message, warningMessage, hoursToSleep, hoursToWaitBeforeTimeout, "HOURS")
if(extendWorkspace == false)
{
sshCommand remote: global_remote, command: "docker stop " + global_dockerContainer_id
sshCommand remote: global_remote, command: "docker rm " + global_dockerContainer_id
}
}
}
}
}
}
def transferOverSsh(parameter_workspaceFileName, parameter_tempFileName, parameter_tempDirectory, parameter_remoteObject) {
filePath_toReturn = ""
if(parameter_tempFileName != null)
{
filePath_toReturn = "$parameter_tempDirectory/$parameter_tempFileName"
sshPut remote: parameter_remoteObject, from: parameter_workspaceFileName, into: filePath_toReturn
}
else
{
filePath_toReturn = "$parameter_tempDirectory/$parameter_workspaceFileName"
sshPut remote: parameter_remoteObject, from: parameter_workspaceFileName, into: filePath_toReturn
}
return filePath_toReturn
}
def copyToDockerContainer(parameter_remoteFilePath, parameter_destinationDockerFilePath, parameter_remoteObject, parameter_dockerContainerId, parameter_removeRemoteFileAfter) {
command_copyToDockerContainer = "docker cp " + '"' + parameter_remoteFilePath + '"' + " " + '"' + "$parameter_dockerContainerId:$parameter_destinationDockerFilePath" + '"'
sshCommand remote: parameter_remoteObject, command: command_copyToDockerContainer
setDockerFilePermissions(parameter_destinationDockerFilePath, parameter_remoteObject, parameter_dockerContainerId)
if(parameter_removeRemoteFileAfter == true)
{
command_removeFromRemote = "rm -f " + '"' + parameter_remoteFilePath + '"'
sshCommand remote: parameter_remoteObject, command: command_removeFromRemote
}
}
def setDockerFilePermissions(parameter_destinationDockerFilePath, parameter_remoteObject, parameter_dockerContainerId) {
setPermissionsCommand = "docker exec -t --privileged --user 0 -w / $parameter_dockerContainerId chmod 777 " + '"' + parameter_destinationDockerFilePath + '"'
sshCommand remote: parameter_remoteObject, command: setPermissionsCommand
}
def transferOverSsh_copyToDockerContainer_removeFile(parameter_workspaceFileName, parameter_tempDirectory, parameter_remoteObject, parameter_dockerContainerId, parameter_destinationDockerFolder){
parameter_tempFileName = parameter_dockerContainerId + "_" + parameter_workspaceFileName
parameter_remoteFilePath = transferOverSsh(parameter_workspaceFileName, parameter_tempFileName, parameter_tempDirectory, parameter_remoteObject)
parameter_destinationDockerFilePath = parameter_destinationDockerFolder + parameter_workspaceFileName
parameter_removeRemoteFileAfter = true
copyToDockerContainer(parameter_remoteFilePath, parameter_destinationDockerFilePath, parameter_remoteObject, parameter_dockerContainerId, parameter_removeRemoteFileAfter)
}
def runCommand_onDockerContainer(parameter_remoteObject, parameter_commandToRun, parameter_dockerContainerId, parameter_runAsRoot) {
commandToRun = ""
if(parameter_runAsRoot == true)
{
commandToRun = "docker exec -t --privileged --user 0 -w / $parameter_dockerContainerId bash -c " + '"' + parameter_commandToRun + '"'
}
else
{
commandToRun = "docker exec -t $parameter_dockerContainerId bash -c " + '"' + parameter_commandToRun + '"'
}
sshCommand remote: parameter_remoteObject, command: commandToRun
}
def getBuildUserEmail(){
wrap([$class: 'BuildUser']) {
return env.BUILD_USER_EMAIL
}
}
def timeout(message, warningMessage, timeToSleep, timeToSleepBeforeTimeout, timeUnits) {
yesNo = false
yesNoTimeout = false
try {
echo "Waiting before prompting user for input..."
sleep(time:timeToSleep,unit:timeUnits)
timeWarning = timeToSleepBeforeTimeout + " " + timeUnits
email_notifyActionRequired(message, warningMessage, timeWarning)
timeout(time: timeToSleepBeforeTimeout, unit: timeUnits)
{
yesNo = input (
id: 'Proceed1',
message: message,
parameters: [
[
$class: 'BooleanParameterDefinition',
defaultValue: true,
description: '',
name: message
]
]
)
}
} catch(err) { // timeout reached or input false
def user = err.getCauses()[0].getUser()
if('SYSTEM' == user.toString()) { // SYSTEM means timeout.
yesNoTimeout = false
yesNo = false
} else {
yesNo = false
echo "Aborted by: [${user}]"
}
}
if(yesNo == true)
{
timeout(message, warningMessage, timeToSleep, timeToSleepBeforeTimeout, timeUnits)
}
return yesNo
}
def email_notifyActionRequired(message, warningMessage, timeWarning) {
// send to email
emailext (
subject: "[JENKINS] Action Required within "+ timeWarning + " - " + message,
body: """
Hello,
Please navigate to the below URL to address the requested action.
- ${env.BUILD_URL}input
Failure to do so within ${timeWarning} will result in the below conditions:
- ${warningMessage}
Thanks,
Jenkins Automated System
""",
to: getBuildUserEmail()
)
}
def email_notifyUploadRequirement() {
// send to email
emailext (
subject: "[JENKINS] Action Required - Upload The JAR/WAR to Decompile",
body: """
Hello,
Please navigate to the below URL to upload the required JAR/WAR for Decompilation.
- ${env.BUILD_URL}input
Thanks,
Jenkins Automated System
""",
to: getBuildUserEmail()
)
}
def email_workspaceUrl(parameter_remoteObject, parameter_unallocatedPort) {
workspaceHostname = parameter_remoteObject.host
// send to email
emailext (
subject: "[JENKINS] Decompiled JAR/WAR Environment Created",
body: """
Jenkins Job Name:
- ${env.JOB_NAME}
Jenkins Job Build Number:
- ${env.BUILD_NUMBER}
Access your environment at the following endpoint:
- http://$workspaceHostname:$parameter_unallocatedPort/
""",
to: getBuildUserEmail()
)
}