Refactor docker-mirror-images.groovy
* Set artifactory.props for images
Change-Id: I96f85713befc1edc6b4e8314641f16bbef667491
diff --git a/docker-mirror-images.groovy b/docker-mirror-images.groovy
index 07a80e7..d88c9d1 100644
--- a/docker-mirror-images.groovy
+++ b/docker-mirror-images.groovy
@@ -8,51 +8,101 @@
* REGISTRY_URL Target Docker Registry URL
* IMAGE_TAG Tag to use when pushing images
* SOURCE_IMAGE_TAG Tag to use when pulling images(optional,if SOURCE_IMAGE_TAG has been found)
+ * SET_DEFAULT_ARTIFACTORY_PROPERTIES Add extra props. directly to artifactory,
* IMAGE_LIST List of images to mirror
+ * Example: docker.elastic.co/elasticsearch/elasticsearch:5.4.1 docker-prod-local.docker.mirantis.net/mirantis/external/docker.elastic.co/elasticsearch
+ * docker.elastic.co/elasticsearch/elasticsearch:SUBS_SOURCE_IMAGE_TAG docker-prod-local.docker.mirantis.net/mirantis/external/elasticsearch:${IMAGE_TAG}* Will be proceed like:
+ * docker tag docker.elastic.co/elasticsearch/elasticsearch:5.4.1 docker-prod-local.docker.mirantis.net/mirantis/external/docker.elastic.co/elasticsearch/elasticsearch:5.4.1
+ *
*
*/
-import java.util.regex.Pattern;
+import java.util.regex.Pattern
+import groovy.json.JsonSlurper
-def common = new com.mirantis.mk.Common()
+common = new com.mirantis.mk.Common()
+external = false
+externalMarker = '/mirantis/external/'
-@NonCPS
+slaveNode = env.SLAVE_NODE ?: 'docker'
+setDefaultArtifactoryProperties = env.SET_DEFAULT_ARTIFACTORY_PROPERTIES ?: true
+
def getImageName(String image) {
def regex = Pattern.compile('(?:.+/)?([^:]+)(?::.+)?')
def matcher = regex.matcher(image)
- if(matcher.find()){
+ if (matcher.find()) {
def imageName = matcher.group(1)
return imageName
- }else{
- throw new IllegalArgumentException("Wrong format of image name.")
+ } else {
+ error("Wrong format of image name.")
}
}
-timeout(time: 12, unit: 'HOURS') {
- node("docker") {
+
+timeout(time: 4, unit: 'HOURS') {
+ node(slaveNode) {
try {
- stage("Mirror Docker Images"){
- def creds = common.getPasswordCredentials(TARGET_REGISTRY_CREDENTIALS_ID)
- sh "docker login --username=${creds.username} --password=${creds.password.toString()} ${REGISTRY_URL}"
+ stage("Mirror Docker Images") {
+
def images = IMAGE_LIST.tokenize('\n')
- def imageName, imagePath, targetRegistry, imageArray
- for (image in images){
- if(image.trim().indexOf(' ') == -1){
- throw new IllegalArgumentException("Wrong format of image and target repository input")
+ def imageName, sourceImage, targetRegistryPath, imageArray
+ for (image in images) {
+ if (image.trim().indexOf(' ') == -1) {
+ error("Wrong format of image and target repository input")
}
imageArray = image.trim().tokenize(' ')
- imagePath = imageArray[0]
- if (imagePath.contains('SUBS_SOURCE_IMAGE_TAG')) {
- common.warningMsg("Replacing SUBS_SOURCE_IMAGE_TAG => ${SOURCE_IMAGE_TAG}")
- imagePath = imagePath.replace('SUBS_SOURCE_IMAGE_TAG', SOURCE_IMAGE_TAG)
+ sourceImage = imageArray[0]
+ if (sourceImage.contains('SUBS_SOURCE_IMAGE_TAG')) {
+ common.warningMsg("Replacing SUBS_SOURCE_IMAGE_TAG => ${env.SOURCE_IMAGE_TAG}")
+ sourceImage = sourceImage.replace('SUBS_SOURCE_IMAGE_TAG', env.SOURCE_IMAGE_TAG)
}
- targetRegistry = imageArray[1]
- imageName = getImageName(imagePath)
- sh """docker pull ${imagePath}
- docker tag ${imagePath} ${targetRegistry}/${imageName}:${IMAGE_TAG}
- docker push ${targetRegistry}/${imageName}:${IMAGE_TAG}"""
+ targetRegistryPath = imageArray[1]
+ targetRegistry = imageArray[1].split('/')[0]
+ imageName = getImageName(sourceImage)
+ targetImageFull = "${targetRegistryPath}/${imageName}:${env.IMAGE_TAG}"
+ srcImage = docker.image(sourceImage)
+ srcImage.pull()
+ // Use sh-docker call for tag, due magic code in plugin:
+ // https://github.com/jenkinsci/docker-workflow-plugin/blob/docker-workflow-1.17/src/main/resources/org/jenkinsci/plugins/docker/workflow/Docker.groovy#L168-L170
+ sh("docker tag ${srcImage.id} ${targetImageFull}")
+ common.infoMsg("Attempt to push docker image into remote registry: ${env.REGISTRY_URL}")
+ sh("docker push ${targetImageFull}")
+ if (targetImageFull.contains(externalMarker)) {
+ external = true
+ }
+
+ if (setDefaultArtifactoryProperties) {
+ common.infoMsg("Processing artifactory props for : ${targetImageFull}")
+ LinkedHashMap artifactoryProperties = [:]
+ // Get digest of pushed image
+ String unique_image_id = sh(
+ script: "docker inspect --format='{{index .RepoDigests 0}}' '${targetImageFull}'",
+ returnStdout: true,
+ ).trim()
+ def image_sha256 = unique_image_id.tokenize(':')[1]
+ def ret = new URL("https://${targetRegistry}/artifactory/api/search/checksum?sha256=${image_sha256}").getText()
+ // Most probably, we would get many images, especially for external images. We need to guess
+ // exactly one, which we pushing now
+ guessImage = targetImageFull.replace(':', '/').replace(targetRegistry, '')
+ ArrayList img_data = new JsonSlurper().parseText(ret)['results']
+ img_data*.uri.each { imgUrl ->
+ if (imgUrl.contains(guessImage)) {
+ artifactoryProperties = [
+ 'com.mirantis.targetTag' : env.IMAGE_TAG,
+ 'com.mirantis.uniqueImageId': unique_image_id,
+ ]
+ if (external) {
+ artifactoryProperties << ['com.mirantis.externalImage': external]
+ }
+ common.infoMsg("artifactoryProperties=> ${artifactoryProperties}")
+ // Call pipeline-library routine to set properties
+ def mcp_artifactory = new com.mirantis.mcp.MCPArtifactory()
+ mcp_artifactory.setProperties(imgUrl - '/manifest.json', artifactoryProperties)
+ }
+ }
+ }
}
}
} catch (Throwable e) {
- // If there was an error or exception thrown, the build failed
+ // Stub for future processing
currentBuild.result = "FAILURE"
throw e
}