Merge ~jocave/plainbox-provider-checkbox:iot-image-checks into plainbox-provider-checkbox:master

Proposed by Jonathan Cave
Status: Merged
Approved by: Jonathan Cave
Approved revision: fecd5b893edb77421bc79c2b96bed4020e6342b1
Merged at revision: 6063034fb9013cbbfc3c11324a82b7fc6389fd42
Proposed branch: ~jocave/plainbox-provider-checkbox:iot-image-checks
Merge into: plainbox-provider-checkbox:master
Diff against target: 237 lines (+211/-0)
4 files modified
bin/ubuntucore_image_checks.py (+116/-0)
units/image/category.pxu (+3/-0)
units/image/jobs.pxu (+72/-0)
units/image/test-plan.pxu (+20/-0)
Reviewer Review Type Date Requested Status
Sheila Miguez (community) Approve
Review via email: mp+387048@code.launchpad.net

Description of the change

I wrote these tests to go in to the test plan I had been working on whose goal was to certify Ubuntu Core IoT images. I'm not sure how relevant these are going to be now, but since I put the time in I may as well propose them.

I test them on an amd64 machine running generic UC18.

To post a comment you must log in.
Revision history for this message
Sheila Miguez (codersquid) wrote :

I have a very minor comment about a summary. Otherwise things seem ok.

Revision history for this message
Jonathan Cave (jocave) wrote :

Good spot, thanks. Fixed and squashed

Revision history for this message
Sheila Miguez (codersquid) wrote :

lgtm

review: Approve
Revision history for this message
Chris Wayne (cwayne) wrote :

