blob: 025ac7d075593583560181d4014d50088d8683f2 [file] [log] [blame]
Ruslan Kamaldinov90d4e672016-11-11 18:31:00 +03001package com.mirantis.mcp
2
Sergey Kulanov91d8def2016-11-15 13:53:17 +02003import org.jfrog.hudson.pipeline.types.ArtifactoryServer
4import org.jfrog.hudson.pipeline.types.buildInfo.BuildInfo
5
Ruslan Kamaldinov90d4e672016-11-11 18:31:00 +03006/**
7 * Return string of mandatory build properties for binaries
8 * User can also add some custom properties.
9 *
10 * @param customProperties a Array of Strings that should be added to mandatory props
11 * in format ["prop1=value1", "prop2=value2"]
12 * */
13def getBinaryBuildProperties(ArrayList customProperties) {
14 def namespace = "com.mirantis."
15 def properties = [
Sergey Kulanovc70f1c22016-11-16 13:05:20 +020016 "buildName=${env.JOB_NAME}",
17 "buildNumber=${env.BUILD_NUMBER}",
Ruslan Kamaldinov90d4e672016-11-11 18:31:00 +030018 "gerritProject=${env.GERRIT_PROJECT}",
19 "gerritChangeNumber=${env.GERRIT_CHANGE_NUMBER}",
20 "gerritPatchsetNumber=${env.GERRIT_PATCHSET_NUMBER}",
21 "gerritChangeId=${env.GERRIT_CHANGE_ID}",
22 "gerritPatchsetRevision=${env.GERRIT_PATCHSET_REVISION}"
23 ]
24
25 if (customProperties) {
26 properties.addAll(customProperties)
27 }
28
29 def common = new com.mirantis.mcp.Common()
30
31 return common.constructString(properties, namespace, ";")
32}
33
34/**
35 * Get URL to artifact by properties
36 * Returns String with URL to found artifact or null if nothing
37 *
38 * @param artifactoryURL String, an URL to Artifactory
39 * @param properties LinkedHashMap, a Hash of properties (key-value) which
40 * which should determine artifact in Artifactory
41 */
42def uriByProperties(String artifactoryURL, LinkedHashMap properties) {
43 def key, value
44 def properties_str = ''
45 for (int i = 0; i < properties.size(); i++) {
46 // avoid serialization errors
47 key = properties.entrySet().toArray()[i].key
48 value = properties.entrySet().toArray()[i].value
49 properties_str += "${key}=${value}&"
50 }
51 def search_url = "${artifactoryURL}/api/search/prop?${properties_str}"
52
53 def result = sh(script: "bash -c \"curl -X GET \'${search_url}\'\"",
54 returnStdout: true).trim()
55 def content = new groovy.json.JsonSlurperClassic().parseText(result)
56 def uri = content.get("results")
57 if (uri) {
58 return uri.last().get("uri")
59 } else {
60 return null
61 }
62}
63
64/**
Ruslan Kamaldinov90d4e672016-11-11 18:31:00 +030065 * Set properties for artifact in Artifactory repo
66 *
67 * @param artifactUrl String, an URL to artifact in Artifactory repo
68 * @param properties LinkedHashMap, a Hash of properties (key-value) which
69 * should be assigned for choosen artifact
70 * @param recursive Boolean, if artifact_url is a directory, whether to set
71 * properties recursively or not
72 */
73def setProperties(String artifactUrl, LinkedHashMap properties, Boolean recursive = false) {
74 def properties_str = 'properties='
75 def key, value
76 if (recursive) {
77 recursive = 'recursive=1'
78 } else {
79 recursive = 'recursive=0'
80 }
Alexander Evseevbd40ef92017-10-18 12:24:45 +030081 properties_str += properties.collect({"${it.key}=${it.value}"}).join(';')
Ruslan Kamaldinov90d4e672016-11-11 18:31:00 +030082 def url = "${artifactUrl}?${properties_str}&${recursive}"
83 withCredentials([
84 [$class : 'UsernamePasswordMultiBinding',
85 credentialsId : 'artifactory',
86 passwordVariable: 'ARTIFACTORY_PASSWORD',
87 usernameVariable: 'ARTIFACTORY_LOGIN']
88 ]) {
89 sh "bash -c \"curl -X PUT -u ${ARTIFACTORY_LOGIN}:${ARTIFACTORY_PASSWORD} \'${url}\'\""
90 }
91}
92
93/**
94 * Get properties for specified artifact in Artifactory
95 * Returns LinkedHashMap of properties
96 *
97 * @param artifactUrl String, an URL to artifact in Artifactory repo
98 */
99def getPropertiesForArtifact(String artifactUrl) {
100 def url = "${artifactUrl}?properties"
101 def result
102 withCredentials([
103 [$class : 'UsernamePasswordMultiBinding',
104 credentialsId : 'artifactory',
105 passwordVariable: 'ARTIFACTORY_PASSWORD',
106 usernameVariable: 'ARTIFACTORY_LOGIN']
107 ]) {
108 result = sh(script: "bash -c \"curl -X GET -u ${ARTIFACTORY_LOGIN}:${ARTIFACTORY_PASSWORD} \'${url}\'\"",
109 returnStdout: true).trim()
110 }
111 def properties = new groovy.json.JsonSlurperClassic().parseText(result)
112 return properties.get("properties")
113}
114
115/**
Denis Egorenko7c0abfe2017-02-14 15:42:02 +0400116 * Find docker images by tag
117 * Returns Array of image' hashes with names as full path in @repo
118 *
119 * Example:
120 *
121 * [ {
122 * "path" : "mirantis/ccp/ci-cd/gerrit-manage/test"
123 * },
124 * {
125 * "path" : "mirantis/ccp/ci-cd/gerrit/test"
126 * }
127 * ]
128 *
129 * @param artifactoryURL String, an URL to Artifactory
130 * @param repo String, a name of repo where should be executed search
131 * @param tag String, tag of searched image
132 */
133def getImagesByTag(String artifactoryURL, String repo, String tag) {
134 def url = "${artifactoryURL}/api/search/aql"
135 def result
136 writeFile file: "query",
137 text: """\
138 items.find(
139 {
140 \"repo\": \"${repo}\",
141 \"@docker.manifest\": { \"\$match\" : \"${tag}*\" }
142 }
143 ).
144 include(\"path\")
145 """.stripIndent()
146 withCredentials([
147 [$class: 'UsernamePasswordMultiBinding',
148 credentialsId: 'artifactory',
149 passwordVariable: 'ARTIFACTORY_PASSWORD',
150 usernameVariable: 'ARTIFACTORY_LOGIN']
151 ]) {
152 result = sh(script: "bash -c \"curl -X POST -u ${ARTIFACTORY_LOGIN}:${ARTIFACTORY_PASSWORD} -d @query \'${url}\'\"",
153 returnStdout: true).trim()
154 }
155 def images = new groovy.json.JsonSlurperClassic().parseText(result)
156 return images.get("results")
157}
158
159/**
Ruslan Kamaldinov90d4e672016-11-11 18:31:00 +0300160 * Upload docker image to Artifactory
161 *
Sergey Kulanov8cd6d222016-11-17 13:42:47 +0200162 * @param server ArtifactoryServer, the instance of Artifactory server
Ruslan Kamaldinov90d4e672016-11-11 18:31:00 +0300163 * @param registry String, the name of Docker registry
164 * @param image String, Docker image name
165 * @param version String, Docker image version
166 * @param repository String, The name of Artifactory Docker repository
Sergey Kulanov8cd6d222016-11-17 13:42:47 +0200167 * @param buildInfo BuildInfo, the instance of a build-info object which can be published,
168 * if defined, then we publish BuildInfo
Ruslan Kamaldinov90d4e672016-11-11 18:31:00 +0300169 */
Sergey Kulanov8cd6d222016-11-17 13:42:47 +0200170def uploadImageToArtifactory (ArtifactoryServer server, String registry, String image,
171 String version, String repository,
Dmitry Burmistrov6ee39522017-05-22 12:46:25 +0400172 BuildInfo buildInfo = null,
173 LinkedHashMap properties = null) {
Denis Egorenkoedba5a52016-11-15 19:55:56 +0300174 // TODO Switch to Artifactoy image' pushing mechanism once we will
175 // prepare automatical way for enabling artifactory build-proxy
176 //def artDocker
Ruslan Kamaldinov90d4e672016-11-11 18:31:00 +0300177 withCredentials([
178 [$class: 'UsernamePasswordMultiBinding',
179 credentialsId: 'artifactory',
180 passwordVariable: 'ARTIFACTORY_PASSWORD',
181 usernameVariable: 'ARTIFACTORY_LOGIN']
182 ]) {
183 sh ("docker login -u ${ARTIFACTORY_LOGIN} -p ${ARTIFACTORY_PASSWORD} ${registry}")
Ruslan Kamaldinov90d4e672016-11-11 18:31:00 +0300184 //artDocker = Artifactory.docker("${env.ARTIFACTORY_LOGIN}", "${env.ARTIFACTORY_PASSWORD}")
185 }
186
Denis Egorenkoedba5a52016-11-15 19:55:56 +0300187 sh ("docker push ${registry}/${image}:${version}")
Ruslan Kamaldinov90d4e672016-11-11 18:31:00 +0300188 //artDocker.push("${registry}/${image}:${version}", "${repository}")
Sergey Kulanov8cd6d222016-11-17 13:42:47 +0200189 def image_url = server.getUrl() + "/api/storage/${repository}/${image}/${version}"
Dmitry Burmistrov6ee39522017-05-22 12:46:25 +0400190 if ( ! properties ) {
191 properties = [
Sergey Kulanovc70f1c22016-11-16 13:05:20 +0200192 'com.mirantis.buildName':"${env.JOB_NAME}",
193 'com.mirantis.buildNumber': "${env.BUILD_NUMBER}",
194 'com.mirantis.gerritProject': "${env.GERRIT_PROJECT}",
195 'com.mirantis.gerritChangeNumber': "${env.GERRIT_CHANGE_NUMBER}",
196 'com.mirantis.gerritPatchsetNumber': "${env.GERRIT_PATCHSET_NUMBER}",
197 'com.mirantis.gerritChangeId': "${env.GERRIT_CHANGE_ID}",
198 'com.mirantis.gerritPatchsetRevision': "${env.GERRIT_PATCHSET_REVISION}",
Sergey Kulanov4d3951c2016-11-24 13:58:15 +0200199 'com.mirantis.targetImg': "${image}",
Sergey Kulanovc70f1c22016-11-16 13:05:20 +0200200 'com.mirantis.targetTag': "${version}"
Dmitry Burmistrov6ee39522017-05-22 12:46:25 +0400201 ]
202 }
Ruslan Kamaldinov90d4e672016-11-11 18:31:00 +0300203
204 setProperties(image_url, properties)
Sergey Kulanov8cd6d222016-11-17 13:42:47 +0200205
206 if ( buildInfo != null ) {
207 buildInfo.env.capture = true
208 buildInfo.env.filter.addInclude("*")
209 buildInfo.env.filter.addExclude("*PASSWORD*")
210 buildInfo.env.filter.addExclude("*password*")
211 buildInfo.env.collect()
212 server.publishBuildInfo(buildInfo)
213 }
Ruslan Kamaldinov90d4e672016-11-11 18:31:00 +0300214}
215
216/**
217 * Upload binaries to Artifactory
218 *
219 * @param server ArtifactoryServer, the instance of Artifactory server
220 * @param buildInfo BuildInfo, the instance of a build-info object which can be published
221 * @param uploadSpec String, a spec which is a JSON file that specifies which files should be
222 * uploaded or downloaded and the target path
223 * @param publishInfo Boolean, whether publish a build-info object to Artifactory
224 */
Sergey Kulanov91d8def2016-11-15 13:53:17 +0200225def uploadBinariesToArtifactory (ArtifactoryServer server, BuildInfo buildInfo, String uploadSpec,
226 Boolean publishInfo = false) {
Jakub Josefbefcf6c2017-11-14 18:03:10 +0100227 server.upload(uploadSpec, buildInfo)
Ruslan Kamaldinov90d4e672016-11-11 18:31:00 +0300228
229 if ( publishInfo ) {
230 buildInfo.env.capture = true
231 buildInfo.env.filter.addInclude("*")
232 buildInfo.env.filter.addExclude("*PASSWORD*")
233 buildInfo.env.filter.addExclude("*password*")
234 buildInfo.env.collect()
Ruslan Kamaldinov90d4e672016-11-11 18:31:00 +0300235 server.publishBuildInfo(buildInfo)
236 }
237}
238
239/**
240 * Promote Docker image artifact to release repo
241 *
242 * @param artifactoryURL String, an URL to Artifactory
243 * @param artifactoryDevRepo String, the source dev repository name
244 * @param artifactoryProdRepo String, the target repository for the move or copy
245 * @param dockerRepo String, the docker repository name to promote
246 * @param artifactTag String, an image tag name to promote
247 * @param targetTag String, target tag to assign the image after promotion
248 * @param copy Boolean, an optional value to set whether to copy instead of move
249 * Default: false
250 */
251def promoteDockerArtifact(String artifactoryURL, String artifactoryDevRepo,
252 String artifactoryProdRepo, String dockerRepo,
253 String artifactTag, String targetTag, Boolean copy = false) {
254 def url = "${artifactoryURL}/api/docker/${artifactoryDevRepo}/v2/promote"
Dmitry Burmistrov5deaa7d2017-05-30 17:12:54 +0400255 String queryFile = UUID.randomUUID().toString()
Dmitry Burmistrov97beb9b2017-05-29 17:21:34 +0400256 writeFile file: queryFile,
Ruslan Kamaldinov90d4e672016-11-11 18:31:00 +0300257 text: """{
258 \"targetRepo\": \"${artifactoryProdRepo}\",
259 \"dockerRepository\": \"${dockerRepo}\",
260 \"tag\": \"${artifactTag}\",
261 \"targetTag\" : \"${targetTag}\",
262 \"copy\": \"${copy}\"
263 }""".stripIndent()
Dmitry Burmistrov97beb9b2017-05-29 17:21:34 +0400264 sh "cat ${queryFile}"
Ruslan Kamaldinov90d4e672016-11-11 18:31:00 +0300265 withCredentials([
266 [$class : 'UsernamePasswordMultiBinding',
267 credentialsId : 'artifactory',
268 passwordVariable: 'ARTIFACTORY_PASSWORD',
269 usernameVariable: 'ARTIFACTORY_LOGIN']
270 ]) {
Dmitry Burmistrov97beb9b2017-05-29 17:21:34 +0400271 sh "bash -c \"curl -u ${ARTIFACTORY_LOGIN}:${ARTIFACTORY_PASSWORD} -H \"Content-Type:application/json\" -X POST -d @${queryFile} ${url}\""
Ruslan Kamaldinov90d4e672016-11-11 18:31:00 +0300272 }
Dmitry Burmistrov97beb9b2017-05-29 17:21:34 +0400273 sh "rm -v ${queryFile}"
Ruslan Kamaldinov90d4e672016-11-11 18:31:00 +0300274}