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