blob: 14dddf13da6e4a99c232e98ddb86c0635c096754 [file] [log] [blame]
/**
*
* Promote VCP(qcow2) images
*
* Expected parameters:
* VCP_IMAGE_LIST - multiline with qcow2 file names
* TAG - Target tag of image.Possible are: "nightly|testing|proposed|201X.X.X"
* SOURCE_TAG - Initial tag to be tagged with TAG. Will replace SUBS_SOURCE_VCP_IMAGE_TAG in VCP_IMAGE_LIST
* UPLOAD_URL - WebDav url with creds, from\to download images
*
*/
def common = new com.mirantis.mk.Common()
def jenkinsUtils = new com.mirantis.mk.JenkinsUtils()
// Better to chose slave with ssd and fast network to webDav host
slaveNode = env.SLAVE_NODE ?: 'promotion'
def job_env = env.getEnvironment().findAll { k, v -> v }
def verify = job_env.VERIFY_DOWNLOAD ?: true
def overwrite = job_env.FORCE_OVERWRITE.toBoolean() ?: false
timeout(time: 6, unit: 'HOURS') {
node(slaveNode) {
String description = ''
insufficientPermissions = false
try {
// Pre-run verify
// promote is restricted to users in aptly-promote-users LDAP group
if (!jenkinsUtils.currentUserInGroups(["mcp-cicd-admins", "aptly-promote-users"])) {
insufficientPermissions = true
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))
}
// Check for required opts
for (opt in ['UPLOAD_URL', 'SOURCE_TAG', 'TAG', 'VCP_IMAGE_LIST']) {
if (!job_env.get(opt, null)) {
error("Invalid input params, at least ${opt} param missing")
}
}
def images = job_env.VCP_IMAGE_LIST.trim().tokenize()
for (image in images) {
if (image.startsWith('#')) {
common.warningMsg("Skipping image ${image}")
continue
}
common.infoMsg("Replacing SUBS_SOURCE_VCP_IMAGE_TAG => ${job_env.SOURCE_TAG}")
sourceImage = image.replace('SUBS_SOURCE_VCP_IMAGE_TAG', job_env.SOURCE_TAG)
targetImage = image.replace('SUBS_SOURCE_VCP_IMAGE_TAG', job_env.TAG)
// TODO: normalize url's?
sourceImageUrl = job_env.UPLOAD_URL + '/' + sourceImage
sourceImageMd5Url = job_env.UPLOAD_URL + '/' + sourceImage + '.md5'
targetImageUrl = job_env.UPLOAD_URL + '/' + targetImage
targetImageMd5Url = job_env.UPLOAD_URL + '/' + targetImage + '.md5'
common.infoMsg("Attempt to download: ${sourceImage} => ${targetImage}")
common.retry(3, 5) {
sh(script: "wget --progress=dot:giga --auth-no-challenge -O ${targetImage} ${sourceImageUrl}")
}
def targetImageMd5 = common.cutOrDie("md5sum ${targetImage} | tee ${targetImage}.md5", 0)
if (verify.toBoolean()) {
common.infoMsg("Checking md5's ")
sh(script: "wget --progress=dot:giga --auth-no-challenge -O ${targetImage}_source_md5 ${sourceImageMd5Url}")
def sourceImageMd5 = readFile(file: "${targetImage}_source_md5").tokenize(' ')[0]
// Compare downloaded and remote files
if (sourceImageMd5 != targetImageMd5) {
error("Image ${targetImage} md5sum verify failed!")
} else {
common.infoMsg("sourceImageMd5: ${sourceImageMd5} == target to upload ImageMd5: ${targetImageMd5}")
}
// Compare downloaded file, and remote file-to-be-promoted. If same - no sense to promote same file
remoteImageMd5Status = sh(script: "wget --progress=dot:giga --auth-no-challenge -O ${targetImage}_expected_target_md5 ${targetImageMd5Url}", returnStatus: true)
if (remoteImageMd5Status == '8') {
common.infoMsg("target to upload ImageMd5 file not even exist.Continue..")
} else {
def remoteImageMd5 = readFile(file: "${targetImage}_expected_target_md5").tokenize(' ')[0]
if (sourceImageMd5 == remoteImageMd5) {
common.infoMsg("sourceImageMd5: ${sourceImageMd5} and target to upload ImageMd5: ${targetImageMd5} are same")
common.warningMsg("Skipping to upload: ${targetImage} since it already same")
description += "Skipping to upload: ${targetImage} since it already same\n"
continue
}
}
common.infoMsg("Check, that we are not going to overwrite released file..")
if (['proposed', 'testing', 'nightly'].contains(job_env.TAG)) {
common.infoMsg("Uploading to ${job_env.TAG} looks safe..")
} else if (['stable'].contains(job_env.TAG)) {
common.warningMsg("Uploading to ${job_env.TAG} not safe! But still possible")
} else {
common.warningMsg("Looks like uploading to new release: ${job_env.TAG}. Checking, that it is not exist yet..")
remoteImageStatus = ''
remoteImageStatus = sh(script: "wget --auth-no-challenge --spider ${targetImageUrl} 2>/dev/null", returnStatus: true)
// wget return code 8 ,if file not exist
if (remoteImageStatus != 8 && !overwrite) {
error("Attempt to overwrite existing release! Target: ${targetImage} already exist!")
}
}
}
common.infoMsg("Attempt to UPLOAD: ${targetImage} => ${targetImageUrl}")
//
def uploadImageStatus = ''
def uploadImageMd5Status = ''
common.retry(3, 5) {
uploadImageStatus = sh(script: "curl -f -T ${targetImage} ${job_env.UPLOAD_URL}", returnStatus: true)
if (uploadImageStatus != 0) {
error("Uploading file: ${targetImage} failed!")
}
}
uploadImageMd5Status = sh(script: "curl -f -T ${targetImage}.md5 ${job_env.UPLOAD_URL}", returnStatus: true)
if (uploadImageMd5Status != 0) {
error("Uploading file: ${targetImage}.md5 failed!")
}
description += "<a href='http://images.mcp.mirantis.net/${targetImage}'>${job_env.SOURCE_TAG}=>${targetImage}</a>"
}
currentBuild.description = description
} catch (Throwable e) {
// If there was an error or exception thrown, the build failed
if (insufficientPermissions) {
currentBuild.result = "ABORTED"
currentBuild.description = "Promote aborted due to insufficient permissions"
} else {
currentBuild.result = "FAILURE"
currentBuild.description = currentBuild.description ? e.message + " " + currentBuild.description : e.message
}
throw e
}
finally {
common.infoMsg("Cleanup..")
sh(script: 'find . -mindepth 1 -delete > /dev/null || true')
}
}
}