Merge ~aittner/charms/+source/scalebot-autopkgtest:add-autopkgtest-charm into ~ce-hyperscale/charms/+source/scalebot-autopkgtest:master

Proposed by Alexandre Erwin Ittner
Status: Merged
Approved by: Andrew Cloke
Approved revision: 8daa3eeeb36d8df75d373a333d88d367cf691e7f
Merged at revision: 8daa3eeeb36d8df75d373a333d88d367cf691e7f
Proposed branch: ~aittner/charms/+source/scalebot-autopkgtest:add-autopkgtest-charm
Merge into: ~ce-hyperscale/charms/+source/scalebot-autopkgtest:master
Diff against target: 538 lines (+490/-0)
8 files modified
README.md (+82/-0)
actions.yaml (+7/-0)
actions/run-test (+31/-0)
config.yaml (+1/-0)
icon.svg (+292/-0)
layer.yaml (+5/-0)
metadata.yaml (+18/-0)
reactive/autopkgtest.py (+54/-0)
Reviewer Review Type Date Requested Status
dann frazier Approve
Review via email: mp+374850@code.launchpad.net
To post a comment you must log in.
Revision history for this message
dann frazier (dannf) wrote :

This looks awesome, thanks Alexandre!

A few comments inline - and one nit about the name, this charm isn't really glued to scalebot at all AFAICT, so I'd suggest we just call it autopkgtest or similar.

Revision history for this message
dann frazier (dannf) wrote :

