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