blob: 7820135e75368fd8757f36f020cca9d4d14b13c4 [file] [log] [blame]
package com.mirantis.mcp
import org.jfrog.hudson.pipeline.types.ArtifactoryServer
import org.jfrog.hudson.pipeline.types.buildInfo.BuildInfo
/**
* Return string of mandatory build properties for binaries
* User can also add some custom properties.
*
* @param customProperties a Array of Strings that should be added to mandatory props
* in format ["prop1=value1", "prop2=value2"]
* */
def getBinaryBuildProperties(ArrayList customProperties) {
def namespace = "com.mirantis."
def properties = [
"buildName=${env.JOB_NAME}",
"buildNumber=${env.BUILD_NUMBER}",
"gerritProject=${env.GERRIT_PROJECT}",
"gerritChangeNumber=${env.GERRIT_CHANGE_NUMBER}",
"gerritPatchsetNumber=${env.GERRIT_PATCHSET_NUMBER}",
"gerritChangeId=${env.GERRIT_CHANGE_ID}",
"gerritPatchsetRevision=${env.GERRIT_PATCHSET_REVISION}"
]
if (customProperties) {
properties.addAll(customProperties)
}
def common = new com.mirantis.mcp.Common()
return common.constructString(properties, namespace, ";")
}
/**
* Get URL to artifact(s) by properties
* Returns String(s) with URL to found artifact or null if nothing
*
* @param artifactoryURL String, an URL to Artifactory
* @param properties LinkedHashMap, a Hash of properties (key-value) which
* which should determine artifact in Artifactory
* @param onlyLastItem Boolean, return only last URL if true(by default),
* else return list of all found artifact URLS
*
*/
def uriByProperties(String artifactoryURL, LinkedHashMap properties, Boolean onlyLastItem=true) {
def key, value
def properties_str = ''
for (int i = 0; i < properties.size(); i++) {
// avoid serialization errors
key = properties.entrySet().toArray()[i].key
value = properties.entrySet().toArray()[i].value
properties_str += "${key}=${value}&"
}
def search_url = "${artifactoryURL}/api/search/prop?${properties_str}"
def result = sh(script: "bash -c \"curl -X GET \'${search_url}\'\"",
returnStdout: true).trim()
def content = new groovy.json.JsonSlurperClassic().parseText(result)
def uri = content.get("results")
if (uri) {
if (onlyLastItem) {
return uri.last().get("uri")
} else {
res = []
uri.each {it ->
res.add(it.get("uri"))
}
return res
}
} else {
return null
}
}
/**
* Set properties for artifact in Artifactory repo
*
* @param artifactUrl String, an URL to artifact in Artifactory repo
* @param properties LinkedHashMap, a Hash of properties (key-value) which
* should be assigned for choosen artifact
* @param recursive Boolean, if artifact_url is a directory, whether to set
* properties recursively or not
*/
def setProperties(String artifactUrl, LinkedHashMap properties, Boolean recursive = false) {
def properties_str = 'properties='
def key, value
if (recursive) {
recursive = 'recursive=1'
} else {
recursive = 'recursive=0'
}
properties_str += properties.collect({"${it.key}=${it.value}"}).join(';')
def url = "${artifactUrl}?${properties_str}&${recursive}"
withCredentials([
[$class : 'UsernamePasswordMultiBinding',
credentialsId : 'artifactory',
passwordVariable: 'ARTIFACTORY_PASSWORD',
usernameVariable: 'ARTIFACTORY_LOGIN']
]) {
sh "bash -c \"curl -X PUT -u ${ARTIFACTORY_LOGIN}:${ARTIFACTORY_PASSWORD} \'${url}\'\""
}
}
/**
* Get properties for specified artifact in Artifactory
* Returns LinkedHashMap of properties
*
* @param artifactUrl String, an URL to artifact in Artifactory repo
*/
def getPropertiesForArtifact(String artifactUrl) {
def url = "${artifactUrl}?properties"
def result
withCredentials([
[$class : 'UsernamePasswordMultiBinding',
credentialsId : 'artifactory',
passwordVariable: 'ARTIFACTORY_PASSWORD',
usernameVariable: 'ARTIFACTORY_LOGIN']
]) {
result = sh(script: "bash -c \"curl -X GET -u ${ARTIFACTORY_LOGIN}:${ARTIFACTORY_PASSWORD} \'${url}\'\"",
returnStdout: true).trim()
}
def properties = new groovy.json.JsonSlurperClassic().parseText(result)
return properties.get("properties")
}
/**
* Find docker images by tag
* Returns Array of image' hashes with names as full path in @repo
*
* Example:
*
* [ {
* "path" : "mirantis/ccp/ci-cd/gerrit-manage/test"
* },
* {
* "path" : "mirantis/ccp/ci-cd/gerrit/test"
* }
* ]
*
* @param artifactoryURL String, an URL to Artifactory
* @param repo String, a name of repo where should be executed search
* @param tag String, tag of searched image
*/
def getImagesByTag(String artifactoryURL, String repo, String tag) {
def url = "${artifactoryURL}/api/search/aql"
def result
writeFile file: "query",
text: """\
items.find(
{
\"repo\": \"${repo}\",
\"@docker.manifest\": { \"\$match\" : \"${tag}*\" }
}
).
include(\"path\")
""".stripIndent()
withCredentials([
[$class: 'UsernamePasswordMultiBinding',
credentialsId: 'artifactory',
passwordVariable: 'ARTIFACTORY_PASSWORD',
usernameVariable: 'ARTIFACTORY_LOGIN']
]) {
result = sh(script: "bash -c \"curl -X POST -u ${ARTIFACTORY_LOGIN}:${ARTIFACTORY_PASSWORD} -d @query \'${url}\'\"",
returnStdout: true).trim()
}
def images = new groovy.json.JsonSlurperClassic().parseText(result)
return images.get("results")
}
/**
* Upload docker image to Artifactory
*
* @param server ArtifactoryServer, the instance of Artifactory server
* @param registry String, the name of Docker registry
* @param image String, Docker image name
* @param version String, Docker image version
* @param repository String, The name of Artifactory Docker repository
* @param buildInfo BuildInfo, the instance of a build-info object which can be published,
* if defined, then we publish BuildInfo
*/
def uploadImageToArtifactory (ArtifactoryServer server, String registry, String image,
String version, String repository,
BuildInfo buildInfo = null,
LinkedHashMap properties = null) {
// TODO Switch to Artifactoy image' pushing mechanism once we will
// prepare automatical way for enabling artifactory build-proxy
//def artDocker
withCredentials([
[$class: 'UsernamePasswordMultiBinding',
credentialsId: 'artifactory',
passwordVariable: 'ARTIFACTORY_PASSWORD',
usernameVariable: 'ARTIFACTORY_LOGIN']
]) {
sh ("docker login -u ${ARTIFACTORY_LOGIN} -p ${ARTIFACTORY_PASSWORD} ${registry}")
//artDocker = Artifactory.docker("${env.ARTIFACTORY_LOGIN}", "${env.ARTIFACTORY_PASSWORD}")
}
sh ("docker push ${registry}/${image}:${version}")
//artDocker.push("${registry}/${image}:${version}", "${repository}")
def image_url = server.getUrl() + "/api/storage/${repository}/${image}/${version}"
if ( ! properties ) {
properties = [
'com.mirantis.buildName':"${env.JOB_NAME}",
'com.mirantis.buildNumber': "${env.BUILD_NUMBER}",
'com.mirantis.gerritProject': "${env.GERRIT_PROJECT}",
'com.mirantis.gerritChangeNumber': "${env.GERRIT_CHANGE_NUMBER}",
'com.mirantis.gerritPatchsetNumber': "${env.GERRIT_PATCHSET_NUMBER}",
'com.mirantis.gerritChangeId': "${env.GERRIT_CHANGE_ID}",
'com.mirantis.gerritPatchsetRevision': "${env.GERRIT_PATCHSET_REVISION}",
'com.mirantis.targetImg': "${image}",
'com.mirantis.targetTag': "${version}"
]
}
setProperties(image_url, properties)
if ( buildInfo != null ) {
buildInfo.env.capture = true
buildInfo.env.filter.addInclude("*")
buildInfo.env.filter.addExclude("*PASSWORD*")
buildInfo.env.filter.addExclude("*password*")
buildInfo.env.collect()
server.publishBuildInfo(buildInfo)
}
}
/**
* Upload binaries to Artifactory
*
* @param server ArtifactoryServer, the instance of Artifactory server
* @param buildInfo BuildInfo, the instance of a build-info object which can be published
* @param uploadSpec String, a spec which is a JSON file that specifies which files should be
* uploaded or downloaded and the target path
* @param publishInfo Boolean, whether publish a build-info object to Artifactory
*/
def uploadBinariesToArtifactory (ArtifactoryServer server, BuildInfo buildInfo, String uploadSpec,
Boolean publishInfo = false) {
server.upload(uploadSpec, buildInfo)
if ( publishInfo ) {
buildInfo.env.capture = true
buildInfo.env.filter.addInclude("*")
buildInfo.env.filter.addExclude("*PASSWORD*")
buildInfo.env.filter.addExclude("*password*")
buildInfo.env.collect()
server.publishBuildInfo(buildInfo)
}
}
/**
* Promote Docker image artifact to release repo
*
* @param artifactoryURL String, an URL to Artifactory
* @param artifactoryDevRepo String, the source dev repository name
* @param artifactoryProdRepo String, the target repository for the move or copy
* @param dockerRepo String, the docker repository name to promote
* @param artifactTag String, an image tag name to promote
* @param targetTag String, target tag to assign the image after promotion
* @param copy Boolean, an optional value to set whether to copy instead of move
* Default: false
*/
def promoteDockerArtifact(String artifactoryURL, String artifactoryDevRepo,
String artifactoryProdRepo, String dockerRepo,
String artifactTag, String targetTag, Boolean copy = false) {
def url = "${artifactoryURL}/api/docker/${artifactoryDevRepo}/v2/promote"
String queryFile = UUID.randomUUID().toString()
writeFile file: queryFile,
text: """{
\"targetRepo\": \"${artifactoryProdRepo}\",
\"dockerRepository\": \"${dockerRepo}\",
\"tag\": \"${artifactTag}\",
\"targetTag\" : \"${targetTag}\",
\"copy\": \"${copy}\"
}""".stripIndent()
sh "cat ${queryFile}"
withCredentials([
[$class : 'UsernamePasswordMultiBinding',
credentialsId : 'artifactory',
passwordVariable: 'ARTIFACTORY_PASSWORD',
usernameVariable: 'ARTIFACTORY_LOGIN']
]) {
sh "bash -c \"curl --fail -u ${ARTIFACTORY_LOGIN}:${ARTIFACTORY_PASSWORD} -H \"Content-Type:application/json\" -X POST -d @${queryFile} ${url}\""
}
sh "rm -v ${queryFile}"
}