Pipeline for promotion images from dev to prod repositories
Original pipeline: docker-mirror-images.groovy (1 patchset)
Pull and push were replaced by promote via api
Unused functions for properies were removed from pipeline
Related-PROD: PROD-33134
Change-Id: I5de16a38b59553311766391bb122037d84b10a51
diff --git a/release-promote-docker-images.groovy b/release-promote-docker-images.groovy
new file mode 100644
index 0000000..fe1ddb7
--- /dev/null
+++ b/release-promote-docker-images.groovy
@@ -0,0 +1,118 @@
+/**
+ *
+ * Mirror list Docker images
+ *
+ * Expected parameters:
+ * TARGET_REGISTRY_CREDENTIALS_ID Credentials for target Docker Registry
+ * TARGET_REGISTRY Target Docker Registry name
+ * 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-dev-local.docker.mirantis.net/mirantis/external/docker.elastic.co/elasticsearch
+ * docker-dev-local.docker.mirantis.net/mirantis/external/elasticsearch:${IMAGE_TAG}*
+ * docker-dev-local.docker.mirantis.net/mirantis/external/docker.elastic.co/elasticsearch/elasticsearch:5.4.1
+ */
+
+import java.util.regex.Pattern
+
+common = new com.mirantis.mk.Common()
+jenkinsUtils = new com.mirantis.mk.JenkinsUtils()
+
+def registryRegex = Pattern.compile('docker-dev|dev-docker')
+def namespaceRegex = Pattern.compile('mirantis|library')
+def componentRegex = Pattern.compile('kaas|kaas-bm|oscore')
+
+String external = false
+String externalMarker = '/mirantis/external/'
+def artifactory = new com.mirantis.mcp.MCPArtifactory()
+def artifactoryServer = Artifactory.server('mcp-ci')
+def git = new com.mirantis.mk.Git()
+def releaseWorkflow = new com.mirantis.mk.ReleaseWorkflow()
+
+// imageList = env.IMAGE_LIST ?: ''
+slaveNode = env.SLAVE_NODE ?: 'python'
+
+timeout(time: 4, unit: 'HOURS') {
+ node(slaveNode) {
+ def user = jenkinsUtils.currentUsername()
+ currentBuild.description = "${user}: [${env.SOURCE_IMAGE_TAG} => ${env.IMAGE_TAG}]\n${env.IMAGE_LIST}"
+ try {
+ allowedGroups = ['release-engineering']
+ releaseTags = ['proposed', 'release', '2018', '2019', '2020']
+ tags = [env.SOURCE_IMAGE_TAG, env.IMAGE_TAG]
+ tagInRelease = tags.any { tag -> releaseTags.any { tag.contains(it) } }
+ if (tagInRelease) {
+ if (!jenkinsUtils.currentUserInGroups(allowedGroups)) {
+ throw new Exception("You - ${user} - don't have permissions to run this job with tags ${tags}!")
+ } else {
+ echo "User `${user}` belongs to one of groups `${allowedGroups}`. Proceeding..."
+ }
+ }
+ stage('Mirror Docker Images') {
+ def images = IMAGE_LIST.tokenize('\n')
+ for (image in images) {
+ lengthImageName = image.tokenize('/').size()
+ if (lengthImageName <= 3) {
+ error("Image ${sourceImage} contains very short path")
+ }
+ String src = ''
+ String dst = ''
+ def (sourceImage, sourceTag) = image.trim().tokenize(':')
+ def (sourceRegistry, namespace, componentNamespace) = image.tokenize('/')
+ String componentNamespace = sourceImage.tokenize('/')[-(lengthImageName - 3)..-2].join('/')
+
+ if (!registryRegex.matcher(sourceRegistry).find() || !namespaceRegex.matcher(namespace).find() || !componentRegex.matcher(component)) {
+ error ("Image ${sourceImage} contains wrong data in path/URL")
+ }
+ if (env.IMAGE_TAG) {
+ targetTag = env.IMAGE_TAG
+ } else {
+ targetTag = sourceTag
+ }
+ String sourceDockerRepo = sourceRegistry.split(/\./)[0]
+ if (sourceDockerRepo.contains('dev-kaas')) {
+ src = 'dev-'
+ dst = ''
+ } else {
+ src = 'dev'
+ dst = 'prod'
+ }
+ String targetDockerRepo = sourceDockerRepo.replaceAll("${src}", "${dst}")
+ String targetImage = sourceImage.replaceAll("${src}", "${dst}")
+ String targetRegistryUrl = sourceRegistry.replaceAll("${src}", "${dst}")
+ String imageRepo = targetImage - targetRegistryUrl
+ 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)
+ }
+
+ if (targetImage.contains(externalMarker)) {
+ external = true
+ // check if images exists - raise error, as we don't want to rewrite existing one
+ // http://artifactory.mcp.mirantis.net/test-prod-openstack-docker/mysql/5.6/manifest.json
+ if (artifactory.imageExists(targetRegistryUrl, "${imageRepo}", targetTag)) {
+ echo "Image ${targetImage} already exists!"
+ continue
+ }
+ }
+ common.infoMsg("Attempt to push docker image into remote registry: ${env.REGISTRY_URL}")
+ common.retry(3, 5) {
+ artifactory.promoteDockerArtifact(artifactoryServer.getUrl(),
+ sourceDockerRepo,
+ targetDockerRepo,
+ imageRepo,
+ sourceTag,
+ targetTag,
+ true)
+ }
+ }
+ }
+ } catch (Throwable e) {
+ // Stub for future processing
+ currentBuild.result = 'FAILURE'
+ throw e
+ }
+ }
+}