blob: 565232fb359176d383dee1acfdadd211f896df42 [file] [log] [blame]
Sergey Kulanov1bbd3612016-09-30 11:40:11 +03001package ci.mcp
2
3/**
Ruslan Kamaldinov90d4e672016-11-11 18:31:00 +03004* Please do not add new functions to this file. Add them to corresponding
5* files in com/mirantis/mcp instead.
6**/
7
8/**
Sergey Kulanov1bbd3612016-09-30 11:40:11 +03009 * https://issues.jenkins-ci.org/browse/JENKINS-26481
10 * fix groovy List.collect()
Sergey Kulanov56d0d052016-10-13 15:48:56 +030011**/
12@NonCPS
13def constructString(ArrayList options, String keyOption, String separator = " ") {
14 return options.collect{ keyOption + it }.join(separator).replaceAll("\n", "")
15}
16
17/**
Sergey Kulanov1bbd3612016-09-30 11:40:11 +030018 * Build command line options, e.g:
19 * cmd_opts=["a=b", "c=d", "e=f"]
20 * key = "--build-arg "
21 * separator = " "
22 * def options = getCommandBuilder(cmd_opts, key, separator)
23 * println options
24 * > --build-arg a=b --build-arg c=d --build-arg e=f
25 *
26 * @param options List of Strings (options that should be populated)
27 * @param keyOption key that should be added before each option
28 * @param separator Separator between key+Option pairs
29 */
Sergey Kulanov1bbd3612016-09-30 11:40:11 +030030def getCommandBuilder(ArrayList options, String keyOption, String separator = " ") {
Sergey Kulanov56d0d052016-10-13 15:48:56 +030031 return constructString(options, keyOption)
32}
33
34/**
Sergey Kulanov20c8b132016-11-02 13:24:32 +020035* Add LABEL to the end of the Dockerfile
36* User can also add some custom properties
37*
38* @param dockerfilePath is the path to Dockerfile, the default is ./Dockerfile
39* @param customProperties a Array of Strings that should be added to mandatory props
40* in format ["prop1=value1", "prop2=value2"]
41**/
42def setDockerfileLabels(String dockerfilePath = "./Dockerfile", ArrayList customProperties = null){
43
44 if (!fileExists(dockerfilePath)){
45 throw new RuntimeException("Unable to add LABEL to Dockerfile, ${dockerfilePath} doesn't exists")
46 }
47 echo "Updating ${dockerfilePath}"
48
49 def namespace = "com.mirantis.image-specs."
50 def properties = [
51 "gerritProject=${env.GERRIT_PROJECT}",
52 "gerritChangeNumber=${env.GERRIT_CHANGE_NUMBER}",
53 "gerritPatchsetNumber=${env.GERRIT_PATCHSET_NUMBER}",
54 "gerritChangeId=${env.GERRIT_CHANGE_ID}",
55 "gerritPatchsetRevision=${env.GERRIT_PATCHSET_REVISION}"
56 ]
57
58 if (customProperties != null){
59 properties.addAll(customProperties)
60 }
61
62 def metadata = constructString(properties, namespace, " ")
63 sh """
64 cat <<EOF>> ${dockerfilePath}
65 # Apply additional build metadata
66 LABEL ${metadata}
67 """
68 return metadata
69}
70
71/**
Sergey Kulanov56d0d052016-10-13 15:48:56 +030072* Return string of mandatory build properties for binaries
73* User can also add some custom properties
74*
75* @param customProperties a Array of Strings that should be added to mandatory props
76* in format ["prop1=value1", "prop2=value2"]
77**/
78def getBinaryBuildProperties(ArrayList customProperties) {
79
80 def namespace = "com.mirantis."
81 def properties = [
82 "gerritProject=${env.GERRIT_PROJECT}",
83 "gerritChangeNumber=${env.GERRIT_CHANGE_NUMBER}",
84 "gerritPatchsetNumber=${env.GERRIT_PATCHSET_NUMBER}",
85 "gerritChangeId=${env.GERRIT_CHANGE_ID}",
Sergey Kulanov64bc88a2016-10-18 16:26:34 +030086 "gerritPatchsetRevision=${env.GERRIT_PATCHSET_REVISION}"
Sergey Kulanov56d0d052016-10-13 15:48:56 +030087 ]
88
89 if (customProperties){
90 properties.addAll(customProperties)
91 }
92
93 return constructString(properties, namespace, ";")
Sergey Kulanov1bbd3612016-09-30 11:40:11 +030094}
Sergey Kulanov1835afe2016-10-19 16:53:14 +030095
96/**
97 * Parse HEAD of current directory and return commit hash
98 */
99def getGitCommit() {
100 git_commit = sh (
101 script: 'git rev-parse HEAD',
102 returnStdout: true
103 ).trim()
104 return git_commit
105}
Denis Egorenkoe3552682016-10-18 13:29:29 +0300106
107/**
Alexander Saprykinb28156c2016-11-09 11:09:48 +0100108 * Describe a commit using the most recent tag reachable from it
109 */
110def getGitDescribe() {
111 git_commit = sh (
112 script: 'git describe --tags',
113 returnStdout: true
114 ).trim()
115 return git_commit
116}
117
118/**
Sergey Kulanov4f2fbcb2016-10-28 14:25:20 +0300119 * Generate current timestamp
120 *
121 * @param format Defaults to yyyyMMddHHmmss
122 */
123def getDatetime(format="yyyyMMddHHmmss") {
124 def now = new Date();
125 return now.format(format, TimeZone.getTimeZone('UTC'));
126}
127
128/**
Denis Egorenkoe3552682016-10-18 13:29:29 +0300129* Get URL to artifact by properties
130* Returns String with URL to found artifact or null if nothing
131*
132* @param artifactoryURL String, an URL to Artifactory
133* @param properties LinkedHashMap, a Hash of properties (key-value) which
134* which should determine artifact in Artifactory
135*/
136def uriByProperties(String artifactoryURL, LinkedHashMap properties) {
137 def key, value
138 def properties_str = ''
139 for ( int i = 0; i < properties.size(); i++ ) {
140 // avoid serialization errors
141 key = properties.entrySet().toArray()[i].key
142 value = properties.entrySet().toArray()[i].value
143 properties_str += "${key}=${value}&"
144 }
145 def search_url = "${artifactoryURL}/api/search/prop?${properties_str}"
146
147 def result = sh(script: "bash -c \"curl -X GET \'${search_url}\'\"",
148 returnStdout: true).trim()
149 def content = new groovy.json.JsonSlurperClassic().parseText(result)
150 def uri = content.get("results")
151 if ( uri ) {
152 return uri.last().get("uri")
153 } else {
154 return null
155 }
156}
157
158/**
Sergey Kulanovd4e31282016-11-08 17:39:19 +0200159* Get URL to artifact by properties
160* Returns String with URL to found artifact or null if nothing
161*
162* @param artifactoryURL String, an URL to Artifactory
163* @param properties String, URI in format prop1=val1&prop2=val2&prop3val3
164* which should determine artifact in Artifactory
165*/
166def uriByProperties(String artifactoryURL, String properties) {
167
168 def search_url = "${artifactoryURL}/api/search/prop?${properties}"
169
170 def result = sh(script: "bash -c \"curl -X GET \'${search_url}\'\"",
171 returnStdout: true).trim()
172 def content = new groovy.json.JsonSlurperClassic().parseText(result)
173 def uri = content.get("results")
174 if ( uri ) {
175 return uri.last().get("uri")
176 } else {
177 return null
178 }
179}
180
181/**
Denis Egorenkoe3552682016-10-18 13:29:29 +0300182* Set properties for artifact in Artifactory repo
183*
184* @param artifactUrl String, an URL to artifact in Artifactory repo
185* @param properties LinkedHashMap, a Hash of properties (key-value) which
186* should be assigned for choosen artifact
187* @param recursive Boolean, if artifact_url is a directory, whether to set
188* properties recursively or not
189*/
190def setProperties (String artifactUrl, LinkedHashMap properties, Boolean recursive=false) {
191 def properties_str = 'properties='
192 def key,value
193 if (recursive) {
194 recursive = 'recursive=1'
195 } else {
196 recursive = 'recursive=0'
197 }
198 for ( int i = 0; i < properties.size(); i++ ) {
199 // avoid serialization errors
200 key = properties.entrySet().toArray()[i].key
201 value = properties.entrySet().toArray()[i].value
202 properties_str += "${key}=${value}|"
203 }
204 def url = "${artifactUrl}?${properties_str}&${recursive}"
205 withCredentials([
206 [$class: 'UsernamePasswordMultiBinding',
207 credentialsId: 'artifactory',
208 passwordVariable: 'ARTIFACTORY_PASSWORD',
209 usernameVariable: 'ARTIFACTORY_LOGIN']
210 ]) {
211 sh "bash -c \"curl -X PUT -u ${ARTIFACTORY_LOGIN}:${ARTIFACTORY_PASSWORD} \'${url}\'\""
212 }
213}
214
215/**
216* Get properties for specified artifact in Artifactory
217* Returns LinkedHashMap of properties
218*
219* @param artifactUrl String, an URL to artifact in Artifactory repo
220*/
221def getPropertiesForArtifact(String artifactUrl) {
222 def url = "${artifactUrl}?properties"
223 def result
224 withCredentials([
225 [$class: 'UsernamePasswordMultiBinding',
226 credentialsId: 'artifactory',
227 passwordVariable: 'ARTIFACTORY_PASSWORD',
228 usernameVariable: 'ARTIFACTORY_LOGIN']
229 ]) {
230 result = sh(script: "bash -c \"curl -X GET -u ${ARTIFACTORY_LOGIN}:${ARTIFACTORY_PASSWORD} \'${url}\'\"",
231 returnStdout: true).trim()
232 }
233 def properties = new groovy.json.JsonSlurperClassic().parseText(result)
234 return properties.get("properties")
235}
236
237/**
238* Upload docker image to Artifactory
239*
240* @param artifactoryURL String, an URL to Artifactory
241* @param registry String, the name of Docker registry
242* @param image String, Docker image name
243* @param version String, Docker image version
244* @param repository String, The name of Artifactory Docker repository
245*/
246def uploadImageToArtifactory (String artifactoryURL, String registry, String image,
247 String version, String repository) {
248 // TODO Switch to Artifactoy image' pushing mechanism once we will
249 // prepare automatical way for enabling artifactory build-proxy
250 //def artDocker
251 withCredentials([
252 [$class: 'UsernamePasswordMultiBinding',
253 credentialsId: 'artifactory',
254 passwordVariable: 'ARTIFACTORY_PASSWORD',
255 usernameVariable: 'ARTIFACTORY_LOGIN']
256 ]) {
257 sh ("docker login -u ${ARTIFACTORY_LOGIN} -p ${ARTIFACTORY_PASSWORD} ${registry}")
258 //artDocker = Artifactory.docker("${env.ARTIFACTORY_LOGIN}", "${env.ARTIFACTORY_PASSWORD}")
259 }
260
261 sh ("docker push ${registry}/${image}:${version}")
262 //artDocker.push("${registry}/${image}:${version}", "${repository}")
263 def image_url = "${artifactoryURL}/api/storage/${repository}/${image}/${version}"
264
265 def properties = ['com.mirantis.build_name':"${env.JOB_NAME}",
266 'com.mirantis.build_id': "${env.BUILD_NUMBER}",
267 'com.mirantis.changeid': "${env.GERRIT_CHANGE_ID}",
268 'com.mirantis.patchset_number': "${env.GERRIT_PATCHSET_NUMBER}",
269 'com.mirantis.target_tag': "${version}"]
270 setProperties(image_url, properties)
271}
272
273/**
274* Upload binaries to Artifactory
275*
276* @param server ArtifactoryServer, the instance of Artifactory server
277* @param buildInfo BuildInfo, the instance of a build-info object which can be published
278* @param uploadSpec String, a spec which is a JSON file that specifies which files should be
279* uploaded or downloaded and the target path
280* @param publishInfo Boolean, whether publish a build-info object to Artifactory
281*/
282def uploadBinariesToArtifactory (server, buildInfo, String uploadSpec,
283 Boolean publishInfo=false) {
284 buildInfo.append(server.upload(uploadSpec))
285
286 if ( publishInfo ) {
287 buildInfo.env.capture = true
288 buildInfo.env.filter.addInclude("*")
289 buildInfo.env.filter.addExclude("*PASSWORD*")
290 buildInfo.env.filter.addExclude("*password*")
291 buildInfo.env.collect()
292 server.publishBuildInfo(buildInfo)
293 }
294}
295
296/**
297* Promote Docker image artifact to release repo
298*
299* @param artifactoryURL String, an URL to Artifactory
300* @param artifactoryDevRepo String, the source dev repository name
301* @param artifactoryProdRepo String, the target repository for the move or copy
302* @param dockerRepo String, the docker repository name to promote
303* @param artifactTag String, an image tag name to promote
304* @param targetTag String, target tag to assign the image after promotion
305* @param copy Boolean, an optional value to set whether to copy instead of move
306* Default: false
307*/
308def promoteDockerArtifact(String artifactoryURL, String artifactoryDevRepo,
309 String artifactoryProdRepo, String dockerRepo,
310 String artifactTag, String targetTag, Boolean copy=false) {
311 def url = "${artifactoryURL}/api/docker/${artifactoryDevRepo}/v2/promote"
312 writeFile file: "query.json",
313 text: """{
314 \"targetRepo\": \"${artifactoryProdRepo}\",
315 \"dockerRepository\": \"${dockerRepo}\",
316 \"tag\": \"${artifactTag}\",
317 \"targetTag\" : \"${targetTag}\",
318 \"copy\": \"${copy}\"
319 }""".stripIndent()
320 sh "cat query.json"
321 withCredentials([
322 [$class: 'UsernamePasswordMultiBinding',
323 credentialsId: 'artifactory',
324 passwordVariable: 'ARTIFACTORY_PASSWORD',
325 usernameVariable: 'ARTIFACTORY_LOGIN']
326 ]) {
327 sh "bash -c \"curl -u ${ARTIFACTORY_LOGIN}:${ARTIFACTORY_PASSWORD} -H \"Content-Type:application/json\" -X POST -d @query.json ${url}\""
328 }
329}