Nice! I added a couple of very minor comments from check tools - incorporate as you see fit. I followed the steps in your README and it worked perfectly (on lakitu w/ lxd cloud). +1.

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1diff --git a/README.md b/README.md
2new file mode 100644
3index 0000000..aa2aa31
4--- /dev/null
5+++ b/README.md
6@@ -0,0 +1,82 @@
7+# Overview
8+
9+This charm is a thin automation layer to run DEP8 tests in a target environment.
10+
11+This charm will deploy a basic environment to run DEP8 tests (with autopkgtest) on the target MAAS-provisioned machine, VM or container. Packages will be build and run in the target itself to improve test coverage.
12+
13+Basic idea is to reuse the tests already available in the Debian packages to validate new hardware configurations and run these tests in existing infrastructure while using Juju to abstract the nature of the target environment. It will not matter, for the charm, if the test is running in a VM or in bare metal, but the intention is run them on metal to minimize the interference of virtualization providers on test results.
14+
15+The test run directly on the target environment using the "null" autopkgtest virtualization provider and it is assumed the environment is "disposable", i.e. it will released or recreated once the tests are finished.
16+
17+
18+
19+# Usage
20+
21+This charm is intended to be deployed and used through test automation but, in development enviroments, the deployment procedure is:
22+
23+- Install the charm with
24+```$ juju deploy cs:~ce-hyperscale/autopkgtest testbed1```.
25+Notice that this example assumes a testbed named "testbed1".
26+
27+- Run a test with the Juju action ``run-test``, passing the Debian package name in argument ``pkgname``:
28+
29+ $ juju run-action testbed1/0 run-test pkgname=nginx
30+ Action queued with id: d13d1822-724f-4719-8ed1-35dd0d124474
31+
32+- Use the action-id to check if the execution is already finished:
33+
34+ $ juju show-action-status d13d1822-724f-4719-8ed1-35dd0d124474
35+ actions:
36+ - action: run-test
37+ completed at: n/a
38+ id: d13d1822-724f-4719-8ed1-35dd0d124474
39+ status: running
40+ unit: testbed1/0
41+
42+- Use ``juju debug-log`` to see the outputs of the test (stdout and stderr) in realtime;
43+
44+- Once the test is finished, grab the output with:
45+
46+ $ juju show-action-output d13d1822-724f-4719-8ed1-35dd0d124474
47+ results:
48+ output-file: /tmp/test-nginx-kz6TT/output.txt
49+ retcode: "0"
50+ summary-file: /tmp/test-nginx-kz6TT/summary.txt
51+ status: completed
52+ timing:
53+ completed: 2019-10-22 21:54:33 +0000 UTC
54+ enqueued: 2019-10-22 21:48:01 +0000 UTC
55+ started: 2019-10-22 21:48:06 +0000 UTC
56+
57+Optionally, run the action with the "--wait" command line switch. This spares the user from polling the test state, but blocks the Juju client process.
58+
59+
60+## Interpreting outputs
61+
62+The exit code returned by ``autopkgtest`` will be saved in variable ``retcode`` (see autpkgtest manpage for more information on it meaning). This only happens if ``autopkgtest`` gets a chance to run and won't be created if the test script fails before this step.
63+
64+Variables ``summary`` and ``output`` will have paths to files containing the summary of the test results and a copy of stdout and stderr of the test execution. Use ``juju ssh`` to see their contents or copy them to the host machine.
65+
66+ $ juju ssh testbed1/0 cat /tmp/test-nginx-kz6TT/summary.txt
67+ light-simple PASS
68+ core-simple PASS
69+ lua PASS
70+ full-simple PASS
71+ extras-simple PASS
72+ full-module-deps PASS
73+ light-module-deps PASS
74+ core-module-deps PASS
75+ extras-module-deps PASS
76+ Connection to 10.214.19.195 closed.
77+
78+Notice that file output.txt can be pretty large.
79+
80+
81+
82+
83+# Known Limitations and Issues
84+
85+- Some tests may refuse to run in containers;
86+
87+- Autopkgtest has a protection against running tests that can break the testbed (restriction ``breaks-testbed``). It does not matter for us as the target will be recreated anyway, but these tests will require patching to force them to run.
88+
89diff --git a/actions.yaml b/actions.yaml
90new file mode 100644
91index 0000000..a77ee65
92--- /dev/null
93+++ b/actions.yaml
94@@ -0,0 +1,7 @@
95+run-test:
96+ description: Run autopkgtest for a single package.
97+ params:
98+ pkgname:
99+ type: string
100+ description: Name of the Debian package to test.
101+ required: [pkgname]
102diff --git a/actions/run-test b/actions/run-test
103new file mode 100755
104index 0000000..1ee6857
105--- /dev/null
106+++ b/actions/run-test
107@@ -0,0 +1,31 @@
108+#!/bin/sh
109+
110+set -e
111+
112+PKGNAME=$(action-get pkgname)
113+BASEDIR=$(mktemp -d /tmp/test-$PKGNAME-XXXXX)
114+
115+OUTFILE=$BASEDIR/output.txt
116+action-set output-file="$OUTFILE"
117+
118+SUMMARY=$BASEDIR/summary.txt
119+action-set summary-file="$SUMMARY"
120+
121+touch $OUTFILE $SUMMARY
122+chmod a+r $OUTFILE $SUMMARY
123+chmod a+x $BASEDIR
124+
125+mkdir $BASEDIR/tmp
126+cd $BASEDIR/tmp
127+
128+{
129+ echo "===== AUTOPKGTEST CHARM TEST STARTING: $PKGNAME ====="
130+ set +e
131+ autopkgtest --summary-file=$SUMMARY -B $PKGNAME -- null
132+ TESTRC=$?
133+ action-set retcode="$TESTRC"
134+ echo "===== AUTOPKGTEST CHARM TEST FINISHED: $PKGNAME ====="
135+} 2>&1 | tee $OUTFILE
136+
137+rm -rf $BASEDIR/tmp
138+exit $TESTRC
139diff --git a/config.yaml b/config.yaml
140new file mode 100644
141index 0000000..7e66e9c
142--- /dev/null
143+++ b/config.yaml
144@@ -0,0 +1 @@
145+options: { }
146diff --git a/icon.svg b/icon.svg
147new file mode 100644
148index 0000000..559154b
149--- /dev/null
150+++ b/icon.svg
151@@ -0,0 +1,292 @@
152+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
153+<!-- Created with Inkscape (http://www.inkscape.org/) -->
154+
155+<svg
156+ xmlns:dc="http://purl.org/dc/elements/1.1/"
157+ xmlns:cc="http://creativecommons.org/ns#"
158+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
159+ xmlns:svg="http://www.w3.org/2000/svg"
160+ xmlns="http://www.w3.org/2000/svg"
161+ xmlns:xlink="http://www.w3.org/1999/xlink"
162+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
163+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
164+ width="96"
165+ height="96"
166+ id="svg6517"
167+ version="1.1"
168+ inkscape:version="0.92.3 (2405546, 2018-03-11)"
169+ sodipodi:docname="icon.svg">
170+ <defs
171+ id="defs6519">
172+ <linearGradient
173+ inkscape:collect="always"
174+ xlink:href="#Background"
175+ id="linearGradient6461"
176+ gradientUnits="userSpaceOnUse"
177+ x1="0"
178+ y1="970.29498"
179+ x2="144"
180+ y2="970.29498"
181+ gradientTransform="matrix(0,-0.66666669,0.6660448,0,-866.25992,731.29077)" />
182+ <linearGradient
183+ id="Background">
184+ <stop
185+ id="stop4178"
186+ offset="0"
187+ style="stop-color:#b8b8b8;stop-opacity:1" />
188+ <stop
189+ id="stop4180"
190+ offset="1"
191+ style="stop-color:#c9c9c9;stop-opacity:1" />
192+ </linearGradient>
193+ <filter
194+ style="color-interpolation-filters:sRGB;"
195+ inkscape:label="Inner Shadow"
196+ id="filter1121">
197+ <feFlood
198+ flood-opacity="0.59999999999999998"
199+ flood-color="rgb(0,0,0)"
200+ result="flood"
201+ id="feFlood1123" />
202+ <feComposite
203+ in="flood"
204+ in2="SourceGraphic"
205+ operator="out"
206+ result="composite1"
207+ id="feComposite1125" />
208+ <feGaussianBlur
209+ in="composite1"
210+ stdDeviation="1"
211+ result="blur"
212+ id="feGaussianBlur1127" />
213+ <feOffset
214+ dx="0"
215+ dy="2"
216+ result="offset"
217+ id="feOffset1129" />
218+ <feComposite
219+ in="offset"
220+ in2="SourceGraphic"
221+ operator="atop"
222+ result="composite2"
223+ id="feComposite1131" />
224+ </filter>
225+ <filter
226+ style="color-interpolation-filters:sRGB;"
227+ inkscape:label="Drop Shadow"
228+ id="filter950">
229+ <feFlood
230+ flood-opacity="0.25"
231+ flood-color="rgb(0,0,0)"
232+ result="flood"
233+ id="feFlood952" />
234+ <feComposite
235+ in="flood"
236+ in2="SourceGraphic"
237+ operator="in"
238+ result="composite1"
239+ id="feComposite954" />
240+ <feGaussianBlur
241+ in="composite1"
242+ stdDeviation="1"
243+ result="blur"
244+ id="feGaussianBlur956" />
245+ <feOffset
246+ dx="0"
247+ dy="1"
248+ result="offset"
249+ id="feOffset958" />
250+ <feComposite
251+ in="SourceGraphic"
252+ in2="offset"
253+ operator="over"
254+ result="composite2"
255+ id="feComposite960" />
256+ </filter>
257+ <clipPath
258+ clipPathUnits="userSpaceOnUse"
259+ id="clipPath873">
260+ <g
261+ transform="matrix(0,-0.66666667,0.66604479,0,-258.25992,677.00001)"
262+ id="g875"
263+ inkscape:label="Layer 1"
264+ style="fill:#ff00ff;fill-opacity:1;stroke:none;display:inline">
265+ <path
266+ style="fill:#ff00ff;fill-opacity:1;stroke:none;display:inline"
267+ d="m 46.702703,898.22775 50.594594,0 C 138.16216,898.22775 144,904.06497 144,944.92583 l 0,50.73846 c 0,40.86071 -5.83784,46.69791 -46.702703,46.69791 l -50.594594,0 C 5.8378378,1042.3622 0,1036.525 0,995.66429 L 0,944.92583 C 0,904.06497 5.8378378,898.22775 46.702703,898.22775 Z"
268+ id="path877"
269+ inkscape:connector-curvature="0"
270+ sodipodi:nodetypes="sssssssss" />
271+ </g>
272+ </clipPath>
273+ <filter
274+ inkscape:collect="always"
275+ id="filter891"
276+ inkscape:label="Badge Shadow">
277+ <feGaussianBlur
278+ inkscape:collect="always"
279+ stdDeviation="0.71999962"
280+ id="feGaussianBlur893" />
281+ </filter>
282+ </defs>
283+ <sodipodi:namedview
284+ id="base"
285+ pagecolor="#ffffff"
286+ bordercolor="#666666"
287+ borderopacity="1.0"
288+ inkscape:pageopacity="0.0"
289+ inkscape:pageshadow="2"
290+ inkscape:zoom="1.0186341"
291+ inkscape:cx="176.12112"
292+ inkscape:cy="-118.41312"
293+ inkscape:document-units="px"
294+ inkscape:current-layer="text150"
295+ showgrid="true"
296+ fit-margin-top="0"
297+ fit-margin-left="0"
298+ fit-margin-right="0"
299+ fit-margin-bottom="0"
300+ inkscape:window-width="1920"
301+ inkscape:window-height="1016"
302+ inkscape:window-x="0"
303+ inkscape:window-y="27"
304+ inkscape:window-maximized="1"
305+ showborder="true"
306+ showguides="true"
307+ inkscape:guide-bbox="true"
308+ inkscape:showpageshadow="false">
309+ <inkscape:grid
310+ type="xygrid"
311+ id="grid821" />
312+ <sodipodi:guide
313+ orientation="1,0"
314+ position="16,48"
315+ id="guide823"
316+ inkscape:locked="false" />
317+ <sodipodi:guide
318+ orientation="0,1"
319+ position="64,80"
320+ id="guide825"
321+ inkscape:locked="false" />
322+ <sodipodi:guide
323+ orientation="1,0"
324+ position="80,40"
325+ id="guide827"
326+ inkscape:locked="false" />
327+ <sodipodi:guide
328+ orientation="0,1"
329+ position="64,16"
330+ id="guide829"
331+ inkscape:locked="false" />
332+ </sodipodi:namedview>
333+ <metadata
334+ id="metadata6522">
335+ <rdf:RDF>
336+ <cc:Work
337+ rdf:about="">
338+ <dc:format>image/svg+xml</dc:format>
339+ <dc:type
340+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
341+ <dc:title />
342+ </cc:Work>
343+ </rdf:RDF>
344+ </metadata>
345+ <g
346+ inkscape:label="BACKGROUND"
347+ inkscape:groupmode="layer"
348+ id="layer1"
349+ transform="translate(268,-635.29076)"
350+ style="display:inline">
351+ <path
352+ style="fill:url(#linearGradient6461);fill-opacity:1;stroke:none;display:inline;filter:url(#filter1121)"
353+ d="m -268,700.15563 0,-33.72973 c 0,-27.24324 3.88785,-31.13513 31.10302,-31.13513 l 33.79408,0 c 27.21507,0 31.1029,3.89189 31.1029,31.13513 l 0,33.72973 c 0,27.24325 -3.88783,31.13514 -31.1029,31.13514 l -33.79408,0 C -264.11215,731.29077 -268,727.39888 -268,700.15563 Z"
354+ id="path6455"
355+ inkscape:connector-curvature="0"
356+ sodipodi:nodetypes="sssssssss" />
357+ <g
358+ aria-label="8"
359+ style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:74.66666412px;line-height:125%;font-family:Arial;-inkscape-font-specification:'Arial Bold';text-align:center;letter-spacing:0px;word-spacing:0px;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:#000000;stroke-width:0.60000002;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
360+ id="text150">
361+ <path
362+ d="m -229.41907,679.75616 q -5.10937,-2.15625 -7.45312,-5.90625 -2.29688,-3.79687 -2.29688,-8.29687 0,-7.6875 5.34375,-12.70313 5.39063,-5.01562 15.28125,-5.01562 9.79688,0 15.1875,5.01562 5.4375,5.01563 5.4375,12.70313 0,4.78125 -2.48437,8.53125 -2.48438,3.70312 -6.98438,5.67187 5.71875,2.29688 8.67188,6.70313 3,4.40625 3,10.17187 0,9.51563 -6.09375,15.46875 -6.04688,5.95313 -16.125,5.95313 -9.375,0 -15.60938,-4.92188 -7.35937,-5.8125 -7.35937,-15.9375 0,-5.57812 2.76562,-10.21875 2.76563,-4.6875 8.71875,-7.21875 z m 2.71875,-13.26562 q 0,3.9375 2.20313,6.14062 2.25,2.20313 5.95312,2.20313 3.75,0 6,-2.20313 2.25,-2.25 2.25,-6.1875 0,-3.70312 -2.25,-5.90625 -2.20312,-2.25 -5.85937,-2.25 -3.79688,0 -6.04688,2.25 -2.25,2.25 -2.25,5.95313 z m -1.21875,29.4375 q 0,5.4375 2.76563,8.48437 2.8125,3.04688 6.98437,3.04688 4.07813,0 6.75,-2.90625 2.67188,-2.95313 2.67188,-8.48438 0,-4.82812 -2.71875,-7.73437 -2.71875,-2.95313 -6.89063,-2.95313 -4.82812,0 -7.21875,3.32813 -2.34375,3.32812 -2.34375,7.21875 z"
363+ style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:96px;font-family:Arial;-inkscape-font-specification:'Arial Bold';fill:#ff0000;stroke:#000000;stroke-width:0.60000002;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
364+ id="path959" />
365+ </g>
366+ </g>
367+ <g
368+ inkscape:groupmode="layer"
369+ id="layer3"
370+ inkscape:label="PLACE YOUR PICTOGRAM HERE"
371+ style="display:inline" />
372+ <g
373+ inkscape:groupmode="layer"
374+ id="layer2"
375+ inkscape:label="BADGE"
376+ style="display:none"
377+ sodipodi:insensitive="true">
378+ <g
379+ style="display:inline"
380+ transform="translate(-340.00001,-581)"
381+ id="g4394"
382+ clip-path="none">
383+ <g
384+ id="g855">
385+ <g
386+ inkscape:groupmode="maskhelper"
387+ id="g870"
388+ clip-path="url(#clipPath873)"
389+ style="opacity:0.6;filter:url(#filter891)">
390+ <path
391+ transform="matrix(1.4999992,0,0,1.4999992,-29.999795,-237.54282)"
392+ d="m 264,552.36218 a 12,12 0 0 1 -12,12 12,12 0 0 1 -12,-12 12,12 0 0 1 12,-12 12,12 0 0 1 12,12 z"
393+ sodipodi:ry="12"
394+ sodipodi:rx="12"
395+ sodipodi:cy="552.36218"
396+ sodipodi:cx="252"
397+ id="path844"
398+ style="color:#000000;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:4;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
399+ sodipodi:type="arc" />
400+ </g>
401+ <g
402+ id="g862">
403+ <path
404+ sodipodi:type="arc"
405+ style="color:#000000;fill:#f5f5f5;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:4;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
406+ id="path4398"
407+ sodipodi:cx="252"
408+ sodipodi:cy="552.36218"
409+ sodipodi:rx="12"
410+ sodipodi:ry="12"
411+ d="m 264,552.36218 a 12,12 0 0 1 -12,12 12,12 0 0 1 -12,-12 12,12 0 0 1 12,-12 12,12 0 0 1 12,12 z"
412+ transform="matrix(1.4999992,0,0,1.4999992,-29.999795,-238.54282)" />
413+ <path
414+ transform="matrix(1.25,0,0,1.25,33,-100.45273)"
415+ d="m 264,552.36218 a 12,12 0 0 1 -12,12 12,12 0 0 1 -12,-12 12,12 0 0 1 12,-12 12,12 0 0 1 12,12 z"
416+ sodipodi:ry="12"
417+ sodipodi:rx="12"
418+ sodipodi:cy="552.36218"
419+ sodipodi:cx="252"
420+ id="path4400"
421+ style="color:#000000;fill:#dd4814;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:4;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
422+ sodipodi:type="arc" />
423+ <path
424+ sodipodi:type="star"
425+ style="color:#000000;fill:#f5f5f5;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:3;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
426+ id="path4459"
427+ sodipodi:sides="5"
428+ sodipodi:cx="666.19574"
429+ sodipodi:cy="589.50385"
430+ sodipodi:r1="7.2431178"
431+ sodipodi:r2="4.3458705"
432+ sodipodi:arg1="1.0471976"
433+ sodipodi:arg2="1.6755161"
434+ inkscape:flatsided="false"
435+ inkscape:rounded="0.1"
436+ inkscape:randomized="0"
437+ d="m 669.8173,595.77657 c -0.39132,0.22593 -3.62645,-1.90343 -4.07583,-1.95066 -0.44938,-0.0472 -4.05653,1.36297 -4.39232,1.06062 -0.3358,-0.30235 0.68963,-4.03715 0.59569,-4.47913 -0.0939,-0.44198 -2.5498,-3.43681 -2.36602,-3.8496 0.18379,-0.41279 4.05267,-0.59166 4.44398,-0.81759 0.39132,-0.22593 2.48067,-3.48704 2.93005,-3.4398 0.44938,0.0472 1.81505,3.67147 2.15084,3.97382 0.3358,0.30236 4.08294,1.2817 4.17689,1.72369 0.0939,0.44198 -2.9309,2.86076 -3.11469,3.27355 -0.18379,0.41279 0.0427,4.27917 -0.34859,4.5051 z"
438+ transform="matrix(1.511423,-0.16366377,0.16366377,1.511423,-755.37346,-191.93651)" />
439+ </g>
440+ </g>
441+ </g>
442+ </g>
443+</svg>
444diff --git a/layer.yaml b/layer.yaml
445new file mode 100644
446index 0000000..6581470
447--- /dev/null
448+++ b/layer.yaml
449@@ -0,0 +1,5 @@
450+includes: ['layer:basic'] # if you use any interfaces, add them here
451+
452+options:
453+ basic:
454+ packages: ['autopkgtest', 'dpkg-dev']
455diff --git a/metadata.yaml b/metadata.yaml
456new file mode 100644
457index 0000000..11dde37
458--- /dev/null
459+++ b/metadata.yaml
460@@ -0,0 +1,18 @@
461+name: autopkgtest
462+summary: Run DEP8 tests on Juju infrastructure
463+maintainer: Canonical Server and Hardware Enablement Team <canonical-hyperscale-team@lists.canonical.com>
464+description: |
465+ This charm will deploy a basic environment to run DEP8 tests (with
466+ autopkgtest) on the target machine, VM or container. Basic idea is to
467+ reuse the tests already available in the packages and run them, using
468+ Juju to automate target selection and deployment. It is assumed the
469+ target environment is "disposable", i.e. it will released or recreated
470+ once the tests are finished.
471+
472+series:
473+ - xenial
474+ - bionic
475+ - eoan
476+tags:
477+ - ops
478+ - misc
479diff --git a/reactive/autopkgtest.py b/reactive/autopkgtest.py
480new file mode 100644
481index 0000000..beb31b8
482--- /dev/null
483+++ b/reactive/autopkgtest.py
484@@ -0,0 +1,54 @@
485+import os
486+import subprocess
487+
488+from charmhelpers.core.hookenv import log, status_set
489+from charms.reactive import (hook, when, when_not, when_any, set_flag,
490+ set_state, remove_state)
491+
492+APT_SOURCE_FNAME = "/etc/apt/sources.list.d/charm-autopkgtest.list"
493+
494+
495+def apt_update():
496+ subprocess.run(["apt-get", "-y", "update"], check=True)
497+
498+
499+def get_release_codename():
500+ with os.popen("lsb_release -cs") as fp:
501+ return fp.read().strip()
502+
503+
504+def add_apt_sources():
505+ """Add an APT source list with the required packages.
506+
507+ This may duplicate some existing entries, but apt seems to handle
508+ this situation pretty well.
509+ """
510+
511+ codename = get_release_codename()
512+ channels = "main universe restricted"
513+ with open(APT_SOURCE_FNAME, "w") as fp:
514+ fp.write("deb-src http://archive.ubuntu.com/ubuntu %s %s\n"
515+ % (codename, channels))
516+ fp.write("deb-src http://security.ubuntu.com/ubuntu %s-security %s\n"
517+ % (codename, channels))
518+ apt_update()
519+
520+
521+def remove_apt_sources():
522+ try:
523+ os.unlink(APT_SOURCE_FNAME)
524+ except FileNotFoundError:
525+ # Ignore non-existing files.
526+ pass
527+ apt_update()
528+
529+
530+@when_not('autopkgtest.ready')
531+def autopkgtest_ready():
532+ try:
533+ add_apt_sources()
534+ except subprocess.CalledProcessError:
535+ status_set('blocked', "Failed to install dependencies")
536+ else:
537+ status_set('active', 'ready')
538+ set_flag('autopkgtest.ready')

Subscribers

People subscribed via source and target branches