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