blob: 1f2032589d440728d01e9d35c9cf826a03b8433f [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 }
81 for (int i = 0; i < properties.size(); i++) {
82 // avoid serialization errors
83 key = properties.entrySet().toArray()[i].key
84 value = properties.entrySet().toArray()[i].value
85 properties_str += "${key}=${value}|"
86 }
87 def url = "${artifactUrl}?${properties_str}&${recursive}"
88 withCredentials([
89 [$class : 'UsernamePasswordMultiBinding',
90 credentialsId : 'artifactory',
91 passwordVariable: 'ARTIFACTORY_PASSWORD',
92 usernameVariable: 'ARTIFACTORY_LOGIN']
93 ]) {
94 sh "bash -c \"curl -X PUT -u ${ARTIFACTORY_LOGIN}:${ARTIFACTORY_PASSWORD} \'${url}\'\""
95 }
96}
97
98/**
99 * Get properties for specified artifact in Artifactory
100 * Returns LinkedHashMap of properties
101 *
102 * @param artifactUrl String, an URL to artifact in Artifactory repo
103 */
104def getPropertiesForArtifact(String artifactUrl) {
105 def url = "${artifactUrl}?properties"
106 def result
107 withCredentials([
108 [$class : 'UsernamePasswordMultiBinding',
109 credentialsId : 'artifactory',
110 passwordVariable: 'ARTIFACTORY_PASSWORD',
111 usernameVariable: 'ARTIFACTORY_LOGIN']
112 ]) {
113 result = sh(script: "bash -c \"curl -X GET -u ${ARTIFACTORY_LOGIN}:${ARTIFACTORY_PASSWORD} \'${url}\'\"",
114 returnStdout: true).trim()
115 }
116 def properties = new groovy.json.JsonSlurperClassic().parseText(result)
117 return properties.get("properties")
118}
119
120/**
Denis Egorenko7c0abfe2017-02-14 15:42:02 +0400121 * Find docker images by tag
122 * Returns Array of image' hashes with names as full path in @repo
123 *
124 * Example:
125 *
126 * [ {
127 * "path" : "mirantis/ccp/ci-cd/gerrit-manage/test"
128 * },
129 * {
130 * "path" : "mirantis/ccp/ci-cd/gerrit/test"
131 * }
132 * ]
133 *
134 * @param artifactoryURL String, an URL to Artifactory
135 * @param repo String, a name of repo where should be executed search
136 * @param tag String, tag of searched image
137 */
138def getImagesByTag(String artifactoryURL, String repo, String tag) {
139 def url = "${artifactoryURL}/api/search/aql"
140 def result
141 writeFile file: "query",
142 text: """\
143 items.find(
144 {
145 \"repo\": \"${repo}\",
146 \"@docker.manifest\": { \"\$match\" : \"${tag}*\" }
147 }
148 ).
149 include(\"path\")
150 """.stripIndent()
151 withCredentials([
152 [$class: 'UsernamePasswordMultiBinding',
153 credentialsId: 'artifactory',
154 passwordVariable: 'ARTIFACTORY_PASSWORD',
155 usernameVariable: 'ARTIFACTORY_LOGIN']
156 ]) {
157 result = sh(script: "bash -c \"curl -X POST -u ${ARTIFACTORY_LOGIN}:${ARTIFACTORY_PASSWORD} -d @query \'${url}\'\"",
158 returnStdout: true).trim()
159 }
160 def images = new groovy.json.JsonSlurperClassic().parseText(result)
161 return images.get("results")
162}
163
164/**
Ruslan Kamaldinov90d4e672016-11-11 18:31:00 +0300165 * Upload docker image to Artifactory
166 *
Sergey Kulanov8cd6d222016-11-17 13:42:47 +0200167 * @param server ArtifactoryServer, the instance of Artifactory server
Ruslan Kamaldinov90d4e672016-11-11 18:31:00 +0300168 * @param registry String, the name of Docker registry
169 * @param image String, Docker image name
170 * @param version String, Docker image version
171 * @param repository String, The name of Artifactory Docker repository
Sergey Kulanov8cd6d222016-11-17 13:42:47 +0200172 * @param buildInfo BuildInfo, the instance of a build-info object which can be published,
173 * if defined, then we publish BuildInfo
Ruslan Kamaldinov90d4e672016-11-11 18:31:00 +0300174 */
Sergey Kulanov8cd6d222016-11-17 13:42:47 +0200175def uploadImageToArtifactory (ArtifactoryServer server, String registry, String image,
176 String version, String repository,
Dmitry Burmistrov6ee39522017-05-22 12:46:25 +0400177 BuildInfo buildInfo = null,
178 LinkedHashMap properties = null) {
Denis Egorenkoedba5a52016-11-15 19:55:56 +0300179 // TODO Switch to Artifactoy image' pushing mechanism once we will
180 // prepare automatical way for enabling artifactory build-proxy
181 //def artDocker
Ruslan Kamaldinov90d4e672016-11-11 18:31:00 +0300182 withCredentials([
183 [$class: 'UsernamePasswordMultiBinding',
184 credentialsId: 'artifactory',
185 passwordVariable: 'ARTIFACTORY_PASSWORD',
186 usernameVariable: 'ARTIFACTORY_LOGIN']
187 ]) {
188 sh ("docker login -u ${ARTIFACTORY_LOGIN} -p ${ARTIFACTORY_PASSWORD} ${registry}")
Ruslan Kamaldinov90d4e672016-11-11 18:31:00 +0300189 //artDocker = Artifactory.docker("${env.ARTIFACTORY_LOGIN}", "${env.ARTIFACTORY_PASSWORD}")
190 }
191
Denis Egorenkoedba5a52016-11-15 19:55:56 +0300192 sh ("docker push ${registry}/${image}:${version}")
Ruslan Kamaldinov90d4e672016-11-11 18:31:00 +0300193 //artDocker.push("${registry}/${image}:${version}", "${repository}")
Sergey Kulanov8cd6d222016-11-17 13:42:47 +0200194 def image_url = server.getUrl() + "/api/storage/${repository}/${image}/${version}"
Dmitry Burmistrov6ee39522017-05-22 12:46:25 +0400195 if ( ! properties ) {
196 properties = [
Sergey Kulanovc70f1c22016-11-16 13:05:20 +0200197 'com.mirantis.buildName':"${env.JOB_NAME}",
198 'com.mirantis.buildNumber': "${env.BUILD_NUMBER}",
199 'com.mirantis.gerritProject': "${env.GERRIT_PROJECT}",
200 'com.mirantis.gerritChangeNumber': "${env.GERRIT_CHANGE_NUMBER}",
201 'com.mirantis.gerritPatchsetNumber': "${env.GERRIT_PATCHSET_NUMBER}",
202 'com.mirantis.gerritChangeId': "${env.GERRIT_CHANGE_ID}",
203 'com.mirantis.gerritPatchsetRevision': "${env.GERRIT_PATCHSET_REVISION}",
Sergey Kulanov4d3951c2016-11-24 13:58:15 +0200204 'com.mirantis.targetImg': "${image}",
Sergey Kulanovc70f1c22016-11-16 13:05:20 +0200205 'com.mirantis.targetTag': "${version}"
Dmitry Burmistrov6ee39522017-05-22 12:46:25 +0400206 ]
207 }
Ruslan Kamaldinov90d4e672016-11-11 18:31:00 +0300208
209 setProperties(image_url, properties)
Sergey Kulanov8cd6d222016-11-17 13:42:47 +0200210
211 if ( buildInfo != null ) {
212 buildInfo.env.capture = true
213 buildInfo.env.filter.addInclude("*")
214 buildInfo.env.filter.addExclude("*PASSWORD*")
215 buildInfo.env.filter.addExclude("*password*")
216 buildInfo.env.collect()
217 server.publishBuildInfo(buildInfo)
218 }
Ruslan Kamaldinov90d4e672016-11-11 18:31:00 +0300219}
220
221/**
222 * Upload binaries to Artifactory
223 *
224 * @param server ArtifactoryServer, the instance of Artifactory server
225 * @param buildInfo BuildInfo, the instance of a build-info object which can be published
226 * @param uploadSpec String, a spec which is a JSON file that specifies which files should be
227 * uploaded or downloaded and the target path
228 * @param publishInfo Boolean, whether publish a build-info object to Artifactory
229 */
Sergey Kulanov91d8def2016-11-15 13:53:17 +0200230def uploadBinariesToArtifactory (ArtifactoryServer server, BuildInfo buildInfo, String uploadSpec,
231 Boolean publishInfo = false) {
Ruslan Kamaldinov90d4e672016-11-11 18:31:00 +0300232 buildInfo.append(server.upload(uploadSpec))
233
234 if ( publishInfo ) {
235 buildInfo.env.capture = true
236 buildInfo.env.filter.addInclude("*")
237 buildInfo.env.filter.addExclude("*PASSWORD*")
238 buildInfo.env.filter.addExclude("*password*")
239 buildInfo.env.collect()
Ruslan Kamaldinov90d4e672016-11-11 18:31:00 +0300240 server.publishBuildInfo(buildInfo)
241 }
242}
243
244/**
245 * Promote Docker image artifact to release repo
246 *
247 * @param artifactoryURL String, an URL to Artifactory
248 * @param artifactoryDevRepo String, the source dev repository name
249 * @param artifactoryProdRepo String, the target repository for the move or copy
250 * @param dockerRepo String, the docker repository name to promote
251 * @param artifactTag String, an image tag name to promote
252 * @param targetTag String, target tag to assign the image after promotion
253 * @param copy Boolean, an optional value to set whether to copy instead of move
254 * Default: false
255 */
256def promoteDockerArtifact(String artifactoryURL, String artifactoryDevRepo,
257 String artifactoryProdRepo, String dockerRepo,
258 String artifactTag, String targetTag, Boolean copy = false) {
259 def url = "${artifactoryURL}/api/docker/${artifactoryDevRepo}/v2/promote"
260 writeFile file: "query.json",
261 text: """{
262 \"targetRepo\": \"${artifactoryProdRepo}\",
263 \"dockerRepository\": \"${dockerRepo}\",
264 \"tag\": \"${artifactTag}\",
265 \"targetTag\" : \"${targetTag}\",
266 \"copy\": \"${copy}\"
267 }""".stripIndent()
268 sh "cat query.json"
269 withCredentials([
270 [$class : 'UsernamePasswordMultiBinding',
271 credentialsId : 'artifactory',
272 passwordVariable: 'ARTIFACTORY_PASSWORD',
273 usernameVariable: 'ARTIFACTORY_LOGIN']
274 ]) {
275 sh "bash -c \"curl -u ${ARTIFACTORY_LOGIN}:${ARTIFACTORY_PASSWORD} -H \"Content-Type:application/json\" -X POST -d @query.json ${url}\""
276 }
277}