blob: 47710848a0f879c4b236eed401e1a6d8af231a58 [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
chnydadc7292f2018-01-17 14:30:22 +0100116 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
Filip Pytloun15fbbc92017-11-27 14:33:22 +0100120def 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 {
147 throw new Exception("Aptly dump publishes for a prefix ${prefix}* failed. No dump files found!")
148 }
chnydad8f51af2017-07-24 10:39:48 +0200149}
150
151/**
152 * Restore publish from YAML file
153 *
154 * @param server Server host
155 * @param recreate Recreate publishes
156 * @param publish Serialized YAML of Publish
157 * @param components Components to restore
158 */
159def restorePublish(server, recreate, publish, components='all') {
160
161 opts = ""
162 if (recreate) {
163 opts << " --recreate"
164 }
165
166 sh("rm tmpFile || true")
167 writeFile(file: "tmpFile", text: publish)
168 sh("aptly-publisher restore --url ${server} --restore-file tmpFile --components ${components} ${opts}")
169}
Oleg Iurchenko85bb5d72018-02-15 16:45:22 +0200170
171/**
172 * The function return name of the snapshot belongs to repo considering the prefix with storage by REST API.
173 *
174 * @param server URI the server to connect to aptly API
175 * @param destribution Destiribution of the repo which have to be found
176 * @param prefix Prefix of the repo including storage eg. prefix or s3:aptcdn:prefix
177 * @param component Component of the repo
178 *
179 * @return snapshot name
180 **/
181def getSnapshotByAPI(server, distribution, prefix, component) {
182 http = new com.mirantis.mk.Http()
183 def list_published = http.restGet(server, '/api/publish')
184 def storage
185 for (items in list_published) {
186 for (row in items) {
187 if (prefix.tokenize(':')[1]) {
188 storage = prefix.tokenize(':')[0] + ':' + prefix.tokenize(':')[1]
189 } else {
190 storage = ''
191 }
192 if (row.key == 'Distribution' && row.value == distribution && items['Prefix'] == prefix.tokenize(':').last() && items['Storage'] == storage) {
193 for (source in items['Sources']){
194 if (source['Component'] == component) {
195 if(env.getEnvironment().containsKey('DEBUG') && env['DEBUG'] == "true"){
196 println ('Snapshot belongs to ' + distribution + '/' + prefix + ': ' + source['Name'])
197 }
198 return source['Name']
199 }
200 }
201 }
202 }
203 }
204 return false
205}
206
207/**
208 * Returns list of the packages matched to pattern and
209 * belonged to particular snapshot by REST API
210 *
211 * @param server URI of the server insluding port and protocol
212 * @param snapshotName Snapshot to check
213 * @param packagesList Pattern of the components to be compared
214 **/
215def snapshotPackagesByAPI(server, snapshotName, packagesList) {
216 http = new com.mirantis.mk.Http()
217 def pkgs = http.restGet(server, "/api/snapshots/${snapshotName}/packages")
218 def packages = []
219
220 for (package_pattern in packagesList.tokenize(',')) {
221 def pkg = pkgs.find { item -> item.contains(package_pattern) }
222 packages.add(pkg)
223 }
224
225 return packages
226}
227
228
229/**
230 * Creates snapshot of the repo or package refs by REST API
231 * @param server URI of the server insluding port and protocol
232 * @param repo Local repo name
233 * @param snapshotName Snapshot name is going to be created
234 * @param snapshotDescription Snapshot description
235 * @param packageRefs List of the packages are going to be included into the snapshot
236 **/
237def snapshotCreateByAPI(server, repo, snapshotName, snapshotDescription = null, packageRefs = null) {
238 http = new com.mirantis.mk.Http()
239 def data = [:]
240 data['Name'] = snapshotName
241 if (snapshotDescription) {
242 data['Description'] = snapshotDescription
243 } else {
244 data['Description'] = "Snapshot of ${repo} repo"
245 }
246 if (packageRefs) {
247 data['PackageRefs'] = packageRefs
248 http.restPost(server, '/api/snapshots', data)
249 } else {
250 http.restPost(server + "/api/repos/${repo}/snapshots", data)
251 }
252}
253
254/**
255 * Publishes the snapshot accodgin to distribution, components and prefix by REST API
256 * @param server URI of the server insluding port and protocol
257 * @param snapshotName Snapshot is going to be published
258 * @param distribution Distribution for the published repo
259 * @param components Component for the published repo
260 * @param prefix Prefix for thepubslidhed repo including storage
261 **/
262def snapshotPublishByAPI(server, snapshotName, distribution, components, prefix) {
263 http = new com.mirantis.mk.Http()
264 def source = [:]
265 source['Name'] = snapshotName
266 source['Component'] = components
267 def data = [:]
268 data['SourceKind'] = 'snapshot'
269 data['Sources'] = [source]
270 data['Architectures'] = ['amd64']
271 data['Distribution'] = distribution
272 return http.restPost(server, "/api/publish/${prefix}", data)
273}
274
275/**
276 * Unpublish Aptly repo by REST API
277 *
278 * @param aptlyServer Aptly connection object
279 * @param aptlyPrefix Aptly prefix where need to delete a repo
280 * @param aptlyRepo Aptly repo name
281 */
282def unpublishByAPI(aptlyServer, aptlyPrefix, aptlyRepo){
283 http = new com.mirantis.mk.Http()
284 http.restDelete(aptlyServer, "/api/publish/${aptlyPrefix}/${aptlyRepo}")
285}
286
287/**
288 * Delete Aptly repo by REST API
289 *
290 * @param aptlyServer Aptly connection object
291 * @param aptlyRepo Aptly repo name
292 */
293def deleteRepoByAPI(aptlyServer, aptlyRepo){
294 http = new com.mirantis.mk.Http()
295 http.restDelete(aptlyServer, "/api/repos/${aptlyRepo}")
296}