blob: 181eafa0e45aa68db31920a6697580f9a863917a [file] [log] [blame]
azvyagintsev87781882018-08-30 18:45:22 +03001/**
2 *
3 * Promote VCP(qcow2) images
4 *
5 * Expected parameters:
6 * VCP_IMAGE_LIST - multiline with qcow2 file names
7 * TAG - Target tag of image.Possible are: "nightly|testing|proposed|201X.X.X"
8 * SOURCE_TAG - Initial tag to be tagged with TAG. Will replace SUBS_SOURCE_VCP_IMAGE_TAG in VCP_IMAGE_LIST
9 * UPLOAD_URL - WebDav url with creds, from\to download images
10 *
11 */
12
13def common = new com.mirantis.mk.Common()
14def jenkinsUtils = new com.mirantis.mk.JenkinsUtils()
15
16// Better to chose slave with ssd and fast network to webDav host
17slaveNode = env.SLAVE_NODE ?: 'jsl23.mcp.mirantis.net'
18def job_env = env.getEnvironment().findAll { k, v -> v }
19def verify = job_env.VERIFY_DOWNLOAD ?: true
20
21
22timeout(time: 6, unit: 'HOURS') {
23 node(slaveNode) {
24
25 String description = ''
26 insufficientPermissions = false
27 try {
28 // Pre-run verify
29 // promote is restricted to users in aptly-promote-users LDAP group
30 if (!jenkinsUtils.currentUserInGroups(["mcp-cicd-admins", "aptly-promote-users"])) {
31 insufficientPermissions = true
32 error(String.format("You don't have permissions to make promote from source:%s to target:%s! Only CI/CD and QA team can perform promote.", job_env.SOURCE_TAG, job_env.TAG))
33 }
34 // Check for required opts
35 for (opt in ['UPLOAD_URL', 'SOURCE_TAG', 'TAG', 'VCP_IMAGE_LIST']) {
36 if (!job_env.get(opt, null)) {
37 error("Invalid input params, at least ${opt} param missing")
38 }
39 }
40 def images = job_env.VCP_IMAGE_LIST.trim().tokenize()
41 for (image in images) {
42 if (image.startsWith('#')) {
43 common.warningMsg("Skipping image ${image}")
44 continue
45 }
46 common.infoMsg("Replacing SUBS_SOURCE_VCP_IMAGE_TAG => ${job_env.SOURCE_TAG}")
47 sourceImage = image.replace('SUBS_SOURCE_VCP_IMAGE_TAG', job_env.SOURCE_TAG)
48 targetImage = image.replace('SUBS_SOURCE_VCP_IMAGE_TAG', job_env.TAG)
49
50 // TODO: normalize url's?
51 sourceImageUrl = job_env.UPLOAD_URL + '/' + sourceImage
52 sourceImageMd5Url = job_env.UPLOAD_URL + '/' + sourceImage + '.md5'
53 targetImageUrl = job_env.UPLOAD_URL + '/' + targetImage
54 targetImageMd5Url = job_env.UPLOAD_URL + '/' + targetImage + '.md5'
55
56 common.infoMsg("Attempt to download: ${sourceImage} => ${targetImage}")
57 common.retry(3, 5) {
58 sh(script: "wget --progress=dot:giga --auth-no-challenge -O ${targetImage} ${sourceImageUrl}")
59 }
60 def targetImageMd5 = common.cutOrDie("md5sum ${targetImage} | tee ${targetImage}.md5", 0)
61 if (verify.toBoolean()) {
62 common.infoMsg("Checking md5's ")
63 sh(script: "wget --progress=dot:giga --auth-no-challenge -O ${targetImage}_source_md5 ${sourceImageMd5Url}")
64 def sourceImageMd5 = readFile(file: "${targetImage}_source_md5").tokenize(' ')[0]
65 // Compare downloaded and remote files
66 if (sourceImageMd5 != targetImageMd5) {
67 error("Image ${targetImage} md5sum verify failed!")
68 } else {
69 common.infoMsg("sourceImageMd5: ${sourceImageMd5} == target to upload ImageMd5: ${targetImageMd5}")
70 }
71 // Compare downloaded file, and remote file-to-be-promoted. If same - no sense to promote same file
72 remoteImageMd5Status = sh(script: "wget --progress=dot:giga --auth-no-challenge -O ${targetImage}_expected_target_md5 ${targetImageMd5Url}", returnStatus: true)
73 if (remoteImageMd5Status == '8') {
74 common.infoMsg("target to upload ImageMd5 file not even exist.Continue..")
75 } else {
76 def remoteImageMd5 = readFile(file: "${targetImage}_expected_target_md5").tokenize(' ')[0]
77 if (sourceImageMd5 == remoteImageMd5) {
78 common.infoMsg("sourceImageMd5: ${sourceImageMd5} and target to upload ImageMd5: ${targetImageMd5} are same")
79 common.warningMsg("Skipping to upload: ${targetImage} since it already same")
80 description += "Skipping to upload: ${targetImage} since it already same\n"
81 continue
82 }
83 }
84 common.infoMsg("Check, that we are not going to overwrite released file..")
85 if (['proposed', 'testing', 'nightly'].contains(job_env.TAG)) {
86 common.infoMsg("Uploading to ${job_env.TAG} looks safe..")
87 } else if (['stable'].contains(job_env.TAG)) {
88 common.warningMsg("Uploading to ${job_env.TAG} not safe! But still possible")
89 } else {
90 common.warningMsg("Looks like uploading to new release: ${job_env.TAG}. Checking, that it is not exist yet..")
91 remoteImageStatus = ''
92 remoteImageStatus = sh(script: "wget --auth-no-challenge --spider ${targetImageUrl} 2>/dev/null", returnStatus: true)
93 // wget return code 8 ,if file not exist
94 if (remoteImageStatus != '8') {
95 error("Attempt to overwrite existing release! Target: ${targetImage} already exist!")
96 }
97 }
98 }
99
100 common.infoMsg("Attempt to UPLOAD: ${targetImage} => ${targetImageUrl}")
101 //
102 def uploadImageStatus = ''
103 def uploadImageMd5Status = ''
104 common.retry(3, 5) {
105 uploadImageStatus = sh(script: "curl -f -T ${targetImage} ${job_env.UPLOAD_URL}", returnStatus: true)
106 if (uploadImageStatus != 0) {
107 error("Uploading file: ${targetImage} failed!")
108 }
109 }
110 uploadImageMd5Status = sh(script: "curl -f -T ${targetImage}.md5 ${job_env.UPLOAD_URL}", returnStatus: true)
111 if (uploadImageMd5Status != 0) {
112 error("Uploading file: ${targetImage}.md5 failed!")
113 }
114
115 description += "<a href='http://apt.mirantis.net:8085/images/${targetImage}'>${job_env.SOURCE_TAG}=>${targetImage}</a>"
116 }
117 currentBuild.description = description
118 } catch (Throwable e) {
119 // If there was an error or exception thrown, the build failed
120 if (insufficientPermissions) {
121 currentBuild.result = "ABORTED"
122 currentBuild.description = "Promote aborted due to insufficient permissions"
123 } else {
124 currentBuild.result = "FAILURE"
125 currentBuild.description = currentBuild.description ? e.message + " " + currentBuild.description : e.message
126 }
127 throw e
128 }
129 finally {
130 common.infoMsg("Cleanup..")
131 sh(script: 'find . -mindepth 1 -delete > /dev/null || true')
132 }
133 }
134}