blob: acad991829392f47aa7343ee51cc6e09e38e4dd9 [file] [log] [blame]
Jakub Josef79ecec32017-02-17 14:36:28 +01001package com.mirantis.mk
2
3/**
4 *
5 * Aptly functions
6 *
7 */
8
9/**
10 * Upload package into local repo
11 *
12 * @param file File path
13 * @param server Server host
14 * @param repo Repository name
15 */
16def uploadPackage(file, server, repo, skipExists=false) {
17 def pkg = file.split('/')[-1].split('_')[0]
18 def jobName = currentBuild.build().environment.JOB_NAME
19
20 sh("curl -v -f -F file=@${file} ${server}/api/files/${pkg}")
21 sh("curl -v -o curl_out_${pkg}.log -f -X POST ${server}/api/repos/${repo}/file/${pkg}")
22
23 try {
24 sh("cat curl_out_${pkg}.log | json_pp | grep 'Unable to add package to repo' && exit 1 || exit 0")
25 } catch (err) {
26 sh("curl -s -f -X DELETE ${server}/api/files/${pkg}")
27 if (skipExists == true) {
28 println "[WARN] Package ${pkg} already exists in repo so skipping it's upload as requested"
29 } else {
30 error("Package ${pkg} already exists in repo, did you forget to add changelog entry and raise version?")
31 }
32 }
33}
34
35/**
36 * Build step to upload package. For use with eg. parallel
37 *
38 * @param file File path
39 * @param server Server host
40 * @param repo Repository name
41 */
42def uploadPackageStep(file, server, repo, skipExists=false) {
43 return {
44 uploadPackage(
45 file,
46 server,
47 repo,
48 skipExists
49 )
50 }
51}
52
53def snapshotRepo(server, repo, timestamp = null) {
54 // XXX: timestamp parameter is obsoleted, time of snapshot creation is
55 // what we should always use, not what calling pipeline provides
56 def now = new Date();
57 def ts = now.format("yyyyMMddHHmmss", TimeZone.getTimeZone('UTC'));
58
59 def snapshot = "${repo}-${ts}"
60 sh("curl -f -X POST -H 'Content-Type: application/json' --data '{\"Name\":\"$snapshot\"}' ${server}/api/repos/${repo}/snapshots")
61}
62
Richard Felkl80c1d372018-03-26 13:03:10 +020063/**
64 * Cleanup snapshots
65 *
66 * @param server Server host
67 * @param opts Options: debug, timeout, ...
68 */
69def cleanupSnapshots(server, opts='-d'){
70 sh("aptly-publisher --url ${server} ${opts} cleanup")
Jakub Josef79ecec32017-02-17 14:36:28 +010071}
72
73def diffPublish(server, source, target, components=null, opts='--timeout 600') {
74 if (components) {
75 def componentsStr = components.join(' ')
76 opts = "${opts} --components ${componentsStr}"
77 }
78 sh("aptly-publisher --dry --url ${server} promote --source ${source} --target ${target} --diff ${opts}")
79}
80
chnyda751ac402017-11-28 17:32:43 +010081def promotePublish(server, source, target, recreate=false, components=null, packages=null, diff=false, opts='-d --timeout 600', dump_publish=false, storage="") {
chnydabe46ffa2017-03-21 13:19:08 +010082 if (components && components != "all" && components != "") {
83 def componentsStr = components.replaceAll(",", " ")
Jakub Josef79ecec32017-02-17 14:36:28 +010084 opts = "${opts} --components ${componentsStr}"
85 }
chnydabe46ffa2017-03-21 13:19:08 +010086 if (packages && packages != "all" && packages != "") {
87 def packagesStr = packages.replaceAll(",", " ")
Jakub Josef79ecec32017-02-17 14:36:28 +010088 opts = "${opts} --packages ${packagesStr}"
89 }
90 if (recreate.toBoolean() == true) {
91 opts = "${opts} --recreate"
92 }
93 if (diff.toBoolean() == true) {
chnyda5de5d432017-04-10 15:35:47 +020094 opts = "${opts} --dry --diff"
Jakub Josef79ecec32017-02-17 14:36:28 +010095 }
chnydabe46ffa2017-03-21 13:19:08 +010096
chnyda751ac402017-11-28 17:32:43 +010097 if (storage && storage != "") {
98 opts = "${opts} --storage ${storage}"
99 }
100
chnyda4906ce02017-08-22 14:45:13 +0200101 if (dump_publish) {
102 def now = new Date();
chnydaf2f95792017-12-11 17:09:27 +0100103 dumpTarget = target
chnyda4906ce02017-08-22 14:45:13 +0200104 def timestamp = now.format("yyyyMMddHHmmss", TimeZone.getTimeZone('UTC'));
chnydaf2f95792017-12-11 17:09:27 +0100105
chnyda7bdfeab2017-12-18 17:10:14 +0100106 if (source.contains(')') || source.contains('*')) {
chnydaf2f95792017-12-11 17:09:27 +0100107 sourceTarget = source.split('/')
108 dumpTarget = target.split('/')[-1]
109 sourceTarget[-1] = dumpTarget
110 dumpTarget = sourceTarget.join('/')
111 }
112
113 dumpPublishes(server, timestamp, dumpTarget)
chnyda4906ce02017-08-22 14:45:13 +0200114 }
chnydac78dfa52017-08-22 14:39:43 +0200115
Jakub Josefa3a4db92018-04-12 11:50:20 +0000116 sh("aptly-publisher --url ${server} promote --acquire-by-hash --source '${source}' --target '${target}' --force-overwrite ${opts}")
chnydac78dfa52017-08-22 14:39:43 +0200117
Jakub Josef79ecec32017-02-17 14:36:28 +0100118}
119
Alexander Noskov18e1e4d2018-06-05 16:34:36 +0400120def publish(server, config='/etc/aptly/publisher.yaml', recreate=false, only_latest=true, force_overwrite=true, opts='-d --timeout 3600') {
Jakub Josef79ecec32017-02-17 14:36:28 +0100121 if (recreate == true) {
122 opts = "${opts} --recreate"
123 }
Filip Pytloun62fe3a42017-11-27 14:30:19 +0100124 if (only_latest == true) {
125 opts = "${opts} --only-latest"
126 }
127 if (force_overwrite == true) {
128 opts = "${opts} --force-overwrite"
129 }
chnydadc7292f2018-01-17 14:30:22 +0100130 sh("aptly-publisher --url ${server} -c ${config} ${opts} --acquire-by-hash publish")
chnydad8f51af2017-07-24 10:39:48 +0200131}
132
133/**
134 * Dump publishes
135 *
136 * @param server Server host
137 * @param save-dir Directory where publishes are to be serialized
138 * @param publishes Publishes to be serialized
139 * @param prefix Prefix of dump files
140 * @param opts Options: debug, timeout, ...
141 */
chnyda5fe91ca2017-09-19 09:19:46 +0200142def dumpPublishes(server, prefix, publishes='all', opts='-d --timeout 600') {
chnydaf2f95792017-12-11 17:09:27 +0100143 sh("aptly-publisher dump --url ${server} --save-dir . --prefix ${prefix} -p '${publishes}' ${opts}")
Jakub Josef30cf6502018-04-04 12:48:03 +0200144 if (findFiles(glob: "${prefix}*")) {
145 archiveArtifacts artifacts: "${prefix}*"
146 } else {
Jakub Joseff5c1bf42018-04-24 16:18:13 +0200147 def common = new com.mirantis.mk.Common()
148 common.warningMsg("Aptly dump publishes for a prefix ${prefix}* failed. No dump files found! This can be OK in case of your creating new publish")
Jakub Josef30cf6502018-04-04 12:48:03 +0200149 }
chnydad8f51af2017-07-24 10:39:48 +0200150}
151
152/**
153 * Restore publish from YAML file
154 *
155 * @param server Server host
156 * @param recreate Recreate publishes
157 * @param publish Serialized YAML of Publish
158 * @param components Components to restore
159 */
160def restorePublish(server, recreate, publish, components='all') {
161
162 opts = ""
163 if (recreate) {
164 opts << " --recreate"
165 }
166
167 sh("rm tmpFile || true")
168 writeFile(file: "tmpFile", text: publish)
169 sh("aptly-publisher restore --url ${server} --restore-file tmpFile --components ${components} ${opts}")
170}
Oleg Iurchenko85bb5d72018-02-15 16:45:22 +0200171
172/**
173 * The function return name of the snapshot belongs to repo considering the prefix with storage by REST API.
174 *
175 * @param server URI the server to connect to aptly API
176 * @param destribution Destiribution of the repo which have to be found
177 * @param prefix Prefix of the repo including storage eg. prefix or s3:aptcdn:prefix
178 * @param component Component of the repo
179 *
180 * @return snapshot name
181 **/
182def getSnapshotByAPI(server, distribution, prefix, component) {
183 http = new com.mirantis.mk.Http()
184 def list_published = http.restGet(server, '/api/publish')
185 def storage
186 for (items in list_published) {
187 for (row in items) {
188 if (prefix.tokenize(':')[1]) {
189 storage = prefix.tokenize(':')[0] + ':' + prefix.tokenize(':')[1]
190 } else {
191 storage = ''
192 }
193 if (row.key == 'Distribution' && row.value == distribution && items['Prefix'] == prefix.tokenize(':').last() && items['Storage'] == storage) {
194 for (source in items['Sources']){
195 if (source['Component'] == component) {
196 if(env.getEnvironment().containsKey('DEBUG') && env['DEBUG'] == "true"){
197 println ('Snapshot belongs to ' + distribution + '/' + prefix + ': ' + source['Name'])
198 }
199 return source['Name']
200 }
201 }
202 }
203 }
204 }
205 return false
206}
207
208/**
Richard Felkld2000552018-04-18 17:29:47 +0200209 * Returns list of the packages from specified Aptly repo by REST API
210 *
211 * @param server URI of the server insluding port and protocol
212 * @param repo Local repo name
213 **/
214def listPackagesFromRepoByAPI(server, repo){
215 http = new com.mirantis.mk.Http()
216 def packageList = http.restGet(server, "/api/repos/${repo}/packages")
217 return packageList
218}
219
220/**
221 * Deletes packages from specified Aptly repo by REST API
222 *
223 * @param server URI of the server insluding port and protocol
224 * @param repo Local repo name
225 * @param packageRefs Package list specified by packageRefs
226 **/
227def deletePackagesFromRepoByAPI(server, repo, packageRefs){
228 http = new com.mirantis.mk.Http()
229 def data = [:]
230 data['PackageRefs'] = packageRefs
231 http.restDelete(server, "/api/repos/${repo}/packages", data)
232}
233
234/**
Oleg Iurchenko85bb5d72018-02-15 16:45:22 +0200235 * Returns list of the packages matched to pattern and
236 * belonged to particular snapshot by REST API
237 *
238 * @param server URI of the server insluding port and protocol
239 * @param snapshotName Snapshot to check
240 * @param packagesList Pattern of the components to be compared
241 **/
242def snapshotPackagesByAPI(server, snapshotName, packagesList) {
243 http = new com.mirantis.mk.Http()
244 def pkgs = http.restGet(server, "/api/snapshots/${snapshotName}/packages")
245 def packages = []
246
247 for (package_pattern in packagesList.tokenize(',')) {
248 def pkg = pkgs.find { item -> item.contains(package_pattern) }
249 packages.add(pkg)
250 }
251
252 return packages
253}
254
255
256/**
257 * Creates snapshot of the repo or package refs by REST API
258 * @param server URI of the server insluding port and protocol
259 * @param repo Local repo name
260 * @param snapshotName Snapshot name is going to be created
261 * @param snapshotDescription Snapshot description
262 * @param packageRefs List of the packages are going to be included into the snapshot
263 **/
264def snapshotCreateByAPI(server, repo, snapshotName, snapshotDescription = null, packageRefs = null) {
265 http = new com.mirantis.mk.Http()
266 def data = [:]
267 data['Name'] = snapshotName
268 if (snapshotDescription) {
269 data['Description'] = snapshotDescription
270 } else {
271 data['Description'] = "Snapshot of ${repo} repo"
272 }
273 if (packageRefs) {
274 data['PackageRefs'] = packageRefs
275 http.restPost(server, '/api/snapshots', data)
276 } else {
Richard Felkld2000552018-04-18 17:29:47 +0200277 http.restPost(server, "/api/repos/${repo}/snapshots", data)
Oleg Iurchenko85bb5d72018-02-15 16:45:22 +0200278 }
279}
280
281/**
282 * Publishes the snapshot accodgin to distribution, components and prefix by REST API
283 * @param server URI of the server insluding port and protocol
284 * @param snapshotName Snapshot is going to be published
285 * @param distribution Distribution for the published repo
286 * @param components Component for the published repo
287 * @param prefix Prefix for thepubslidhed repo including storage
288 **/
289def snapshotPublishByAPI(server, snapshotName, distribution, components, prefix) {
290 http = new com.mirantis.mk.Http()
291 def source = [:]
292 source['Name'] = snapshotName
293 source['Component'] = components
294 def data = [:]
295 data['SourceKind'] = 'snapshot'
296 data['Sources'] = [source]
297 data['Architectures'] = ['amd64']
298 data['Distribution'] = distribution
299 return http.restPost(server, "/api/publish/${prefix}", data)
300}
301
302/**
303 * Unpublish Aptly repo by REST API
304 *
305 * @param aptlyServer Aptly connection object
306 * @param aptlyPrefix Aptly prefix where need to delete a repo
307 * @param aptlyRepo Aptly repo name
308 */
309def unpublishByAPI(aptlyServer, aptlyPrefix, aptlyRepo){
310 http = new com.mirantis.mk.Http()
311 http.restDelete(aptlyServer, "/api/publish/${aptlyPrefix}/${aptlyRepo}")
312}
313
314/**
315 * Delete Aptly repo by REST API
316 *
317 * @param aptlyServer Aptly connection object
318 * @param aptlyRepo Aptly repo name
319 */
320def deleteRepoByAPI(aptlyServer, aptlyRepo){
321 http = new com.mirantis.mk.Http()
322 http.restDelete(aptlyServer, "/api/repos/${aptlyRepo}")
323}