blob: 4ccc74a44c38dc2f42434d35abf13035b2b7332f [file] [log] [blame]
Richard Felkle90ef1c2017-12-08 00:13:56 +01001/**
2 *
3 * Mirror Docker images
4 *
5 * Expected parameters:
6 * TARGET_REGISTRY_CREDENTIALS_ID Credentials for target Docker Registry
7 * TARGET_REGISTRY Target Docker Registry name
8 * REGISTRY_URL Target Docker Registry URL
9 * IMAGE_TAG Tag to use when pushing images
azvyagintsevd162b912018-07-26 10:52:14 +020010 * SOURCE_IMAGE_TAG Tag to use when pulling images(optional,if SOURCE_IMAGE_TAG has been found)
azvyagintsev388a1bd2018-09-06 12:39:49 +030011 * SET_DEFAULT_ARTIFACTORY_PROPERTIES Add extra props. directly to artifactory,
Richard Felkle90ef1c2017-12-08 00:13:56 +010012 * IMAGE_LIST List of images to mirror
azvyagintsev388a1bd2018-09-06 12:39:49 +030013 * Example: docker.elastic.co/elasticsearch/elasticsearch:5.4.1 docker-prod-local.docker.mirantis.net/mirantis/external/docker.elastic.co/elasticsearch
14 * docker.elastic.co/elasticsearch/elasticsearch:SUBS_SOURCE_IMAGE_TAG docker-prod-local.docker.mirantis.net/mirantis/external/elasticsearch:${IMAGE_TAG}* Will be proceed like:
15 * 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
16 *
Richard Felkle90ef1c2017-12-08 00:13:56 +010017 *
18 */
azvyagintsev388a1bd2018-09-06 12:39:49 +030019import java.util.regex.Pattern
20import groovy.json.JsonSlurper
Richard Felkle90ef1c2017-12-08 00:13:56 +010021
azvyagintsev388a1bd2018-09-06 12:39:49 +030022common = new com.mirantis.mk.Common()
23external = false
24externalMarker = '/mirantis/external/'
Richard Felkle90ef1c2017-12-08 00:13:56 +010025
azvyagintsev388a1bd2018-09-06 12:39:49 +030026slaveNode = env.SLAVE_NODE ?: 'docker'
27setDefaultArtifactoryProperties = env.SET_DEFAULT_ARTIFACTORY_PROPERTIES ?: true
28
Richard Felkle90ef1c2017-12-08 00:13:56 +010029def getImageName(String image) {
30 def regex = Pattern.compile('(?:.+/)?([^:]+)(?::.+)?')
31 def matcher = regex.matcher(image)
azvyagintsev388a1bd2018-09-06 12:39:49 +030032 if (matcher.find()) {
Richard Felkle90ef1c2017-12-08 00:13:56 +010033 def imageName = matcher.group(1)
34 return imageName
azvyagintsev388a1bd2018-09-06 12:39:49 +030035 } else {
36 error("Wrong format of image name.")
Richard Felkle90ef1c2017-12-08 00:13:56 +010037 }
38}
azvyagintsev388a1bd2018-09-06 12:39:49 +030039
40timeout(time: 4, unit: 'HOURS') {
41 node(slaveNode) {
Jakub Josefa63f9862018-01-11 17:58:38 +010042 try {
azvyagintsev388a1bd2018-09-06 12:39:49 +030043 stage("Mirror Docker Images") {
44
Jakub Josefa63f9862018-01-11 17:58:38 +010045 def images = IMAGE_LIST.tokenize('\n')
azvyagintsev388a1bd2018-09-06 12:39:49 +030046 def imageName, sourceImage, targetRegistryPath, imageArray
47 for (image in images) {
48 if (image.trim().indexOf(' ') == -1) {
49 error("Wrong format of image and target repository input")
Jakub Josefa63f9862018-01-11 17:58:38 +010050 }
51 imageArray = image.trim().tokenize(' ')
azvyagintsev388a1bd2018-09-06 12:39:49 +030052 sourceImage = imageArray[0]
53 if (sourceImage.contains('SUBS_SOURCE_IMAGE_TAG')) {
54 common.warningMsg("Replacing SUBS_SOURCE_IMAGE_TAG => ${env.SOURCE_IMAGE_TAG}")
55 sourceImage = sourceImage.replace('SUBS_SOURCE_IMAGE_TAG', env.SOURCE_IMAGE_TAG)
azvyagintsevd162b912018-07-26 10:52:14 +020056 }
azvyagintsev388a1bd2018-09-06 12:39:49 +030057 targetRegistryPath = imageArray[1]
58 targetRegistry = imageArray[1].split('/')[0]
59 imageName = getImageName(sourceImage)
60 targetImageFull = "${targetRegistryPath}/${imageName}:${env.IMAGE_TAG}"
61 srcImage = docker.image(sourceImage)
azvyagintsev86ba4a02018-10-03 19:21:28 +030062 common.retry(3, 5) {
63 srcImage.pull()
64 }
azvyagintsev388a1bd2018-09-06 12:39:49 +030065 // Use sh-docker call for tag, due magic code in plugin:
66 // https://github.com/jenkinsci/docker-workflow-plugin/blob/docker-workflow-1.17/src/main/resources/org/jenkinsci/plugins/docker/workflow/Docker.groovy#L168-L170
67 sh("docker tag ${srcImage.id} ${targetImageFull}")
68 common.infoMsg("Attempt to push docker image into remote registry: ${env.REGISTRY_URL}")
azvyagintsev86ba4a02018-10-03 19:21:28 +030069 common.retry(3, 5) {
70 docker.withRegistry(env.REGISTRY_URL, env.TARGET_REGISTRY_CREDENTIALS_ID) {
71 sh("docker push ${targetImageFull}")
72 }
Alexander Evseevd70ef002018-10-02 13:01:27 +020073 }
azvyagintsev388a1bd2018-09-06 12:39:49 +030074 if (targetImageFull.contains(externalMarker)) {
75 external = true
76 }
77
78 if (setDefaultArtifactoryProperties) {
79 common.infoMsg("Processing artifactory props for : ${targetImageFull}")
80 LinkedHashMap artifactoryProperties = [:]
81 // Get digest of pushed image
82 String unique_image_id = sh(
83 script: "docker inspect --format='{{index .RepoDigests 0}}' '${targetImageFull}'",
84 returnStdout: true,
85 ).trim()
86 def image_sha256 = unique_image_id.tokenize(':')[1]
87 def ret = new URL("https://${targetRegistry}/artifactory/api/search/checksum?sha256=${image_sha256}").getText()
88 // Most probably, we would get many images, especially for external images. We need to guess
89 // exactly one, which we pushing now
90 guessImage = targetImageFull.replace(':', '/').replace(targetRegistry, '')
91 ArrayList img_data = new JsonSlurper().parseText(ret)['results']
92 img_data*.uri.each { imgUrl ->
93 if (imgUrl.contains(guessImage)) {
94 artifactoryProperties = [
95 'com.mirantis.targetTag' : env.IMAGE_TAG,
96 'com.mirantis.uniqueImageId': unique_image_id,
97 ]
98 if (external) {
99 artifactoryProperties << ['com.mirantis.externalImage': external]
100 }
101 common.infoMsg("artifactoryProperties=> ${artifactoryProperties}")
102 // Call pipeline-library routine to set properties
103 def mcp_artifactory = new com.mirantis.mcp.MCPArtifactory()
azvyagintsev86ba4a02018-10-03 19:21:28 +0300104 common.retry(3, 5) {
105 mcp_artifactory.setProperties(imgUrl - '/manifest.json', artifactoryProperties)
106 }
azvyagintsev388a1bd2018-09-06 12:39:49 +0300107 }
108 }
109 }
Richard Felkl7c920d02017-12-11 15:28:18 +0100110 }
Richard Felkle90ef1c2017-12-08 00:13:56 +0100111 }
Jakub Josefa63f9862018-01-11 17:58:38 +0100112 } catch (Throwable e) {
azvyagintsev388a1bd2018-09-06 12:39:49 +0300113 // Stub for future processing
Jakub Josefa63f9862018-01-11 17:58:38 +0100114 currentBuild.result = "FAILURE"
115 throw e
Richard Felkle90ef1c2017-12-08 00:13:56 +0100116 }
Richard Felkle90ef1c2017-12-08 00:13:56 +0100117 }
azvyagintsevd162b912018-07-26 10:52:14 +0200118}