Obviously this is still relevant for the core images, so very worth writing, thanks. Given the ODM program pricing structure has core as 50% of the cost of classic, I think we can still assume the majority will be core.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1diff --git a/bin/ubuntucore_image_checks.py b/bin/ubuntucore_image_checks.py
2new file mode 100755
3index 0000000..214fc42
4--- /dev/null
5+++ b/bin/ubuntucore_image_checks.py
6@@ -0,0 +1,116 @@
7+#!/usr/bin/env python3
8+# Copyright 2020 Canonical Ltd.
9+# All rights reserved.
10+#
11+# Written by:
12+# Jonathan Cave <jonathan.cave@canonical.com>
13+
14+import io
15+import sys
16+
17+from checkbox_support.snap_utils.snapd import Snapd
18+
19+
20+class SnapInfo():
21+
22+ def __init__(self):
23+ self.kernel = None
24+ self.gadget = None
25+ data = Snapd().list()
26+ for snap in data:
27+ if snap['type'] == 'kernel':
28+ self.kernel = snap
29+ if snap['type'] == 'gadget':
30+ self.gadget = snap
31+
32+ def test_kernel_publisher(self):
33+ if not self.kernel:
34+ raise SystemExit('ERROR: failed to get kernel snap info')
35+ if self.kernel['publisher']['id'] != 'canonical':
36+ raise SystemExit('ERROR: kernel snap publisher must be canonical')
37+ if self.kernel['publisher']['validation'] != 'verified':
38+ raise SystemExit('ERROR: kernel snap publisher must be verified')
39+ print('PASS')
40+
41+ def test_kernel_tracking(self):
42+ if not self.kernel:
43+ raise SystemExit('ERROR: failed to get kernel snap info')
44+ if not self.kernel.get('tracking-channel'):
45+ raise SystemExit('ERROR: kernel must be tracking a store channel')
46+ if 'stable' not in self.kernel['tracking-channel']:
47+ raise SystemExit('ERROR: kernel must be on a stable channel')
48+ print('PASS')
49+
50+ def test_gadget_publisher(self):
51+ if not self.gadget:
52+ raise SystemExit('ERROR: failed to get gadget snap info')
53+ if self.gadget['publisher']['id'] != 'canonical':
54+ raise SystemExit('ERROR: gadget snap publisher must be canonical')
55+ if self.gadget['publisher']['validation'] != 'verified':
56+ raise SystemExit('ERROR: gadget snap publisher must be verified')
57+ print('PASS')
58+
59+ def test_gadget_tracking(self):
60+ if not self.gadget:
61+ raise SystemExit('ERROR: failed to get gadget snap info')
62+ if not self.gadget.get('tracking-channel'):
63+ raise SystemExit('ERROR: gadget must be tracking a store channel')
64+ if 'stable' not in self.gadget['tracking-channel']:
65+ raise SystemExit('ERROR: gadget must be on a stable channel')
66+ print('PASS')
67+
68+
69+class ModelInfo():
70+
71+ def __init__(self):
72+ self.authority = None
73+ self.brand = None
74+ for line in io.StringIO(Snapd().get_assertions('model').text):
75+ if ':' in line:
76+ entry = line.split(':', maxsplit=1)
77+ if entry[0] == 'authority-id':
78+ self.authority = entry[1].strip()
79+ if entry[0] == 'brand-id':
80+ self.brand = entry[1].strip()
81+
82+ def test_model_authority(self):
83+ if not self.authority:
84+ raise SystemExit('ERROR: failed to get model authority info')
85+ if self.authority != 'canonical':
86+ raise SystemExit('ERROR: model authority must be canonical')
87+ print('PASS')
88+
89+ def test_model_brand(self):
90+ if not self.brand:
91+ raise SystemExit('ERROR: failed to get model brand info')
92+ if self.brand != 'canonical':
93+ raise SystemExit('ERROR: model brand must be canonical')
94+ print('PASS')
95+
96+
97+def main():
98+ if len(sys.argv) != 2:
99+ raise SystemExit('USAGE: ubuntucore_image_checks.py [action]')
100+ action = sys.argv[1]
101+
102+ snapinfo = SnapInfo()
103+ modelinfo = ModelInfo()
104+
105+ if action == 'kernel-publisher':
106+ snapinfo.test_kernel_publisher()
107+ elif action == 'kernel-tracking':
108+ snapinfo.test_kernel_tracking()
109+ elif action == 'gadget-publisher':
110+ snapinfo.test_gadget_publisher()
111+ elif action == 'gadget-tracking':
112+ snapinfo.test_gadget_tracking()
113+ elif action == 'model-authority':
114+ modelinfo.test_model_authority()
115+ elif action == 'model-brand':
116+ modelinfo.test_model_authority()
117+ else:
118+ raise SystemExit('ERROR: unrecognised action')
119+
120+
121+if __name__ == '__main__':
122+ main()
123diff --git a/units/image/category.pxu b/units/image/category.pxu
124new file mode 100644
125index 0000000..919d6cf
126--- /dev/null
127+++ b/units/image/category.pxu
128@@ -0,0 +1,3 @@
129+unit: category
130+id: image
131+_name: Image verification tests
132\ No newline at end of file
133diff --git a/units/image/jobs.pxu b/units/image/jobs.pxu
134new file mode 100644
135index 0000000..efe8d4e
136--- /dev/null
137+++ b/units/image/jobs.pxu
138@@ -0,0 +1,72 @@
139+
140+id: image/kernel-publisher-canonical
141+category_id: image
142+summary: Check that the kernel snap publisher is Canonical
143+description:
144+ During certification testing IoT devices must be running a kernel supplied
145+ by Canonical
146+plugin: shell
147+command:
148+ ubuntucore_image_checks.py kernel-publisher
149+estimated_duration: 2.0
150+flags: preserve-locale
151+
152+id: image/kernel-tracking-stable
153+category_id: image
154+summary: Check that the kernel snap is tracking stable channel
155+description:
156+ During certification testing IoT devices must be running a kernel that is on
157+ a stable channel
158+plugin: shell
159+command:
160+ ubuntucore_image_checks.py kernel-tracking
161+estimated_duration: 2.0
162+flags: preserve-locale
163+
164+id: image/gadget-publisher-canonical
165+category_id: image
166+summary: Check that the gadget snap publisher is Canonical
167+description:
168+ During certification testing IoT devices must be running a kernel supplied
169+ by Canonical
170+plugin: shell
171+command:
172+ ubuntucore_image_checks.py gadget-publisher
173+estimated_duration: 2.0
174+flags: preserve-locale
175+
176+id: image/gadget-tracking-stable
177+category_id: image
178+summary: Check that the gadget snap is tracking stable channel
179+description:
180+ During certification testing IoT devices must be running a gadget that is on
181+ a stable channel
182+plugin: shell
183+command:
184+ ubuntucore_image_checks.py gadget-tracking
185+estimated_duration: 2.0
186+flags: preserve-locale
187+
188+id: image/model-authority-canonical
189+category_id: image
190+summary: Check that model authority-id is canonical
191+description:
192+ The authority-id declares on whose authority this assertion is made. This
193+ must be Canonical for the certification of IoT devices.
194+plugin: shell
195+command:
196+ ubuntucore_image_checks.py model-authority
197+estimated_duration: 2.0
198+flags: preserve-locale
199+
200+id: image/model-brand-canonical
201+category_id: image
202+summary: Check the model brand-id is canoncial
203+description:
204+ For the certification of IoT devices canonical provided generic images must
205+ be used. Hence, the brand-id must be canonical.
206+plugin: shell
207+command:
208+ ubuntucore_image_checks.py model-brand
209+estimated_duration: 2.0
210+flags: preserve-locale
211\ No newline at end of file
212diff --git a/units/image/test-plan.pxu b/units/image/test-plan.pxu
213new file mode 100644
214index 0000000..48af204
215--- /dev/null
216+++ b/units/image/test-plan.pxu
217@@ -0,0 +1,20 @@
218+
219+id: iot-cert-image-full
220+unit: test plan
221+name: Sanity checks for images being certified on IoT devices
222+include:
223+nested_part:
224+ iot-cert-image-manual
225+ iot-cert-image-automated
226+
227+id: iot-cert-image-automated
228+unit: test plan
229+name: Automated Sanity checks for images being certified on IoT devices
230+include:
231+ image/.*
232+
233+id: iot-cert-image-manual
234+unit: test plan
235+name: Manual Sanity checks for images being certified on IoT devices
236+include:
237+

Subscribers

People subscribed via source and target branches