Merge ~lamoura/ubuntu/+source/ubuntu-advantage-tools:upload-27.8-jammy into ubuntu/+source/ubuntu-advantage-tools:ubuntu/devel
- Git
- lp:~lamoura/ubuntu/+source/ubuntu-advantage-tools
- upload-27.8-jammy
- Merge into ubuntu/devel
Status: | Merged |
---|---|
Merged at revision: | 06882843231c960ea65fdd1fcb2d9f06fec8b071 |
Proposed branch: | ~lamoura/ubuntu/+source/ubuntu-advantage-tools:upload-27.8-jammy |
Merge into: | ubuntu/+source/ubuntu-advantage-tools:ubuntu/devel |
Diff against target: |
3242 lines (+1504/-374) 41 files modified
debian/changelog (+21/-0) features/_version.feature (+1/-1) features/attach_validtoken.feature (+6/-6) features/attached_commands.feature (+23/-18) features/attached_enable.feature (+103/-17) features/aws-ids.yaml (+1/-0) features/azure-ids.yaml (+1/-0) features/enable_fips_vm.feature (+48/-37) features/realtime_kernel.feature (+128/-0) features/staging_commands.feature (+1/-1) features/ubuntu_pro.feature (+9/-9) features/ubuntu_pro_fips.feature (+270/-9) features/ubuntu_upgrade.feature (+1/-2) features/unattached_status.feature (+85/-68) help_data.yaml (+10/-0) lib/upgrade_lts_contract.py (+25/-5) tools/refresh-keyrings.sh (+4/-1) tox.ini (+3/-0) uaclient/clouds/identity.py (+2/-0) uaclient/clouds/tests/test_identity.py (+6/-3) uaclient/config.py (+1/-1) uaclient/contract.py (+1/-1) uaclient/entitlements/__init__.py (+2/-0) uaclient/entitlements/base.py (+19/-9) uaclient/entitlements/cis.py (+1/-1) uaclient/entitlements/fips.py (+69/-44) uaclient/entitlements/livepatch.py (+5/-0) uaclient/entitlements/realtime.py (+84/-0) uaclient/entitlements/tests/test_cc.py (+2/-0) uaclient/entitlements/tests/test_fips.py (+60/-35) uaclient/entitlements/tests/test_livepatch.py (+8/-0) uaclient/entitlements/tests/test_repo.py (+17/-7) uaclient/messages.py (+46/-0) uaclient/status.py (+4/-4) uaclient/tests/test_cli_attach.py (+2/-2) uaclient/tests/test_cli_collect_logs.py (+2/-2) uaclient/tests/test_cli_status.py (+49/-39) uaclient/tests/test_upgrade_lts_contract.py (+67/-1) uaclient/tests/test_util.py (+221/-27) uaclient/util.py (+95/-23) uaclient/version.py (+1/-1) |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Robie Basak | ubuntu-sru | Approve | |
Canonical Server | Pending | ||
Review via email: mp+419498@code.launchpad.net |
Commit message
Description of the change
This MR represents the release of 27.8 for Jammy.
We have already uploaded the new package into our staging PPA:
https:/
And we have already created an SRU bug for it:
https:/
Let us know if there is anything else we need to address here
Sergio Durigan Junior (sergiodj) : | # |
Chad Smith (chad.smith) wrote : | # |
LGTM. Versioning looks good as previous upload to -proposed was rejected.
Sergio Durigan Junior (sergiodj) wrote : | # |
Uploaded:
$ dput ubuntu-
Trying to upload package to ubuntu
Checking signature on .changes
gpg: /home/sergio/
Checking signature on .dsc
gpg: /home/sergio/
Uploading to ubuntu (via ftp to upload.ubuntu.com):
Uploading ubuntu-
Uploading ubuntu-
Uploading ubuntu-
Uploading ubuntu-
Successfully uploaded packages.
Preview Diff
1 | diff --git a/debian/changelog b/debian/changelog |
2 | index b44d4d9..a272000 100644 |
3 | --- a/debian/changelog |
4 | +++ b/debian/changelog |
5 | @@ -1,3 +1,24 @@ |
6 | +ubuntu-advantage-tools (27.8~22.04.1) jammy; urgency=medium |
7 | + |
8 | + * New upstream release 27.8 (LP: #1969125) |
9 | + - entitlements: apply overrides from the contract response |
10 | + - fips: |
11 | + + unhold fips packages when enabling fips-updates |
12 | + + Automatically disable fips service before enabling fips-updates |
13 | + + unhold more packages when enabling fips |
14 | + - lib: fix upgrade script for unsupported releases (LP: #1968067) |
15 | + - realtime: add support for realtime kernel beta service on Jammy |
16 | + |
17 | + -- Lucas Moura <lucas.moura@canonical.com> Wed, 13 Apr 2022 18:17:02 -0300 |
18 | + |
19 | +ubuntu-advantage-tools (27.7.1~22.04.1) jammy; urgency=medium |
20 | + |
21 | + * fips: |
22 | + - make fips service incompatible with fips-updates |
23 | + - unhold more packages when enabling fips |
24 | + |
25 | + -- Lucas Moura <lucas.moura@canonical.com> Thu, 31 Mar 2022 16:18:36 -0300 |
26 | + |
27 | ubuntu-advantage-tools (27.7~22.04.1) jammy; urgency=medium |
28 | |
29 | * d/changelog: |
30 | diff --git a/features/_version.feature b/features/_version.feature |
31 | index b972500..35b73f7 100644 |
32 | --- a/features/_version.feature |
33 | +++ b/features/_version.feature |
34 | @@ -15,7 +15,7 @@ Feature: UA is expected version |
35 | Scenario Outline: Check ua version |
36 | Given a `<release>` machine with ubuntu-advantage-tools installed |
37 | When I run `dpkg-query --showformat='${Version}' --show ubuntu-advantage-tools` with sudo |
38 | - Then stdout matches regexp: |
39 | + Then I will see the following on stdout |
40 | """ |
41 | {UACLIENT_BEHAVE_CHECK_VERSION} |
42 | """ |
43 | diff --git a/features/attach_validtoken.feature b/features/attach_validtoken.feature |
44 | index 25f763b..35fd90f 100644 |
45 | --- a/features/attach_validtoken.feature |
46 | +++ b/features/attach_validtoken.feature |
47 | @@ -11,7 +11,7 @@ Feature: Command behaviour when attaching a machine to an Ubuntu Advantage |
48 | And I run `ua status --all` as non-root |
49 | Then stdout matches regexp: |
50 | """ |
51 | - SERVICE ENTITLED STATUS DESCRIPTION |
52 | + SERVICE +ENTITLED STATUS DESCRIPTION |
53 | cc-eal +yes +n/a +Common Criteria EAL2 Provisioning Packages |
54 | cis +yes +n/a +Security compliance and audit tools |
55 | esm-apps +yes +n/a +UA Apps: Extended Security Maintenance \(ESM\) |
56 | @@ -58,7 +58,7 @@ Feature: Command behaviour when attaching a machine to an Ubuntu Advantage |
57 | """ |
58 | And stdout matches regexp: |
59 | """ |
60 | - SERVICE ENTITLED STATUS DESCRIPTION |
61 | + SERVICE +ENTITLED STATUS DESCRIPTION |
62 | cc-eal +yes +<cc_status> +Common Criteria EAL2 Provisioning Packages |
63 | """ |
64 | And stdout matches regexp: |
65 | @@ -315,7 +315,7 @@ Feature: Command behaviour when attaching a machine to an Ubuntu Advantage |
66 | """ |
67 | And stdout matches regexp: |
68 | """ |
69 | - SERVICE ENTITLED STATUS DESCRIPTION |
70 | + SERVICE +ENTITLED STATUS DESCRIPTION |
71 | cc-eal +yes +<cc_status> +Common Criteria EAL2 Provisioning Packages |
72 | """ |
73 | And stdout matches regexp: |
74 | @@ -375,7 +375,7 @@ Feature: Command behaviour when attaching a machine to an Ubuntu Advantage |
75 | """ |
76 | And stdout matches regexp: |
77 | """ |
78 | - SERVICE ENTITLED STATUS DESCRIPTION |
79 | + SERVICE +ENTITLED STATUS DESCRIPTION |
80 | cc-eal +yes +<cc_status> +Common Criteria EAL2 Provisioning Packages |
81 | """ |
82 | And stdout matches regexp: |
83 | @@ -435,7 +435,7 @@ Feature: Command behaviour when attaching a machine to an Ubuntu Advantage |
84 | """ |
85 | And stdout matches regexp: |
86 | """ |
87 | - SERVICE ENTITLED STATUS DESCRIPTION |
88 | + SERVICE +ENTITLED STATUS DESCRIPTION |
89 | cc-eal +yes +<cc_status> +Common Criteria EAL2 Provisioning Packages |
90 | """ |
91 | And stdout matches regexp: |
92 | @@ -477,7 +477,7 @@ Feature: Command behaviour when attaching a machine to an Ubuntu Advantage |
93 | When I run `ua status` with sudo |
94 | Then stdout matches regexp: |
95 | """ |
96 | - SERVICE ENTITLED STATUS DESCRIPTION |
97 | + SERVICE +ENTITLED STATUS DESCRIPTION |
98 | cc-eal +yes +<cc-eal> +Common Criteria EAL2 Provisioning Packages |
99 | """ |
100 | And stdout matches regexp: |
101 | diff --git a/features/attached_commands.feature b/features/attached_commands.feature |
102 | index dd6cf1a..f3ed252 100644 |
103 | --- a/features/attached_commands.feature |
104 | +++ b/features/attached_commands.feature |
105 | @@ -129,9 +129,9 @@ Feature: Command behaviour when attached to an UA subscription |
106 | |
107 | Examples: ubuntu release |
108 | | release | valid_services | |
109 | - | xenial | cc-eal, cis, esm-apps, esm-infra, fips, fips-updates, livepatch, ros,\nros-updates. | |
110 | - | bionic | cc-eal, cis, esm-apps, esm-infra, fips, fips-updates, livepatch, ros,\nros-updates. | |
111 | - | focal | cc-eal, esm-apps, esm-infra, fips, fips-updates, livepatch, ros,\nros-updates, usg. | |
112 | + | xenial | cc-eal, cis, esm-apps, esm-infra, fips, fips-updates, livepatch,\nrealtime-kernel, ros, ros-updates. | |
113 | + | bionic | cc-eal, cis, esm-apps, esm-infra, fips, fips-updates, livepatch,\nrealtime-kernel, ros, ros-updates. | |
114 | + | focal | cc-eal, esm-apps, esm-infra, fips, fips-updates, livepatch, realtime-kernel,\nros, ros-updates, usg. | |
115 | |
116 | @series.xenial |
117 | @series.bionic |
118 | @@ -148,8 +148,8 @@ Feature: Command behaviour when attached to an UA subscription |
119 | And stderr matches regexp: |
120 | """ |
121 | Cannot disable unknown service 'foobar'. |
122 | - Try cc-eal, cis, esm-apps, esm-infra, fips, fips-updates, livepatch, ros, |
123 | - ros-updates. |
124 | + Try cc-eal, cis, esm-apps, esm-infra, fips, fips-updates, livepatch, |
125 | + realtime-kernel, ros, ros-updates. |
126 | """ |
127 | And I verify that running `ua disable esm-infra` `as non-root` exits `1` |
128 | And stderr matches regexp: |
129 | @@ -187,8 +187,8 @@ Feature: Command behaviour when attached to an UA subscription |
130 | And stderr matches regexp: |
131 | """ |
132 | Cannot disable unknown service 'foobar'. |
133 | - Try cc-eal, esm-apps, esm-infra, fips, fips-updates, livepatch, ros, |
134 | - ros-updates, usg. |
135 | + Try cc-eal, esm-apps, esm-infra, fips, fips-updates, livepatch, realtime-kernel, |
136 | + ros, ros-updates, usg. |
137 | """ |
138 | And I verify that running `ua disable esm-infra` `as non-root` exits `1` |
139 | And stderr matches regexp: |
140 | @@ -231,7 +231,7 @@ Feature: Command behaviour when attached to an UA subscription |
141 | When I run `ua status --all` as non-root |
142 | Then stdout matches regexp: |
143 | """ |
144 | - SERVICE AVAILABLE DESCRIPTION |
145 | + SERVICE +AVAILABLE DESCRIPTION |
146 | cc-eal +<cc-eal> +Common Criteria EAL2 Provisioning Packages |
147 | """ |
148 | Then stdout matches regexp: |
149 | @@ -241,6 +241,7 @@ Feature: Command behaviour when attached to an UA subscription |
150 | fips +<fips> +NIST-certified core packages |
151 | fips-updates +<fips> +NIST-certified core packages with priority security updates |
152 | livepatch +yes +Canonical Livepatch service |
153 | + realtime-kernel +<realtime-kernel> +Beta-version Ubuntu Kernel with PREEMPT_RT patches |
154 | ros +<ros> +Security Updates for the Robot Operating System |
155 | ros-updates +<ros> +All Updates for the Robot Operating System |
156 | """ |
157 | @@ -280,10 +281,10 @@ Feature: Command behaviour when attached to an UA subscription |
158 | """ |
159 | |
160 | Examples: ubuntu release |
161 | - | release | esm-apps | cc-eal | cis | fips | fips-update | ros | cis_or_usg | |
162 | - | xenial | yes | yes | yes | yes | yes | yes | cis | |
163 | - | bionic | yes | yes | yes | yes | yes | yes | cis | |
164 | - | focal | yes | no | yes | yes | yes | no | usg | |
165 | + | release | esm-apps | cc-eal | cis | fips | fips-update | ros | cis_or_usg | realtime-kernel | |
166 | + | xenial | yes | yes | yes | yes | yes | yes | cis | no | |
167 | + | bionic | yes | yes | yes | yes | yes | yes | cis | no | |
168 | + | focal | yes | no | yes | yes | yes | no | usg | no | |
169 | |
170 | @series.all |
171 | @uses.config.machine_type.lxd.container |
172 | @@ -361,8 +362,8 @@ Feature: Command behaviour when attached to an UA subscription |
173 | And I run `ua status --all` with sudo |
174 | Then stdout matches regexp: |
175 | """ |
176 | - SERVICE ENTITLED STATUS DESCRIPTION |
177 | - cc-eal no |
178 | + SERVICE +ENTITLED STATUS DESCRIPTION |
179 | + cc-eal +no |
180 | """ |
181 | When I run `ua --version` as non-root |
182 | Then I will see the uaclient version on stdout with features ` +disable_auto_attach +machine_token_overlay -other` |
183 | @@ -403,8 +404,8 @@ Feature: Command behaviour when attached to an UA subscription |
184 | And stderr matches regexp: |
185 | """ |
186 | Cannot disable unknown service 'foobar'. |
187 | - Try cc-eal, cis, esm-apps, esm-infra, fips, fips-updates, livepatch, ros, |
188 | - ros-updates. |
189 | + Try cc-eal, cis, esm-apps, esm-infra, fips, fips-updates, livepatch, |
190 | + realtime-kernel, ros, ros-updates. |
191 | """ |
192 | When I run `ua status` with sudo |
193 | Then stdout matches regexp: |
194 | @@ -449,8 +450,8 @@ Feature: Command behaviour when attached to an UA subscription |
195 | And stderr matches regexp: |
196 | """ |
197 | Cannot disable unknown service 'foobar'. |
198 | - Try cc-eal, esm-apps, esm-infra, fips, fips-updates, livepatch, ros, |
199 | - ros-updates, usg. |
200 | + Try cc-eal, esm-apps, esm-infra, fips, fips-updates, livepatch, realtime-kernel, |
201 | + ros, ros-updates, usg. |
202 | """ |
203 | When I run `ua status` with sudo |
204 | Then stdout matches regexp: |
205 | @@ -558,6 +559,8 @@ Feature: Command behaviour when attached to an UA subscription |
206 | \(https://ubuntu.com/security/certifications#fips\) |
207 | - livepatch: Canonical Livepatch service |
208 | \(https://ubuntu.com/security/livepatch\) |
209 | + - realtime-kernel: Beta-version Ubuntu Kernel with PREEMPT_RT patches |
210 | + \(https://ubuntu.com/realtime-kernel\) |
211 | - ros-updates: All Updates for the Robot Operating System |
212 | \(https://ubuntu.com/robotics/ros-esm\) |
213 | - ros: Security Updates for the Robot Operating System |
214 | @@ -657,6 +660,8 @@ Feature: Command behaviour when attached to an UA subscription |
215 | \(https://ubuntu.com/security/certifications#fips\) |
216 | - livepatch: Canonical Livepatch service |
217 | \(https://ubuntu.com/security/livepatch\) |
218 | + - realtime-kernel: Beta-version Ubuntu Kernel with PREEMPT_RT patches |
219 | + \(https://ubuntu.com/realtime-kernel\) |
220 | - ros-updates: All Updates for the Robot Operating System |
221 | \(https://ubuntu.com/robotics/ros-esm\) |
222 | - ros: Security Updates for the Robot Operating System |
223 | diff --git a/features/attached_enable.feature b/features/attached_enable.feature |
224 | index 90a62cb..7944100 100644 |
225 | --- a/features/attached_enable.feature |
226 | +++ b/features/attached_enable.feature |
227 | @@ -669,7 +669,7 @@ Feature: Enable command behaviour when attached to an UA subscription |
228 | And stdout is a json matching the `ua_operation` schema |
229 | And I will see the following on stdout: |
230 | """ |
231 | - {"_schema_version": "0.1", "errors": [{"message": "Cannot enable FIPS when Livepatch is enabled.", "service": "fips", "type": "service"}], "failed_services": ["fips"], "needs_reboot": false, "processed_services": [], "result": "failure", "warnings": []} |
232 | + {"_schema_version": "0.1", "errors": [{"message": "Cannot enable FIPS when Livepatch is enabled.", "message_code": "incompatible-service-stops-enable", "service": "fips", "type": "service"}], "failed_services": ["fips"], "needs_reboot": false, "processed_services": [], "result": "failure", "warnings": []} |
233 | """ |
234 | |
235 | @slow |
236 | @@ -693,6 +693,7 @@ Feature: Enable command behaviour when attached to an UA subscription |
237 | Then I will see the following on stdout |
238 | """ |
239 | One moment, checking your subscription first |
240 | + Disabling incompatible service: Livepatch |
241 | Updating package lists |
242 | Installing FIPS packages |
243 | FIPS enabled |
244 | @@ -761,21 +762,21 @@ Feature: Enable command behaviour when attached to an UA subscription |
245 | And I run `ua status --all` as non-root |
246 | Then stdout matches regexp |
247 | """ |
248 | - ros yes disabled Security Updates for the Robot Operating System |
249 | + ros +yes disabled Security Updates for the Robot Operating System |
250 | """ |
251 | When I run `ua enable ros --assume-yes --beta` with sudo |
252 | And I run `ua status --all` as non-root |
253 | Then stdout matches regexp |
254 | """ |
255 | - ros yes enabled Security Updates for the Robot Operating System |
256 | + ros +yes enabled Security Updates for the Robot Operating System |
257 | """ |
258 | And stdout matches regexp |
259 | """ |
260 | - esm-apps yes enabled UA Apps: Extended Security Maintenance \(ESM\) |
261 | + esm-apps +yes enabled UA Apps: Extended Security Maintenance \(ESM\) |
262 | """ |
263 | And stdout matches regexp |
264 | """ |
265 | - esm-infra yes enabled UA Infra: Extended Security Maintenance \(ESM\) |
266 | + esm-infra +yes enabled UA Infra: Extended Security Maintenance \(ESM\) |
267 | """ |
268 | When I verify that running `ua disable esm-apps` `with sudo` and stdin `N` exits `1` |
269 | Then stdout matches regexp |
270 | @@ -793,11 +794,11 @@ Feature: Enable command behaviour when attached to an UA subscription |
271 | When I run `ua status --all` as non-root |
272 | Then stdout matches regexp |
273 | """ |
274 | - ros yes disabled Security Updates for the Robot Operating System |
275 | + ros +yes disabled Security Updates for the Robot Operating System |
276 | """ |
277 | And stdout matches regexp |
278 | """ |
279 | - esm-apps yes disabled UA Apps: Extended Security Maintenance \(ESM\) |
280 | + esm-apps +yes disabled UA Apps: Extended Security Maintenance \(ESM\) |
281 | """ |
282 | When I verify that running `ua enable ros --beta` `with sudo` and stdin `N` exits `1` |
283 | Then stdout matches regexp |
284 | @@ -818,15 +819,15 @@ Feature: Enable command behaviour when attached to an UA subscription |
285 | When I run `ua status --all` as non-root |
286 | Then stdout matches regexp |
287 | """ |
288 | - ros yes enabled Security Updates for the Robot Operating System |
289 | + ros +yes enabled Security Updates for the Robot Operating System |
290 | """ |
291 | And stdout matches regexp |
292 | """ |
293 | - esm-apps yes enabled UA Apps: Extended Security Maintenance \(ESM\) |
294 | + esm-apps +yes enabled UA Apps: Extended Security Maintenance \(ESM\) |
295 | """ |
296 | And stdout matches regexp |
297 | """ |
298 | - esm-infra yes enabled UA Infra: Extended Security Maintenance \(ESM\) |
299 | + esm-infra +yes enabled UA Infra: Extended Security Maintenance \(ESM\) |
300 | """ |
301 | When I run `apt-cache policy` as non-root |
302 | Then apt-cache policy for the following url has permission `500` |
303 | @@ -840,7 +841,7 @@ Feature: Enable command behaviour when attached to an UA subscription |
304 | And I run `ua status --all` as non-root |
305 | Then stdout matches regexp |
306 | """ |
307 | - ros-updates yes enabled All Updates for the Robot Operating System |
308 | + ros-updates +yes enabled All Updates for the Robot Operating System |
309 | """ |
310 | When I run `apt-cache policy` as non-root |
311 | Then apt-cache policy for the following url has permission `500` |
312 | @@ -869,11 +870,11 @@ Feature: Enable command behaviour when attached to an UA subscription |
313 | When I run `ua status --all` as non-root |
314 | Then stdout matches regexp |
315 | """ |
316 | - ros-updates yes enabled All Updates for the Robot Operating System |
317 | + ros-updates +yes enabled All Updates for the Robot Operating System |
318 | """ |
319 | And stdout matches regexp |
320 | """ |
321 | - ros yes enabled Security Updates for the Robot Operating System |
322 | + ros +yes enabled Security Updates for the Robot Operating System |
323 | """ |
324 | When I run `ua disable ros-updates --assume-yes` with sudo |
325 | When I run `ua disable ros --assume-yes` with sudo |
326 | @@ -883,19 +884,19 @@ Feature: Enable command behaviour when attached to an UA subscription |
327 | When I run `ua status --all` as non-root |
328 | Then stdout matches regexp |
329 | """ |
330 | - ros-updates yes enabled All Updates for the Robot Operating System |
331 | + ros-updates +yes enabled All Updates for the Robot Operating System |
332 | """ |
333 | And stdout matches regexp |
334 | """ |
335 | - ros yes enabled Security Updates for the Robot Operating System |
336 | + ros +yes enabled Security Updates for the Robot Operating System |
337 | """ |
338 | And stdout matches regexp |
339 | """ |
340 | - esm-apps yes enabled UA Apps: Extended Security Maintenance \(ESM\) |
341 | + esm-apps +yes enabled UA Apps: Extended Security Maintenance \(ESM\) |
342 | """ |
343 | And stdout matches regexp |
344 | """ |
345 | - esm-infra yes enabled UA Infra: Extended Security Maintenance \(ESM\) |
346 | + esm-infra +yes enabled UA Infra: Extended Security Maintenance \(ESM\) |
347 | """ |
348 | When I run `ua detach` `with sudo` and stdin `y` |
349 | Then stdout matches regexp: |
350 | @@ -911,3 +912,88 @@ Feature: Enable command behaviour when attached to an UA subscription |
351 | | release | ros-security-source | ros-updates-source | |
352 | | xenial | https://esm.ubuntu.com/ros/ubuntu xenial-security/main | https://esm.ubuntu.com/ros-updates/ubuntu xenial-updates/main | |
353 | | bionic | https://esm.ubuntu.com/ros/ubuntu bionic-security/main | https://esm.ubuntu.com/ros-updates/ubuntu bionic-updates/main | |
354 | + |
355 | + # Overall test for overrides; in the future, when many services |
356 | + # have overrides, we can consider removing this |
357 | + # FIPS is a good choice because we expect to have it |
358 | + @series.focal |
359 | + @uses.config.machine_type.aws.generic |
360 | + Scenario: Cloud overrides for a generic aws Focal instance |
361 | + Given a `focal` machine with ubuntu-advantage-tools installed |
362 | + When I create the file `/tmp/machine-token-overlay.json` with the following: |
363 | + """ |
364 | + { |
365 | + "machineTokenInfo": { |
366 | + "contractInfo": { |
367 | + "resourceEntitlements": [ |
368 | + { |
369 | + "type": "fips", |
370 | + "entitled": true, |
371 | + "affordances": { |
372 | + "architectures": [ |
373 | + "amd64", |
374 | + "ppc64el", |
375 | + "ppc64le", |
376 | + "s390x", |
377 | + "x86_64" |
378 | + ], |
379 | + "series": [ |
380 | + "xenial", |
381 | + "bionic", |
382 | + "focal" |
383 | + ] |
384 | + }, |
385 | + "directives": { |
386 | + "additionalPackages": [ |
387 | + "ubuntu-fips" |
388 | + ], |
389 | + "aptKey": "E23341B2A1467EDBF07057D6C1997C40EDE22758", |
390 | + "aptURL": "https://esm.ubuntu.com/fips", |
391 | + "suites": [ |
392 | + "xenial", |
393 | + "bionic", |
394 | + "focal" |
395 | + ] |
396 | + }, |
397 | + "obligations": { |
398 | + "enableByDefault": false |
399 | + }, |
400 | + "overrides": [ |
401 | + { |
402 | + "selector": { |
403 | + "series": "focal" |
404 | + }, |
405 | + "directives": { |
406 | + "additionalPackages": [ |
407 | + "some-package-focal" |
408 | + ] |
409 | + } |
410 | + }, |
411 | + { |
412 | + "selector": { |
413 | + "cloud": "aws" |
414 | + }, |
415 | + "directives": { |
416 | + "additionalPackages": [ |
417 | + "some-package-aws" |
418 | + ] |
419 | + } |
420 | + } |
421 | + ] |
422 | + } |
423 | + ] |
424 | + } |
425 | + } |
426 | + } |
427 | + """ |
428 | + And I append the following on uaclient config: |
429 | + """ |
430 | + features: |
431 | + machine_token_overlay: "/tmp/machine-token-overlay.json" |
432 | + """ |
433 | + And I attach `contract_token` with sudo |
434 | + And I verify that running `ua enable fips --assume-yes` `with sudo` exits `1` |
435 | + Then stderr matches regexp: |
436 | + """ |
437 | + Stderr: E: Unable to locate package some-package-aws |
438 | + """ |
439 | diff --git a/features/aws-ids.yaml b/features/aws-ids.yaml |
440 | index f2376ad..ec6c43c 100644 |
441 | --- a/features/aws-ids.yaml |
442 | +++ b/features/aws-ids.yaml |
443 | @@ -3,3 +3,4 @@ bionic-fips: ami-03b75f613f80bcff1 |
444 | focal: ami-0489b8bdbbf3a3b32 |
445 | xenial: ami-011bcfe2bea365b6a |
446 | xenial-fips: ami-077e4c339a098fc9f |
447 | +focal-fips: ami-02782bf2569bf457c |
448 | diff --git a/features/azure-ids.yaml b/features/azure-ids.yaml |
449 | index 735223f..10b1155 100644 |
450 | --- a/features/azure-ids.yaml |
451 | +++ b/features/azure-ids.yaml |
452 | @@ -3,3 +3,4 @@ focal: "Canonical:0001-com-ubuntu-pro-focal:pro-20_04-lts" |
453 | xenial: "Canonical:0001-com-ubuntu-pro-xenial:pro-16_04-lts" |
454 | bionic-fips: "Canonical:0001-com-ubuntu-pro-bionic-fips:pro-fips-18_04" |
455 | xenial-fips: "Canonical:0001-com-ubuntu-pro-xenial-fips:pro-fips-16_04-private" |
456 | +focal-fips: "Canonical:0001-com-ubuntu-pro-focal-fips:pro-fips-20_04" |
457 | diff --git a/features/enable_fips_vm.feature b/features/enable_fips_vm.feature |
458 | index a055354..03ccd39 100644 |
459 | --- a/features/enable_fips_vm.feature |
460 | +++ b/features/enable_fips_vm.feature |
461 | @@ -462,14 +462,11 @@ Feature: FIPS enablement in lxd VMs |
462 | | focal | FIPS Updates | fips-updates |https://esm.ubuntu.com/fips-updates/ubuntu focal-updates/main | |
463 | |
464 | @slow |
465 | - @series.xenial |
466 | - @series.bionic |
467 | + @series.lts |
468 | @uses.config.machine_type.lxd.vm |
469 | Scenario Outline: Attached enable fips-updates on fips enabled vm |
470 | Given a `<release>` machine with ubuntu-advantage-tools installed |
471 | When I attach `contract_token` with sudo |
472 | - And I run `ua disable livepatch` with sudo |
473 | - And I run `DEBIAN_FRONTEND=noninteractive apt-get install -o Dpkg::Options::="--force-confdef" -o Dpkg::Options::="--force-confold" -y openssh-client openssh-server strongswan` with sudo, retrying exit [100] |
474 | And I run `ua enable fips --assume-yes` with sudo |
475 | Then stdout matches regexp: |
476 | """ |
477 | @@ -484,47 +481,61 @@ Feature: FIPS enablement in lxd VMs |
478 | fips +yes enabled |
479 | """ |
480 | When I reboot the `<release>` machine |
481 | - And I run `ua enable fips-updates --assume-yes` with sudo |
482 | + And I run `uname -r` as non-root |
483 | Then stdout matches regexp: |
484 | """ |
485 | - Updating package lists |
486 | - Installing FIPS Updates packages |
487 | - FIPS Updates enabled |
488 | - A reboot is required to complete install |
489 | + fips |
490 | """ |
491 | - When I run `ua status --all` with sudo |
492 | + When I verify that running `ua enable fips-updates --assume-yes` `with sudo` exits `0` |
493 | Then stdout matches regexp: |
494 | """ |
495 | - fips +yes n/a |
496 | - """ |
497 | - And stdout matches regexp: |
498 | - """ |
499 | - fips-updates +yes enabled |
500 | - """ |
501 | - When I reboot the `<release>` machine |
502 | - Then I verify that running `apt update` `with sudo` exits `0` |
503 | - And I verify that `ubuntu-fips` is installed from apt source `<fips-apt-source>` |
504 | - And I verify that `openssh-server` is installed from apt source `<fips-apt-source>` |
505 | - And I verify that `openssh-client` is installed from apt source `<fips-apt-source>` |
506 | - And I verify that `strongswan` is installed from apt source `<fips-apt-source>` |
507 | - And I verify that `openssh-server-hmac` is installed from apt source `<fips-apt-source>` |
508 | - And I verify that `openssh-client-hmac` is installed from apt source `<fips-apt-source>` |
509 | - And I verify that `strongswan-hmac` is installed from apt source `<fips-apt-source>` |
510 | - When I run `uname -r` as non-root |
511 | - Then stdout matches regexp: |
512 | - """ |
513 | - fips |
514 | + One moment, checking your subscription first |
515 | + Disabling incompatible service: FIPS |
516 | + Updating package lists |
517 | + Installing FIPS Updates packages |
518 | + FIPS Updates enabled |
519 | + A reboot is required to complete install. |
520 | + """ |
521 | + When I run `ua status --all` with sudo |
522 | + Then stdout matches regexp: |
523 | + """ |
524 | + fips-updates +yes enabled |
525 | + """ |
526 | + And stdout matches regexp: |
527 | + """ |
528 | + fips +yes n/a |
529 | + """ |
530 | + When I reboot the `<release>` machine |
531 | + And I run `ua enable livepatch` with sudo |
532 | + And I run `ua status --all` with sudo |
533 | + Then stdout matches regexp: |
534 | + """ |
535 | + fips-updates +yes enabled |
536 | + """ |
537 | + And stdout matches regexp: |
538 | + """ |
539 | + fips +yes n/a |
540 | + """ |
541 | + And stdout matches regexp: |
542 | + """ |
543 | + livepatch +yes enabled |
544 | + """ |
545 | + When I run `uname -r` as non-root |
546 | + Then stdout matches regexp: |
547 | + """ |
548 | + fips |
549 | + """ |
550 | + When I run `cat /proc/sys/crypto/fips_enabled` with sudo |
551 | + Then I will see the following on stdout: |
552 | + """ |
553 | + 1 |
554 | """ |
555 | - When I run `cat /proc/sys/crypto/fips_enabled` with sudo |
556 | - Then I will see the following on stdout: |
557 | - """ |
558 | - 1 |
559 | - """ |
560 | |
561 | Examples: ubuntu release |
562 | - | release | fips-apt-source | |
563 | - | xenial | https://esm.ubuntu.com/fips-updates/ubuntu xenial-updates/main | |
564 | - | bionic | https://esm.ubuntu.com/fips-updates/ubuntu bionic-updates/main | |
565 | + | release | |
566 | + | xenial | |
567 | + | bionic | |
568 | + | focal | |
569 | |
570 | @slow |
571 | @series.xenial |
572 | diff --git a/features/realtime_kernel.feature b/features/realtime_kernel.feature |
573 | new file mode 100644 |
574 | index 0000000..a04664c |
575 | --- /dev/null |
576 | +++ b/features/realtime_kernel.feature |
577 | @@ -0,0 +1,128 @@ |
578 | +@uses.config.contract_token |
579 | +Feature: Enable command behaviour when attached to an UA subscription |
580 | + |
581 | + @series.jammy |
582 | + @uses.config.machine_type.lxd.container |
583 | + Scenario Outline: Enable Real-Time Kernel service in a container |
584 | + Given a `<release>` machine with ubuntu-advantage-tools installed |
585 | + When I attach `contract_token` with sudo |
586 | + Then I verify that running `ua enable realtime-kernel` `as non-root` exits `1` |
587 | + And I will see the following on stderr: |
588 | + """ |
589 | + This command must be run as root (try using sudo). |
590 | + """ |
591 | + Then I verify that running `ua enable realtime-kernel --beta` `with sudo` exits `1` |
592 | + Then I will see the following on stdout: |
593 | + """ |
594 | + One moment, checking your subscription first |
595 | + Cannot install Real-Time Kernel on a container. |
596 | + """ |
597 | + Examples: ubuntu release |
598 | + | release | |
599 | + | jammy | |
600 | + |
601 | + @series.lts |
602 | + @uses.config.machine_type.lxd.vm |
603 | + Scenario Outline: Enable Real-Time Kernel service on unsupported release |
604 | + Given a `<release>` machine with ubuntu-advantage-tools installed |
605 | + When I attach `contract_token` with sudo |
606 | + Then I verify that running `ua enable realtime-kernel` `as non-root` exits `1` |
607 | + And I will see the following on stderr: |
608 | + """ |
609 | + This command must be run as root (try using sudo). |
610 | + """ |
611 | + Then I verify that running `ua enable realtime-kernel --beta` `with sudo` exits `1` |
612 | + Then I will see the following on stdout: |
613 | + """ |
614 | + One moment, checking your subscription first |
615 | + Real-Time Kernel is not available for Ubuntu <version> (<full_name>). |
616 | + """ |
617 | + Examples: ubuntu release |
618 | + | release | version | full_name | |
619 | + | xenial | 16.04 LTS | Xenial Xerus | |
620 | + | bionic | 18.04 LTS | Bionic Beaver | |
621 | + | focal | 20.04 LTS | Focal Fossa | |
622 | + | jammy | 22.04 | Jammy Jellyfish | |
623 | + |
624 | + @series.jammy |
625 | + @uses.config.machine_type.gcp.generic |
626 | + Scenario Outline: Enable Real-Time Kernel service |
627 | + Given a `<release>` machine with ubuntu-advantage-tools installed |
628 | + When I create the file `/home/ubuntu/machine-token-overlay.json` with the following: |
629 | + """ |
630 | + { |
631 | + "machineTokenInfo": { |
632 | + "contractInfo": { |
633 | + "resourceEntitlements": [ |
634 | + { |
635 | + "type": "realtime-kernel", |
636 | + "affordances": { |
637 | + "series": ["jammy"] |
638 | + } |
639 | + } |
640 | + ] |
641 | + } |
642 | + } |
643 | + } |
644 | + """ |
645 | + And I append the following on uaclient config: |
646 | + """ |
647 | + features: |
648 | + machine_token_overlay: "/home/ubuntu/machine-token-overlay.json" |
649 | + """ |
650 | + When I attach `contract_token` with sudo |
651 | + And I run `ua disable livepatch --assume-yes` with sudo |
652 | + Then I verify that running `ua enable realtime-kernel` `as non-root` exits `1` |
653 | + And I will see the following on stderr: |
654 | + """ |
655 | + This command must be run as root (try using sudo). |
656 | + """ |
657 | + Then I verify that running `ua enable realtime-kernel` `with sudo` exits `1` |
658 | + And stderr matches regexp: |
659 | + """ |
660 | + Cannot enable unknown service 'realtime-kernel'. |
661 | + """ |
662 | + When I run `ua enable realtime-kernel --beta` `with sudo` and stdin `y` |
663 | + Then stdout matches regexp: |
664 | + """ |
665 | + One moment, checking your subscription first |
666 | + The real-time kernel is a beta version of the 22.04 Ubuntu kernel with the |
667 | + PREEMPT_RT patchset integrated for x86_64 and ARM64. |
668 | + |
669 | + .*You will not be able to revert to your original kernel after enabling real-time..* |
670 | + |
671 | + Do you want to continue\? \[ default = Yes \]: \(Y/n\) Updating package lists |
672 | + Installing Real-Time Kernel packages |
673 | + Real-Time Kernel enabled |
674 | + A reboot is required to complete install. |
675 | + """ |
676 | + When I run `apt-cache policy linux-realtime` as non-root |
677 | + Then stdout does not match regexp: |
678 | + """ |
679 | + .*Installed: \(none\) |
680 | + """ |
681 | + And stdout matches regexp: |
682 | + """ |
683 | + \s* 500 https://esm.ubuntu.com/realtime/ubuntu <release>/main amd64 Packages |
684 | + """ |
685 | + When I verify that running `ua enable realtime-kernel --beta` `with sudo` exits `1` |
686 | + Then stdout matches regexp |
687 | + """ |
688 | + One moment, checking your subscription first |
689 | + Real-Time Kernel is already enabled. |
690 | + See: sudo ua status |
691 | + """ |
692 | + When I reboot the `<release>` machine |
693 | + When I run `uname -r` as non-root |
694 | + Then stdout matches regexp: |
695 | + """ |
696 | + realtime |
697 | + """ |
698 | + When I run `ua disable realtime-kernel` `with sudo` and stdin `y` |
699 | + Then stdout matches regexp: |
700 | + """ |
701 | + This will disable the Real-Time Kernel entitlement but the Real-Time Kernel will remain installed. |
702 | + """ |
703 | + Examples: ubuntu release |
704 | + | release | |
705 | + | jammy | |
706 | diff --git a/features/staging_commands.feature b/features/staging_commands.feature |
707 | index 360b329..23aed73 100644 |
708 | --- a/features/staging_commands.feature |
709 | +++ b/features/staging_commands.feature |
710 | @@ -9,7 +9,7 @@ Feature: Enable command behaviour when attached to an UA staging subscription |
711 | And I run `ua status --all` as non-root |
712 | Then stdout matches regexp |
713 | """ |
714 | - esm-apps yes enabled UA Apps: Extended Security Maintenance \(ESM\) |
715 | + esm-apps +yes enabled UA Apps: Extended Security Maintenance \(ESM\) |
716 | """ |
717 | And I verify that running `apt update` `with sudo` exits `0` |
718 | When I run `apt-cache policy` as non-root |
719 | diff --git a/features/ubuntu_pro.feature b/features/ubuntu_pro.feature |
720 | index 04ef4fc..0f336ef 100644 |
721 | --- a/features/ubuntu_pro.feature |
722 | +++ b/features/ubuntu_pro.feature |
723 | @@ -25,7 +25,7 @@ Feature: Command behaviour when auto-attached in an ubuntu PRO image |
724 | When I run `ua auto-attach` with sudo |
725 | Then stdout matches regexp: |
726 | """ |
727 | - SERVICE ENTITLED STATUS DESCRIPTION |
728 | + SERVICE +ENTITLED STATUS DESCRIPTION |
729 | cc-eal +yes +<cc-eal-s> +Common Criteria EAL2 Provisioning Packages |
730 | """ |
731 | Then stdout matches regexp: |
732 | @@ -96,7 +96,7 @@ Feature: Command behaviour when auto-attached in an ubuntu PRO image |
733 | When I run `ua auto-attach` with sudo |
734 | Then stdout matches regexp: |
735 | """ |
736 | - SERVICE ENTITLED STATUS DESCRIPTION |
737 | + SERVICE +ENTITLED STATUS DESCRIPTION |
738 | cc-eal +yes +<cc-eal-s> +Common Criteria EAL2 Provisioning Packages |
739 | """ |
740 | Then stdout matches regexp: |
741 | @@ -167,7 +167,7 @@ Feature: Command behaviour when auto-attached in an ubuntu PRO image |
742 | When I run `ua auto-attach` with sudo |
743 | Then stdout matches regexp: |
744 | """ |
745 | - SERVICE ENTITLED STATUS DESCRIPTION |
746 | + SERVICE +ENTITLED STATUS DESCRIPTION |
747 | cc-eal +yes +<cc-eal-s> +Common Criteria EAL2 Provisioning Packages |
748 | """ |
749 | Then stdout matches regexp: |
750 | @@ -228,7 +228,7 @@ Feature: Command behaviour when auto-attached in an ubuntu PRO image |
751 | And I run `ua status --wait` as non-root |
752 | Then stdout matches regexp: |
753 | """ |
754 | - SERVICE ENTITLED STATUS DESCRIPTION |
755 | + SERVICE +ENTITLED STATUS DESCRIPTION |
756 | cc-eal +yes +<cc-eal-s> +Common Criteria EAL2 Provisioning Packages |
757 | """ |
758 | Then stdout matches regexp: |
759 | @@ -246,7 +246,7 @@ Feature: Command behaviour when auto-attached in an ubuntu PRO image |
760 | When I run `ua status --all` as non-root |
761 | Then stdout matches regexp: |
762 | """ |
763 | - SERVICE ENTITLED STATUS DESCRIPTION |
764 | + SERVICE +ENTITLED STATUS DESCRIPTION |
765 | cc-eal +yes +<cc-eal-s> +Common Criteria EAL2 Provisioning Packages |
766 | """ |
767 | Then stdout matches regexp: |
768 | @@ -362,7 +362,7 @@ Feature: Command behaviour when auto-attached in an ubuntu PRO image |
769 | And I run `ua status` as non-root |
770 | Then stdout matches regexp: |
771 | """ |
772 | - SERVICE ENTITLED STATUS DESCRIPTION |
773 | + SERVICE +ENTITLED STATUS DESCRIPTION |
774 | cc-eal +yes +<cc-eal-s> +Common Criteria EAL2 Provisioning Packages |
775 | """ |
776 | Then stdout matches regexp: |
777 | @@ -380,7 +380,7 @@ Feature: Command behaviour when auto-attached in an ubuntu PRO image |
778 | When I run `ua status --all` as non-root |
779 | Then stdout matches regexp: |
780 | """ |
781 | - SERVICE ENTITLED STATUS DESCRIPTION |
782 | + SERVICE +ENTITLED STATUS DESCRIPTION |
783 | cc-eal +yes +<cc-eal-s> +Common Criteria EAL2 Provisioning Packages |
784 | """ |
785 | Then stdout matches regexp: |
786 | @@ -496,7 +496,7 @@ Feature: Command behaviour when auto-attached in an ubuntu PRO image |
787 | And I run `ua status` as non-root |
788 | Then stdout matches regexp: |
789 | """ |
790 | - SERVICE ENTITLED STATUS DESCRIPTION |
791 | + SERVICE +ENTITLED STATUS DESCRIPTION |
792 | cc-eal +yes +<cc-eal-s> +Common Criteria EAL2 Provisioning Packages |
793 | """ |
794 | Then stdout matches regexp: |
795 | @@ -514,7 +514,7 @@ Feature: Command behaviour when auto-attached in an ubuntu PRO image |
796 | When I run `ua status --all` as non-root |
797 | Then stdout matches regexp: |
798 | """ |
799 | - SERVICE ENTITLED STATUS DESCRIPTION |
800 | + SERVICE +ENTITLED STATUS DESCRIPTION |
801 | cc-eal +yes +<cc-eal-s> +Common Criteria EAL2 Provisioning Packages |
802 | """ |
803 | Then stdout matches regexp: |
804 | diff --git a/features/ubuntu_pro_fips.feature b/features/ubuntu_pro_fips.feature |
805 | index 7a18b03..1e83ee3 100644 |
806 | --- a/features/ubuntu_pro_fips.feature |
807 | +++ b/features/ubuntu_pro_fips.feature |
808 | @@ -26,12 +26,6 @@ Feature: Command behaviour when auto-attached in an ubuntu PRO fips image |
809 | """ |
810 | And I verify that running `apt update` `with sudo` exits `0` |
811 | And I verify that running `grep Traceback /var/log/ubuntu-advantage.log` `with sudo` exits `1` |
812 | - And I verify that `openssh-server` is installed from apt source `<fips-apt-source>` |
813 | - And I verify that `openssh-client` is installed from apt source `<fips-apt-source>` |
814 | - And I verify that `strongswan` is installed from apt source `<fips-apt-source>` |
815 | - And I verify that `openssh-server-hmac` is installed from apt source `<fips-apt-source>` |
816 | - And I verify that `openssh-client-hmac` is installed from apt source `<fips-apt-source>` |
817 | - And I verify that `strongswan-hmac` is installed from apt source `<fips-apt-source>` |
818 | When I run `uname -r` as non-root |
819 | Then stdout matches regexp: |
820 | """ |
821 | @@ -79,6 +73,10 @@ Feature: Command behaviour when auto-attached in an ubuntu PRO fips image |
822 | """ |
823 | https://esm.ubuntu.com/apps/ubuntu <release>-apps-security/main amd64 Packages |
824 | """ |
825 | + And apt-cache policy for the following url has permission `1001` |
826 | + """ |
827 | + <fips-apt-source> amd64 Packages |
828 | + """ |
829 | And I verify that running `apt update` `with sudo` exits `0` |
830 | When I run `apt install -y <infra-pkg>/<release>-infra-security` with sudo, retrying exit [100] |
831 | And I run `apt-cache policy <infra-pkg>` as non-root |
832 | @@ -99,15 +97,48 @@ Feature: Command behaviour when auto-attached in an ubuntu PRO fips image |
833 | \s*\*\*\* .* 500 |
834 | \s*500 https://esm.ubuntu.com/apps/ubuntu <release>-apps-security/main amd64 Packages |
835 | """ |
836 | + When I run `ua enable fips-updates --assume-yes` with sudo |
837 | + Then I will see the following on stdout: |
838 | + """ |
839 | + One moment, checking your subscription first |
840 | + Disabling incompatible service: FIPS |
841 | + Updating package lists |
842 | + Installing FIPS Updates packages |
843 | + FIPS Updates enabled |
844 | + A reboot is required to complete install. |
845 | + """ |
846 | + When I run `ua status` with sudo |
847 | + Then stdout matches regexp: |
848 | + """ |
849 | + fips +yes +n/a +NIST-certified core packages |
850 | + fips-updates +yes +enabled +NIST-certified core packages with priority security updates |
851 | + """ |
852 | + When I reboot the `<release>` machine |
853 | + And I run `uname -r` as non-root |
854 | + Then stdout matches regexp: |
855 | + """ |
856 | + <fips-kernel-version> |
857 | + """ |
858 | + When I run `apt-cache policy ubuntu-azure-fips` as non-root |
859 | + Then stdout does not match regexp: |
860 | + """ |
861 | + .*Installed: \(none\) |
862 | + """ |
863 | + When I run `cat /proc/sys/crypto/fips_enabled` with sudo |
864 | + Then I will see the following on stdout: |
865 | + """ |
866 | + 1 |
867 | + """ |
868 | |
869 | Examples: ubuntu release |
870 | | release | infra-pkg | apps-pkg | fips-apt-source | fips-kernel-version | |
871 | | xenial | libkrad0 | jq | https://esm.ubuntu.com/fips/ubuntu xenial/main | fips | |
872 | | bionic | libkrad0 | bundler | https://esm.ubuntu.com/fips/ubuntu bionic/main | azure-fips | |
873 | + | focal | hello | 389-ds | https://esm.ubuntu.com/fips/ubuntu focal/main | azure-fips | |
874 | |
875 | - @series.lts |
876 | - @uses.config.machine_type.aws.pro.fips |
877 | - Scenario Outline: Check fips is enabled correctly on Ubuntu pro fips AWS machine |
878 | + @series.focal |
879 | + @uses.config.machine_type.azure.pro.fips |
880 | + Scenario Outline: Check fips packages are correctly installed on Azure Focal machine |
881 | Given a `<release>` machine with ubuntu-advantage-tools installed |
882 | When I create the file `/etc/ubuntu-advantage/uaclient.conf` with the following: |
883 | """ |
884 | @@ -115,6 +146,44 @@ Feature: Command behaviour when auto-attached in an ubuntu PRO fips image |
885 | data_dir: /var/lib/ubuntu-advantage |
886 | log_level: debug |
887 | log_file: /var/log/ubuntu-advantage.log |
888 | + features: |
889 | + allow_xenial_fips_on_cloud: true |
890 | + """ |
891 | + And I run `ua auto-attach` with sudo |
892 | + And I run `ua status --wait` as non-root |
893 | + And I run `ua status` as non-root |
894 | + Then stdout matches regexp: |
895 | + """ |
896 | + esm-apps +yes +enabled +UA Apps: Extended Security Maintenance \(ESM\) |
897 | + esm-infra +yes +enabled +UA Infra: Extended Security Maintenance \(ESM\) |
898 | + fips +yes +enabled +NIST-certified core packages |
899 | + fips-updates +yes +disabled +NIST-certified core packages with priority security updates |
900 | + livepatch +yes +n/a +Canonical Livepatch service |
901 | + """ |
902 | + And I verify that running `apt update` `with sudo` exits `0` |
903 | + And I verify that running `grep Traceback /var/log/ubuntu-advantage.log` `with sudo` exits `1` |
904 | + And I verify that `openssh-server` is installed from apt source `<fips-apt-source>` |
905 | + And I verify that `openssh-client` is installed from apt source `<fips-apt-source>` |
906 | + And I verify that `strongswan` is installed from apt source `<fips-apt-source>` |
907 | + And I verify that `strongswan-hmac` is installed from apt source `<fips-apt-source>` |
908 | + |
909 | + Examples: ubuntu release |
910 | + | release | fips-apt-source | |
911 | + | focal | https://esm.ubuntu.com/fips/ubuntu focal/main | |
912 | + |
913 | + @series.xenial |
914 | + @series.bionic |
915 | + @uses.config.machine_type.azure.pro.fips |
916 | + Scenario Outline: Check fips packages are correctly installed on Azure Bionic & Xenial machines |
917 | + Given a `<release>` machine with ubuntu-advantage-tools installed |
918 | + When I create the file `/etc/ubuntu-advantage/uaclient.conf` with the following: |
919 | + """ |
920 | + contract_url: 'https://contracts.canonical.com' |
921 | + data_dir: /var/lib/ubuntu-advantage |
922 | + log_level: debug |
923 | + log_file: /var/log/ubuntu-advantage.log |
924 | + features: |
925 | + allow_xenial_fips_on_cloud: true |
926 | """ |
927 | And I run `ua auto-attach` with sudo |
928 | And I run `ua status --wait` as non-root |
929 | @@ -135,6 +204,36 @@ Feature: Command behaviour when auto-attached in an ubuntu PRO fips image |
930 | And I verify that `openssh-server-hmac` is installed from apt source `<fips-apt-source>` |
931 | And I verify that `openssh-client-hmac` is installed from apt source `<fips-apt-source>` |
932 | And I verify that `strongswan-hmac` is installed from apt source `<fips-apt-source>` |
933 | + |
934 | + Examples: ubuntu release |
935 | + | release | fips-apt-source | |
936 | + | xenial | https://esm.ubuntu.com/fips/ubuntu xenial/main | |
937 | + | bionic | https://esm.ubuntu.com/fips/ubuntu bionic/main | |
938 | + |
939 | + @series.lts |
940 | + @uses.config.machine_type.aws.pro.fips |
941 | + Scenario Outline: Check fips is enabled correctly on Ubuntu pro fips AWS machine |
942 | + Given a `<release>` machine with ubuntu-advantage-tools installed |
943 | + When I create the file `/etc/ubuntu-advantage/uaclient.conf` with the following: |
944 | + """ |
945 | + contract_url: 'https://contracts.canonical.com' |
946 | + data_dir: /var/lib/ubuntu-advantage |
947 | + log_level: debug |
948 | + log_file: /var/log/ubuntu-advantage.log |
949 | + """ |
950 | + And I run `ua auto-attach` with sudo |
951 | + And I run `ua status --wait` as non-root |
952 | + And I run `ua status` as non-root |
953 | + Then stdout matches regexp: |
954 | + """ |
955 | + esm-apps +yes +enabled +UA Apps: Extended Security Maintenance \(ESM\) |
956 | + esm-infra +yes +enabled +UA Infra: Extended Security Maintenance \(ESM\) |
957 | + fips +yes +enabled +NIST-certified core packages |
958 | + fips-updates +yes +disabled +NIST-certified core packages with priority security updates |
959 | + livepatch +yes +n/a +Canonical Livepatch service |
960 | + """ |
961 | + And I verify that running `apt update` `with sudo` exits `0` |
962 | + And I verify that running `grep Traceback /var/log/ubuntu-advantage.log` `with sudo` exits `1` |
963 | When I run `uname -r` as non-root |
964 | Then stdout matches regexp: |
965 | """ |
966 | @@ -182,6 +281,10 @@ Feature: Command behaviour when auto-attached in an ubuntu PRO fips image |
967 | """ |
968 | https://esm.ubuntu.com/apps/ubuntu <release>-apps-security/main amd64 Packages |
969 | """ |
970 | + And apt-cache policy for the following url has permission `1001` |
971 | + """ |
972 | + <fips-apt-source> amd64 Packages |
973 | + """ |
974 | And I verify that running `apt update` `with sudo` exits `0` |
975 | When I run `apt install -y <infra-pkg>/<release>-infra-security` with sudo, retrying exit [100] |
976 | And I run `apt-cache policy <infra-pkg>` as non-root |
977 | @@ -202,9 +305,167 @@ Feature: Command behaviour when auto-attached in an ubuntu PRO fips image |
978 | \s*\*\*\* .* 500 |
979 | \s*500 https://esm.ubuntu.com/apps/ubuntu <release>-apps-security/main amd64 Packages |
980 | """ |
981 | + When I run `ua enable fips-updates --assume-yes` with sudo |
982 | + Then I will see the following on stdout: |
983 | + """ |
984 | + One moment, checking your subscription first |
985 | + Disabling incompatible service: FIPS |
986 | + Updating package lists |
987 | + Installing FIPS Updates packages |
988 | + FIPS Updates enabled |
989 | + A reboot is required to complete install. |
990 | + """ |
991 | + When I run `ua status` with sudo |
992 | + Then stdout matches regexp: |
993 | + """ |
994 | + fips +yes +n/a +NIST-certified core packages |
995 | + fips-updates +yes +enabled +NIST-certified core packages with priority security updates |
996 | + """ |
997 | + When I reboot the `<release>` machine |
998 | + And I run `uname -r` as non-root |
999 | + Then stdout matches regexp: |
1000 | + """ |
1001 | + <fips-kernel-version> |
1002 | + """ |
1003 | + When I run `apt-cache policy ubuntu-aws-fips` as non-root |
1004 | + Then stdout does not match regexp: |
1005 | + """ |
1006 | + .*Installed: \(none\) |
1007 | + """ |
1008 | + When I run `cat /proc/sys/crypto/fips_enabled` with sudo |
1009 | + Then I will see the following on stdout: |
1010 | + """ |
1011 | + 1 |
1012 | + """ |
1013 | |
1014 | Examples: ubuntu release |
1015 | | release | infra-pkg | apps-pkg | fips-apt-source | fips-kernel-version | |
1016 | | xenial | libkrad0 | jq | https://esm.ubuntu.com/fips/ubuntu xenial/main | fips | |
1017 | | bionic | libkrad0 | bundler | https://esm.ubuntu.com/fips/ubuntu bionic/main | aws-fips | |
1018 | + | focal | hello | 389-ds | https://esm.ubuntu.com/fips/ubuntu focal/main | aws-fips | |
1019 | |
1020 | + @series.focal |
1021 | + @uses.config.machine_type.aws.pro.fips |
1022 | + Scenario Outline: Check fips packages are correctly installed on AWS Focal machine |
1023 | + Given a `<release>` machine with ubuntu-advantage-tools installed |
1024 | + When I create the file `/etc/ubuntu-advantage/uaclient.conf` with the following: |
1025 | + """ |
1026 | + contract_url: 'https://contracts.canonical.com' |
1027 | + data_dir: /var/lib/ubuntu-advantage |
1028 | + log_level: debug |
1029 | + log_file: /var/log/ubuntu-advantage.log |
1030 | + features: |
1031 | + allow_xenial_fips_on_cloud: true |
1032 | + """ |
1033 | + And I run `ua auto-attach` with sudo |
1034 | + And I run `ua status --wait` as non-root |
1035 | + And I run `ua status` as non-root |
1036 | + Then stdout matches regexp: |
1037 | + """ |
1038 | + esm-apps +yes +enabled +UA Apps: Extended Security Maintenance \(ESM\) |
1039 | + esm-infra +yes +enabled +UA Infra: Extended Security Maintenance \(ESM\) |
1040 | + fips +yes +enabled +NIST-certified core packages |
1041 | + fips-updates +yes +disabled +NIST-certified core packages with priority security updates |
1042 | + livepatch +yes +n/a +Canonical Livepatch service |
1043 | + """ |
1044 | + And I verify that running `apt update` `with sudo` exits `0` |
1045 | + And I verify that running `grep Traceback /var/log/ubuntu-advantage.log` `with sudo` exits `1` |
1046 | + And I verify that `openssh-server` is installed from apt source `<fips-apt-source>` |
1047 | + And I verify that `openssh-client` is installed from apt source `<fips-apt-source>` |
1048 | + And I verify that `strongswan` is installed from apt source `<fips-apt-source>` |
1049 | + And I verify that `strongswan-hmac` is installed from apt source `<fips-apt-source>` |
1050 | + |
1051 | + Examples: ubuntu release |
1052 | + | release | fips-apt-source | |
1053 | + | focal | https://esm.ubuntu.com/fips/ubuntu focal/main | |
1054 | + |
1055 | + @series.xenial |
1056 | + @series.bionic |
1057 | + @uses.config.machine_type.aws.pro.fips |
1058 | + Scenario Outline: Check fips packages are correctly installed on AWS Bionic & Xenial machines |
1059 | + Given a `<release>` machine with ubuntu-advantage-tools installed |
1060 | + When I create the file `/etc/ubuntu-advantage/uaclient.conf` with the following: |
1061 | + """ |
1062 | + contract_url: 'https://contracts.canonical.com' |
1063 | + data_dir: /var/lib/ubuntu-advantage |
1064 | + log_level: debug |
1065 | + log_file: /var/log/ubuntu-advantage.log |
1066 | + features: |
1067 | + allow_xenial_fips_on_cloud: true |
1068 | + """ |
1069 | + And I run `ua auto-attach` with sudo |
1070 | + And I run `ua status --wait` as non-root |
1071 | + And I run `ua status` as non-root |
1072 | + Then stdout matches regexp: |
1073 | + """ |
1074 | + esm-apps +yes +enabled +UA Apps: Extended Security Maintenance \(ESM\) |
1075 | + esm-infra +yes +enabled +UA Infra: Extended Security Maintenance \(ESM\) |
1076 | + fips +yes +enabled +NIST-certified core packages |
1077 | + fips-updates +yes +disabled +NIST-certified core packages with priority security updates |
1078 | + livepatch +yes +n/a +Canonical Livepatch service |
1079 | + """ |
1080 | + And I verify that running `apt update` `with sudo` exits `0` |
1081 | + And I verify that running `grep Traceback /var/log/ubuntu-advantage.log` `with sudo` exits `1` |
1082 | + And I verify that `openssh-server` is installed from apt source `<fips-apt-source>` |
1083 | + And I verify that `openssh-client` is installed from apt source `<fips-apt-source>` |
1084 | + And I verify that `strongswan` is installed from apt source `<fips-apt-source>` |
1085 | + And I verify that `openssh-server-hmac` is installed from apt source `<fips-apt-source>` |
1086 | + And I verify that `openssh-client-hmac` is installed from apt source `<fips-apt-source>` |
1087 | + And I verify that `strongswan-hmac` is installed from apt source `<fips-apt-source>` |
1088 | + |
1089 | + Examples: ubuntu release |
1090 | + | release | fips-apt-source | |
1091 | + | xenial | https://esm.ubuntu.com/fips/ubuntu xenial/main | |
1092 | + | bionic | https://esm.ubuntu.com/fips/ubuntu bionic/main | |
1093 | + |
1094 | + @series.focal |
1095 | + @uses.config.machine_type.azure.pro.fips |
1096 | + @uses.config.machine_type.aws.pro.fips |
1097 | + Scenario Outline: Check fips-updates can be enable in a focal PRO FIPS machine |
1098 | + Given a `<release>` machine with ubuntu-advantage-tools installed |
1099 | + When I create the file `/etc/ubuntu-advantage/uaclient.conf` with the following: |
1100 | + """ |
1101 | + contract_url: 'https://contracts.canonical.com' |
1102 | + data_dir: /var/lib/ubuntu-advantage |
1103 | + log_level: debug |
1104 | + log_file: /var/log/ubuntu-advantage.log |
1105 | + """ |
1106 | + And I run `ua auto-attach` with sudo |
1107 | + And I run `ua status --wait` as non-root |
1108 | + And I run `ua status` as non-root |
1109 | + Then stdout matches regexp: |
1110 | + """ |
1111 | + fips +yes +enabled +NIST-certified core packages |
1112 | + fips-updates +yes +disabled +NIST-certified core packages with priority security updates |
1113 | + """ |
1114 | + When I run `ua enable fips-updates --assume-yes` with sudo |
1115 | + Then stdout matches regexp: |
1116 | + """ |
1117 | + One moment, checking your subscription first |
1118 | + Disabling incompatible service: FIPS |
1119 | + Updating package lists |
1120 | + Installing FIPS Updates packages |
1121 | + FIPS Updates enabled |
1122 | + A reboot is required to complete install. |
1123 | + """ |
1124 | + When I run `ua status` with sudo |
1125 | + Then stdout matches regexp: |
1126 | + """ |
1127 | + fips +yes +n/a +NIST-certified core packages |
1128 | + fips-updates +yes +enabled +NIST-certified core packages with priority security updates |
1129 | + """ |
1130 | + When I reboot the `<release>` machine |
1131 | + And I run `uname -r` as non-root |
1132 | + Then stdout matches regexp: |
1133 | + """ |
1134 | + fips |
1135 | + """ |
1136 | + When I run `cat /proc/sys/crypto/fips_enabled` with sudo |
1137 | + Then I will see the following on stdout: |
1138 | + """ |
1139 | + 1 |
1140 | + """ |
1141 | + |
1142 | + Examples: ubuntu release |
1143 | + | release | |
1144 | + | focal | |
1145 | diff --git a/features/ubuntu_upgrade.feature b/features/ubuntu_upgrade.feature |
1146 | index 4cf3407..0ffa683 100644 |
1147 | --- a/features/ubuntu_upgrade.feature |
1148 | +++ b/features/ubuntu_upgrade.feature |
1149 | @@ -17,7 +17,6 @@ Feature: Upgrade between releases when uaclient is attached |
1150 | [Sources] |
1151 | AllowThirdParty=yes |
1152 | """ |
1153 | - And I run `sed -i 's/Prompt=lts/Prompt=normal/' /etc/update-manager/release-upgrades` with sudo |
1154 | And I run `do-release-upgrade <devel_release> --frontend DistUpgradeViewNonInteractive` `with sudo` and stdin `y\n` |
1155 | And I reboot the `<release>` machine |
1156 | And I run `lsb_release -cs` as non-root |
1157 | @@ -42,7 +41,7 @@ Feature: Upgrade between releases when uaclient is attached |
1158 | |
1159 | Examples: ubuntu release |
1160 | | release | next_release | devel_release | |
1161 | - | focal | impish | | |
1162 | + | focal | jammy | --devel-release | |
1163 | | impish | jammy | --devel-release | |
1164 | |
1165 | @slow |
1166 | diff --git a/features/unattached_status.feature b/features/unattached_status.feature |
1167 | index 08538a2..eccaf60 100644 |
1168 | --- a/features/unattached_status.feature |
1169 | +++ b/features/unattached_status.feature |
1170 | @@ -47,13 +47,13 @@ Feature: Unattached status |
1171 | When I run `ua status` as non-root |
1172 | Then stdout matches regexp: |
1173 | """ |
1174 | - SERVICE AVAILABLE DESCRIPTION |
1175 | - cc-eal <cc-eal> +Common Criteria EAL2 Provisioning Packages |
1176 | + SERVICE +AVAILABLE DESCRIPTION |
1177 | + cc-eal +<cc-eal> +Common Criteria EAL2 Provisioning Packages |
1178 | ?<cis>( +<cis-available> +Security compliance and audit tools)? |
1179 | - ?esm-infra <esm-infra> +UA Infra: Extended Security Maintenance \(ESM\) |
1180 | - fips <fips> +NIST-certified core packages |
1181 | - fips-updates <fips> +NIST-certified core packages with priority security updates |
1182 | - livepatch <livepatch> +Canonical Livepatch service |
1183 | + ?esm-infra +<esm-infra> +UA Infra: Extended Security Maintenance \(ESM\) |
1184 | + fips +<fips> +NIST-certified core packages |
1185 | + fips-updates +<fips> +NIST-certified core packages with priority security updates |
1186 | + livepatch +<livepatch> +Canonical Livepatch service |
1187 | ?<usg>( +<cis-available> +Security compliance and audit tools)? |
1188 | |
1189 | This machine is not attached to a UA subscription. |
1190 | @@ -62,16 +62,17 @@ Feature: Unattached status |
1191 | When I run `ua status --all` as non-root |
1192 | Then stdout matches regexp: |
1193 | """ |
1194 | - SERVICE AVAILABLE DESCRIPTION |
1195 | - cc-eal <cc-eal> +Common Criteria EAL2 Provisioning Packages |
1196 | + SERVICE +AVAILABLE DESCRIPTION |
1197 | + cc-eal +<cc-eal> +Common Criteria EAL2 Provisioning Packages |
1198 | ?<cis>( +<cis-available> +Security compliance and audit tools)? |
1199 | - ?esm-apps <esm-apps> +UA Apps: Extended Security Maintenance \(ESM\) |
1200 | - esm-infra <esm-infra> +UA Infra: Extended Security Maintenance \(ESM\) |
1201 | - fips <fips> +NIST-certified core packages |
1202 | - fips-updates <fips> +NIST-certified core packages with priority security updates |
1203 | - livepatch <livepatch> +Canonical Livepatch service |
1204 | - ros <ros> +Security Updates for the Robot Operating System |
1205 | - ros-updates <ros> +All Updates for the Robot Operating System |
1206 | + ?esm-apps +<esm-apps> +UA Apps: Extended Security Maintenance \(ESM\) |
1207 | + esm-infra +<esm-infra> +UA Infra: Extended Security Maintenance \(ESM\) |
1208 | + fips +<fips> +NIST-certified core packages |
1209 | + fips-updates +<fips> +NIST-certified core packages with priority security updates |
1210 | + livepatch +<livepatch> +Canonical Livepatch service |
1211 | + realtime-kernel +<realtime-kernel> +Beta-version Ubuntu Kernel with PREEMPT_RT patches |
1212 | + ros +<ros> +Security Updates for the Robot Operating System |
1213 | + ros-updates +<ros> +All Updates for the Robot Operating System |
1214 | ?<usg>( +<cis-available> +Security compliance and audit tools)? |
1215 | |
1216 | This machine is not attached to a UA subscription. |
1217 | @@ -80,13 +81,13 @@ Feature: Unattached status |
1218 | When I run `ua status` with sudo |
1219 | Then stdout matches regexp: |
1220 | """ |
1221 | - SERVICE AVAILABLE DESCRIPTION |
1222 | - cc-eal <cc-eal> +Common Criteria EAL2 Provisioning Packages |
1223 | + SERVICE +AVAILABLE DESCRIPTION |
1224 | + cc-eal +<cc-eal> +Common Criteria EAL2 Provisioning Packages |
1225 | ?<cis>( +<cis-available> +Security compliance and audit tools)? |
1226 | - ?esm-infra <esm-infra> +UA Infra: Extended Security Maintenance \(ESM\) |
1227 | - fips <fips> +NIST-certified core packages |
1228 | - fips-updates <fips> +NIST-certified core packages with priority security updates |
1229 | - livepatch <livepatch> +Canonical Livepatch service |
1230 | + ?esm-infra +<esm-infra> +UA Infra: Extended Security Maintenance \(ESM\) |
1231 | + fips +<fips> +NIST-certified core packages |
1232 | + fips-updates +<fips> +NIST-certified core packages with priority security updates |
1233 | + livepatch +<livepatch> +Canonical Livepatch service |
1234 | ?<usg>( +<cis-available> +Security compliance and audit tools)? |
1235 | |
1236 | This machine is not attached to a UA subscription. |
1237 | @@ -95,16 +96,17 @@ Feature: Unattached status |
1238 | When I run `ua status --all` with sudo |
1239 | Then stdout matches regexp: |
1240 | """ |
1241 | - SERVICE AVAILABLE DESCRIPTION |
1242 | - cc-eal <cc-eal> +Common Criteria EAL2 Provisioning Packages |
1243 | + SERVICE +AVAILABLE DESCRIPTION |
1244 | + cc-eal +<cc-eal> +Common Criteria EAL2 Provisioning Packages |
1245 | ?<cis>( +<cis-available> +Security compliance and audit tools)? |
1246 | - ?esm-apps <esm-apps> +UA Apps: Extended Security Maintenance \(ESM\) |
1247 | - esm-infra <esm-infra> +UA Infra: Extended Security Maintenance \(ESM\) |
1248 | - fips <fips> +NIST-certified core packages |
1249 | - fips-updates <fips> +NIST-certified core packages with priority security updates |
1250 | - livepatch <livepatch> +Canonical Livepatch service |
1251 | - ros <ros> +Security Updates for the Robot Operating System |
1252 | - ros-updates <ros> +All Updates for the Robot Operating System |
1253 | + ?esm-apps +<esm-apps> +UA Apps: Extended Security Maintenance \(ESM\) |
1254 | + esm-infra +<esm-infra> +UA Infra: Extended Security Maintenance \(ESM\) |
1255 | + fips +<fips> +NIST-certified core packages |
1256 | + fips-updates +<fips> +NIST-certified core packages with priority security updates |
1257 | + livepatch +<livepatch> +Canonical Livepatch service |
1258 | + realtime-kernel +<realtime-kernel> +Beta-version Ubuntu Kernel with PREEMPT_RT patches |
1259 | + ros +<ros> +Security Updates for the Robot Operating System |
1260 | + ros-updates +<ros> +All Updates for the Robot Operating System |
1261 | ?<usg>( +<cis-available> +Security compliance and audit tools)? |
1262 | |
1263 | This machine is not attached to a UA subscription. |
1264 | @@ -118,16 +120,17 @@ Feature: Unattached status |
1265 | And I run `ua status` as non-root |
1266 | Then stdout matches regexp: |
1267 | """ |
1268 | - SERVICE AVAILABLE DESCRIPTION |
1269 | - cc-eal <cc-eal> +Common Criteria EAL2 Provisioning Packages |
1270 | + SERVICE +AVAILABLE DESCRIPTION |
1271 | + cc-eal +<cc-eal> +Common Criteria EAL2 Provisioning Packages |
1272 | ?<cis>( +<cis-available> +Security compliance and audit tools)? |
1273 | - ?esm-apps <esm-apps> +UA Apps: Extended Security Maintenance \(ESM\) |
1274 | - esm-infra <esm-infra> +UA Infra: Extended Security Maintenance \(ESM\) |
1275 | - fips <fips> +NIST-certified core packages |
1276 | - fips-updates <fips> +NIST-certified core packages with priority security updates |
1277 | - livepatch <livepatch> +Canonical Livepatch service |
1278 | - ros <ros> +Security Updates for the Robot Operating System |
1279 | - ros-updates <ros> +All Updates for the Robot Operating System |
1280 | + ?esm-apps +<esm-apps> +UA Apps: Extended Security Maintenance \(ESM\) |
1281 | + esm-infra +<esm-infra> +UA Infra: Extended Security Maintenance \(ESM\) |
1282 | + fips +<fips> +NIST-certified core packages |
1283 | + fips-updates +<fips> +NIST-certified core packages with priority security updates |
1284 | + livepatch +<livepatch> +Canonical Livepatch service |
1285 | + realtime-kernel +<realtime-kernel> +Beta-version Ubuntu Kernel with PREEMPT_RT patches |
1286 | + ros +<ros> +Security Updates for the Robot Operating System |
1287 | + ros-updates +<ros> +All Updates for the Robot Operating System |
1288 | ?<usg>( +<cis-available> +Security compliance and audit tools)? |
1289 | |
1290 | This machine is not attached to a UA subscription. |
1291 | @@ -135,44 +138,44 @@ Feature: Unattached status |
1292 | """ |
1293 | |
1294 | Examples: ubuntu release |
1295 | - | release | esm-apps | cc-eal | cis | cis-available | fips | esm-infra | ros | livepatch | usg | |
1296 | - | xenial | yes | yes | cis | yes | yes | yes | yes | yes | | |
1297 | - | bionic | yes | yes | cis | yes | yes | yes | yes | yes | | |
1298 | - | focal | yes | no | | yes | yes | yes | no | yes | usg | |
1299 | - | impish | no | no | cis | no | no | no | no | no | | |
1300 | - | jammy | no | no | cis | no | no | no | no | no | | |
1301 | + | release | esm-apps | cc-eal | cis | cis-available | fips | esm-infra | ros | livepatch | usg | realtime-kernel | |
1302 | + | xenial | yes | yes | cis | yes | yes | yes | yes | yes | | no | |
1303 | + | bionic | yes | yes | cis | yes | yes | yes | yes | yes | | no | |
1304 | + | focal | yes | no | | yes | yes | yes | no | yes | usg | no | |
1305 | + | impish | no | no | cis | no | no | no | no | no | | no | |
1306 | + | jammy | no | no | cis | no | no | no | no | no | | yes | |
1307 | |
1308 | @series.all |
1309 | @uses.config.machine_type.lxd.container |
1310 | @uses.config.contract_token |
1311 | - @uses.config.contract_token_staging_expired |
1312 | Scenario Outline: Simulate status in a ubuntu machine |
1313 | Given a `<release>` machine with ubuntu-advantage-tools installed |
1314 | When I do a preflight check for `contract_token` without the all flag |
1315 | Then stdout matches regexp: |
1316 | """ |
1317 | - SERVICE AVAILABLE ENTITLED AUTO_ENABLED DESCRIPTION |
1318 | - cc-eal <cc-eal> +yes +no +Common Criteria EAL2 Provisioning Packages |
1319 | + SERVICE +AVAILABLE ENTITLED AUTO_ENABLED DESCRIPTION |
1320 | + cc-eal +<cc-eal> +yes +no +Common Criteria EAL2 Provisioning Packages |
1321 | ?<cis>( +<cis-available> +yes +no +Security compliance and audit tools)? |
1322 | - ?esm-infra <esm-infra> +yes +yes +UA Infra: Extended Security Maintenance \(ESM\) |
1323 | - fips <fips> +yes +no +NIST-certified core packages |
1324 | - fips-updates <fips> +yes +no +NIST-certified core packages with priority security updates |
1325 | - livepatch <livepatch> +yes +yes +Canonical Livepatch service |
1326 | + ?esm-infra +<esm-infra> +yes +yes +UA Infra: Extended Security Maintenance \(ESM\) |
1327 | + fips +<fips> +yes +no +NIST-certified core packages |
1328 | + fips-updates +<fips> +yes +no +NIST-certified core packages with priority security updates |
1329 | + livepatch +<livepatch> +yes +yes +Canonical Livepatch service |
1330 | ?<usg>( +<cis-available> +yes +no +Security compliance and audit tools)? |
1331 | """ |
1332 | When I do a preflight check for `contract_token` with the all flag |
1333 | Then stdout matches regexp: |
1334 | """ |
1335 | - SERVICE AVAILABLE ENTITLED AUTO_ENABLED DESCRIPTION |
1336 | - cc-eal <cc-eal> +yes +no +Common Criteria EAL2 Provisioning Packages |
1337 | + SERVICE +AVAILABLE ENTITLED AUTO_ENABLED DESCRIPTION |
1338 | + cc-eal +<cc-eal> +yes +no +Common Criteria EAL2 Provisioning Packages |
1339 | ?<cis>( +<cis-available> +yes +no +Security compliance and audit tools)? |
1340 | - ?esm-apps <esm-apps> +yes +yes +UA Apps: Extended Security Maintenance \(ESM\) |
1341 | - esm-infra <esm-infra> +yes +yes +UA Infra: Extended Security Maintenance \(ESM\) |
1342 | - fips <fips> +yes +no +NIST-certified core packages |
1343 | - fips-updates <fips> +yes +no +NIST-certified core packages with priority security updates |
1344 | - livepatch <livepatch> +yes +yes +Canonical Livepatch service |
1345 | - ros <ros> +yes +no +Security Updates for the Robot Operating System |
1346 | - ros-updates <ros> +yes +no +All Updates for the Robot Operating System |
1347 | + ?esm-apps +<esm-apps> +yes +yes +UA Apps: Extended Security Maintenance \(ESM\) |
1348 | + esm-infra +<esm-infra> +yes +yes +UA Infra: Extended Security Maintenance \(ESM\) |
1349 | + fips +<fips> +yes +no +NIST-certified core packages |
1350 | + fips-updates +<fips> +yes +no +NIST-certified core packages with priority security updates |
1351 | + livepatch +<livepatch> +yes +yes +Canonical Livepatch service |
1352 | + realtime-kernel +<realtime-kernel> +yes +no +Beta-version Ubuntu Kernel with PREEMPT_RT patches |
1353 | + ros +<ros> +yes +no +Security Updates for the Robot Operating System |
1354 | + ros-updates +<ros> +yes +no +All Updates for the Robot Operating System |
1355 | ?<usg>( +<cis-available> +yes +no +Security compliance and audit tools)? |
1356 | """ |
1357 | When I do a preflight check for `contract_token` formatted as json |
1358 | @@ -199,6 +202,20 @@ Feature: Unattached status |
1359 | services: [] |
1360 | warnings: [] |
1361 | """ |
1362 | + Examples: ubuntu release |
1363 | + | release | esm-apps | cc-eal | cis | cis-available | fips | esm-infra | ros | livepatch | usg | realtime-kernel | |
1364 | + | xenial | yes | yes | cis | yes | yes | yes | yes | yes | | no | |
1365 | + | bionic | yes | yes | cis | yes | yes | yes | yes | yes | | no | |
1366 | + | focal | yes | no | | yes | yes | yes | no | yes | usg | no | |
1367 | + | impish | no | no | cis | no | no | no | no | no | | no | |
1368 | + | jammy | no | no | cis | no | no | no | no | no | | yes | |
1369 | + |
1370 | + |
1371 | + @series.all |
1372 | + @uses.config.machine_type.lxd.container |
1373 | + @uses.config.contract_token_staging_expired |
1374 | + Scenario Outline: Simulate status with expired token in a ubuntu machine |
1375 | + Given a `<release>` machine with ubuntu-advantage-tools installed |
1376 | When I run `sed -i 's/contracts.can/contracts.staging.can/' /etc/ubuntu-advantage/uaclient.conf` with sudo |
1377 | And I verify that a preflight check for `contract_token_staging_expired` formatted as json exits 1 |
1378 | Then stdout is a json matching the `ua_status` schema |
1379 | @@ -223,13 +240,13 @@ Feature: Unattached status |
1380 | This token is not valid. |
1381 | Contract \".*\" expired on .* |
1382 | |
1383 | - SERVICE AVAILABLE ENTITLED AUTO_ENABLED DESCRIPTION |
1384 | - cc-eal <cc-eal> +yes +no +Common Criteria EAL2 Provisioning Packages |
1385 | + SERVICE +AVAILABLE ENTITLED AUTO_ENABLED DESCRIPTION |
1386 | + cc-eal +<cc-eal> +yes +no +Common Criteria EAL2 Provisioning Packages |
1387 | ?<cis>( +<cis-available> +yes +no +Security compliance and audit tools)? |
1388 | - ?esm-infra <esm-infra> +yes +yes +UA Infra: Extended Security Maintenance \(ESM\) |
1389 | - fips <fips> +yes +no +NIST-certified core packages |
1390 | - fips-updates <fips> +yes +no +NIST-certified core packages with priority security updates |
1391 | - livepatch <livepatch> +yes +yes +Canonical Livepatch service |
1392 | + ?esm-infra +<esm-infra> +yes +yes +UA Infra: Extended Security Maintenance \(ESM\) |
1393 | + fips +<fips> +yes +no +NIST-certified core packages |
1394 | + fips-updates +<fips> +yes +no +NIST-certified core packages with priority security updates |
1395 | + livepatch +<livepatch> +yes +yes +Canonical Livepatch service |
1396 | ?<usg>( +<cis-available> +yes +no +Security compliance and audit tools)? |
1397 | """ |
1398 | |
1399 | @@ -239,4 +256,4 @@ Feature: Unattached status |
1400 | | bionic | yes | yes | cis | yes | yes | yes | yes | yes | | |
1401 | | focal | yes | no | | yes | yes | yes | no | yes | usg | |
1402 | | impish | no | no | cis | no | no | no | no | no | | |
1403 | - | jammy | no | no | cis | no | no | no | no | no | | |
1404 | + | jammy | no | no | cis | no | no | yes | no | no | | |
1405 | diff --git a/help_data.yaml b/help_data.yaml |
1406 | index d5d6486..c301573 100644 |
1407 | --- a/help_data.yaml |
1408 | +++ b/help_data.yaml |
1409 | @@ -61,6 +61,16 @@ livepatch: |
1410 | more about Ubuntu Kernel Livepatch service at |
1411 | https://ubuntu.com/security/livepatch |
1412 | |
1413 | +realtime-kernel: |
1414 | + help: | |
1415 | + The real-time kernel is a beta version of the 22.04 Ubuntu kernel with the |
1416 | + PREEMPT_RT patchset integrated for x86_64 and ARM64. It services extreme |
1417 | + latency-dependent use cases and provides deterministic response times to |
1418 | + service events. By meeting stringent preemption specifications, the |
1419 | + real-time kernel is suitable for telco applications and embedded devices |
1420 | + in industrial automation and robotics. To enroll in the beta program, visit |
1421 | + https://ubuntu.com/realtime-kernel |
1422 | + |
1423 | ros: |
1424 | help: | |
1425 | ros provides access to a private PPA which includes security-related |
1426 | diff --git a/keyrings/ubuntu-advantage-realtime-kernel.gpg b/keyrings/ubuntu-advantage-realtime-kernel.gpg |
1427 | new file mode 100644 |
1428 | index 0000000..edf9246 |
1429 | Binary files /dev/null and b/keyrings/ubuntu-advantage-realtime-kernel.gpg differ |
1430 | diff --git a/lib/upgrade_lts_contract.py b/lib/upgrade_lts_contract.py |
1431 | index 2da9d58..ca7af18 100755 |
1432 | --- a/lib/upgrade_lts_contract.py |
1433 | +++ b/lib/upgrade_lts_contract.py |
1434 | @@ -34,21 +34,27 @@ version_to_codename = { |
1435 | "16.04": "xenial", |
1436 | "18.04": "bionic", |
1437 | "20.04": "focal", |
1438 | - "20.10": "groovy", |
1439 | + "21.10": "impish", |
1440 | + "22.04": "jammy", |
1441 | } |
1442 | |
1443 | current_codename_to_past_codename = { |
1444 | "xenial": "trusty", |
1445 | "bionic": "xenial", |
1446 | "focal": "bionic", |
1447 | - "groovy": "focal", |
1448 | + "impish": "focal", |
1449 | + # We are considering the past release for Jammy to be Focal |
1450 | + # because we don't have any services available on Impish. |
1451 | + # Therefore, it is safer for us to try to process contract deltas |
1452 | + # using Focal |
1453 | + "jammy": "focal", |
1454 | } |
1455 | |
1456 | |
1457 | def process_contract_delta_after_apt_lock() -> None: |
1458 | logging.debug("Check whether to upgrade-lts-contract") |
1459 | if not UAConfig().is_attached: |
1460 | - logging.debug("Skiping upgrade-lts-contract. Machine is unattached") |
1461 | + logging.debug("Skipping upgrade-lts-contract. Machine is unattached") |
1462 | return |
1463 | out, _err = subp(["lsof", "/var/lib/apt/lists/lock"], rcs=[0, 1]) |
1464 | msg = "Starting upgrade-lts-contract." |
1465 | @@ -58,7 +64,15 @@ def process_contract_delta_after_apt_lock() -> None: |
1466 | logging.debug(msg) |
1467 | |
1468 | current_version = parse_os_release()["VERSION_ID"] |
1469 | - current_release = version_to_codename[current_version] |
1470 | + current_release = version_to_codename.get(current_version) |
1471 | + |
1472 | + if current_release is None: |
1473 | + msg = "Unable to get release codename for version: {}".format( |
1474 | + current_version |
1475 | + ) |
1476 | + print(msg) |
1477 | + logging.warning(msg) |
1478 | + sys.exit(1) |
1479 | |
1480 | if current_release == "trusty": |
1481 | msg = "Unable to execute upgrade-lts-contract.py on trusty" |
1482 | @@ -66,7 +80,13 @@ def process_contract_delta_after_apt_lock() -> None: |
1483 | logging.warning(msg) |
1484 | sys.exit(1) |
1485 | |
1486 | - past_release = current_codename_to_past_codename[current_release] |
1487 | + past_release = current_codename_to_past_codename.get(current_release) |
1488 | + if past_release is None: |
1489 | + msg = "Could not find past release for: {}".format(current_release) |
1490 | + print(msg) |
1491 | + logging.warning(msg) |
1492 | + sys.exit(1) |
1493 | + |
1494 | past_entitlements = UAConfig(series=past_release).entitlements |
1495 | new_entitlements = UAConfig(series=current_release).entitlements |
1496 | |
1497 | diff --git a/tools/refresh-keyrings.sh b/tools/refresh-keyrings.sh |
1498 | index f4c1db1..850d8fb 100755 |
1499 | --- a/tools/refresh-keyrings.sh |
1500 | +++ b/tools/refresh-keyrings.sh |
1501 | @@ -28,6 +28,7 @@ ESM_APPS_KEY_ID="E8A443CE358113D187BEE0E6AB01A101DB53907B" |
1502 | FIPS_KEY_ID="E23341B2A1467EDBF07057D6C1997C40EDE22758" |
1503 | CIS_KEY_ID="81CF06E53F2C513A" |
1504 | ROS_KEY_ID="853874C8B0F10896" |
1505 | +REALTIME_KEY_ID="F6D1E58F4DCD9F91" |
1506 | |
1507 | generate_keyrings() { |
1508 | KEYRING_DIR="$1" |
1509 | @@ -50,6 +51,8 @@ generate_keyrings() { |
1510 | service_name="cis";; |
1511 | $ROS_KEY_ID) |
1512 | service_name="ros";; |
1513 | + $REALTIME_KEY_ID) |
1514 | + service_name="realtime-kernel";; |
1515 | *) |
1516 | echo "Unhandled key id provided: " $key |
1517 | exit 1; |
1518 | @@ -70,6 +73,6 @@ generate_keyrings() { |
1519 | } |
1520 | |
1521 | |
1522 | -generate_keyrings $TARGET_DIR $EAL_KEY_ID $ESM_INFRA_KEY_ID $ESM_APPS_KEY_ID $FIPS_KEY_ID $CIS_KEY_ID $ROS_KEY_ID |
1523 | +generate_keyrings $TARGET_DIR $EAL_KEY_ID $ESM_INFRA_KEY_ID $ESM_APPS_KEY_ID $FIPS_KEY_ID $CIS_KEY_ID $ROS_KEY_ID $REALTIME_KEY_ID |
1524 | |
1525 | rm -rf $tmp_dir |
1526 | diff --git a/tox.ini b/tox.ini |
1527 | index 45962e0..dffbfa8 100644 |
1528 | --- a/tox.ini |
1529 | +++ b/tox.ini |
1530 | @@ -60,6 +60,7 @@ commands = |
1531 | behave-vm-16.04: behave -v {posargs} --tags="uses.config.machine_type.lxd.vm" --tags="series.xenial,series.all,series.lts" --tags="~upgrade" |
1532 | behave-vm-18.04: behave -v {posargs} --tags="uses.config.machine_type.lxd.vm" --tags="series.bionic,series.all,series.lts" --tags="~upgrade" |
1533 | behave-vm-20.04: behave -v {posargs} --tags="uses.config.machine_type.lxd.vm" --tags="series.focal,series.all,series.lts" --tags="~upgrade" |
1534 | + behave-vm-22.04: behave -v {posargs} --tags="uses.config.machine_type.lxd.vm" --tags="series.jammy,series.all,series.lts" --tags="~upgrade" |
1535 | behave-upgrade-16.04: behave -v {posargs} --tags="upgrade" --tags="series.xenial,series.all" |
1536 | behave-upgrade-18.04: behave -v {posargs} --tags="upgrade" --tags="series.bionic,series.all" |
1537 | behave-upgrade-20.04: behave -v {posargs} --tags="upgrade" --tags="series.focal,series.all" |
1538 | @@ -72,6 +73,7 @@ commands = |
1539 | behave-awspro-20.04: behave -v {posargs} --tags="uses.config.machine_type.aws.pro" --tags="series.focal,series.lts,series.all" |
1540 | behave-awspro-fips-16.04: behave -v {posargs} --tags="uses.config.machine_type.aws.pro.fips" --tags="series.xenial,series.lts,series.all" |
1541 | behave-awspro-fips-18.04: behave -v {posargs} --tags="uses.config.machine_type.aws.pro.fips" --tags="series.bionic,series.lts,series.all" |
1542 | + behave-awspro-fips-20.04: behave -v {posargs} --tags="uses.config.machine_type.aws.pro.fips" --tags="series.focal,series.lts,series.all" |
1543 | behave-azuregeneric-16.04: behave -v {posargs} --tags="uses.config.machine_type.azure.generic" --tags="series.xenial,series.lts,series.all" --tags="~upgrade" |
1544 | behave-azuregeneric-18.04: behave -v {posargs} --tags="uses.config.machine_type.azure.generic" --tags="series.bionic,series.lts,series.all" --tags="~upgrade" |
1545 | behave-azuregeneric-20.04: behave -v {posargs} --tags="uses.config.machine_type.azure.generic" --tags="series.focal,series.lts,series.all" --tags="~upgrade" |
1546 | @@ -80,6 +82,7 @@ commands = |
1547 | behave-azurepro-20.04: behave -v {posargs} --tags="uses.config.machine_type.azure.pro" --tags="series.focal,series.lts,series.all" |
1548 | behave-azurepro-fips-16.04: behave -v {posargs} --tags="uses.config.machine_type.azure.pro.fips" --tags="series.xenial,series.lts,series.all" |
1549 | behave-azurepro-fips-18.04: behave -v {posargs} --tags="uses.config.machine_type.azure.pro.fips" --tags="series.bionic,series.lts,series.all" |
1550 | + behave-azurepro-fips-20.04: behave -v {posargs} --tags="uses.config.machine_type.azure.pro.fips" --tags="series.focal,series.lts,series.all" |
1551 | behave-gcpgeneric-16.04: behave -v {posargs} --tags="uses.config.machine_type.gcp.generic" --tags="series.xenial,series.lts,series.all" --tags="~upgrade" |
1552 | behave-gcpgeneric-18.04: behave -v {posargs} --tags="uses.config.machine_type.gcp.generic" --tags="series.bionic,series.lts,series.all" --tags="~upgrade" |
1553 | behave-gcpgeneric-20.04: behave -v {posargs} --tags="uses.config.machine_type.gcp.generic" --tags="series.focal,series.lts,series.all" --tags="~upgrade" |
1554 | diff --git a/uaclient/clouds/identity.py b/uaclient/clouds/identity.py |
1555 | index 7542d35..a39fef0 100644 |
1556 | --- a/uaclient/clouds/identity.py |
1557 | +++ b/uaclient/clouds/identity.py |
1558 | @@ -1,5 +1,6 @@ |
1559 | import logging |
1560 | from enum import Enum |
1561 | +from functools import lru_cache |
1562 | from typing import Dict, Optional, Tuple, Type # noqa: F401 |
1563 | |
1564 | from uaclient import clouds, exceptions, util |
1565 | @@ -36,6 +37,7 @@ def get_instance_id() -> Optional[str]: |
1566 | return None |
1567 | |
1568 | |
1569 | +@lru_cache(maxsize=None) |
1570 | @apply_config_settings_override("cloud_type") |
1571 | def get_cloud_type() -> Tuple[Optional[str], Optional[NoCloudTypeReason]]: |
1572 | if util.which("cloud-id"): |
1573 | diff --git a/uaclient/clouds/tests/test_identity.py b/uaclient/clouds/tests/test_identity.py |
1574 | index a21efee..ae2e4a6 100644 |
1575 | --- a/uaclient/clouds/tests/test_identity.py |
1576 | +++ b/uaclient/clouds/tests/test_identity.py |
1577 | @@ -40,7 +40,7 @@ class TestGetCloudType: |
1578 | @mock.patch(M_PATH + "util.subp", return_value=("somecloud\n", "")) |
1579 | def test_use_cloud_id_when_available(self, m_subp, m_which): |
1580 | """Use cloud-id utility to discover cloud type.""" |
1581 | - assert ("somecloud", None) == get_cloud_type() |
1582 | + assert ("somecloud", None) == get_cloud_type.__wrapped__() |
1583 | assert [mock.call("cloud-id")] == m_which.call_args_list |
1584 | |
1585 | @mock.patch(M_PATH + "util.which", return_value="/usr/bin/cloud-id") |
1586 | @@ -49,7 +49,10 @@ class TestGetCloudType: |
1587 | side_effect=exceptions.ProcessExecutionError("cloud-id"), |
1588 | ) |
1589 | def test_error_when_cloud_id_fails(self, m_subp, m_which): |
1590 | - assert (None, NoCloudTypeReason.CLOUD_ID_ERROR) == get_cloud_type() |
1591 | + assert ( |
1592 | + None, |
1593 | + NoCloudTypeReason.CLOUD_ID_ERROR, |
1594 | + ) == get_cloud_type.__wrapped__() |
1595 | |
1596 | @pytest.mark.parametrize( |
1597 | "settings_overrides", |
1598 | @@ -80,7 +83,7 @@ class TestGetCloudType: |
1599 | expected_value = "test" |
1600 | |
1601 | m_load_file.return_value = settings_overrides |
1602 | - assert get_cloud_type() == (expected_value, None) |
1603 | + assert get_cloud_type.__wrapped__() == (expected_value, None) |
1604 | |
1605 | |
1606 | @mock.patch(M_PATH + "get_cloud_type") |
1607 | diff --git a/uaclient/config.py b/uaclient/config.py |
1608 | index 079708e..74bb06b 100644 |
1609 | --- a/uaclient/config.py |
1610 | +++ b/uaclient/config.py |
1611 | @@ -357,7 +357,7 @@ class UAConfig: |
1612 | entitlement_cfg["resourceToken"] = tokens_by_name[ |
1613 | entitlement_name |
1614 | ] |
1615 | - util.apply_series_overrides(entitlement_cfg, self.series) |
1616 | + util.apply_contract_overrides(entitlement_cfg, self.series) |
1617 | self._entitlements[entitlement_name] = entitlement_cfg |
1618 | return self._entitlements |
1619 | |
1620 | diff --git a/uaclient/contract.py b/uaclient/contract.py |
1621 | index 47d0b5a..b47b484 100644 |
1622 | --- a/uaclient/contract.py |
1623 | +++ b/uaclient/contract.py |
1624 | @@ -347,7 +347,7 @@ def process_entitlement_delta( |
1625 | from uaclient.entitlements import entitlement_factory |
1626 | |
1627 | if series_overrides: |
1628 | - util.apply_series_overrides(new_access) |
1629 | + util.apply_contract_overrides(new_access) |
1630 | |
1631 | deltas = util.get_dict_deltas(orig_access, new_access) |
1632 | ret = False |
1633 | diff --git a/uaclient/entitlements/__init__.py b/uaclient/entitlements/__init__.py |
1634 | index 1c6a156..8f7356d 100644 |
1635 | --- a/uaclient/entitlements/__init__.py |
1636 | +++ b/uaclient/entitlements/__init__.py |
1637 | @@ -7,6 +7,7 @@ from uaclient.entitlements.cc import CommonCriteriaEntitlement |
1638 | from uaclient.entitlements.cis import CISEntitlement |
1639 | from uaclient.entitlements.esm import ESMAppsEntitlement, ESMInfraEntitlement |
1640 | from uaclient.entitlements.livepatch import LivepatchEntitlement |
1641 | +from uaclient.entitlements.realtime import RealtimeKernelEntitlement |
1642 | from uaclient.entitlements.ros import ROSEntitlement, ROSUpdatesEntitlement |
1643 | from uaclient.exceptions import EntitlementNotFoundError |
1644 | from uaclient.util import is_config_value_true |
1645 | @@ -19,6 +20,7 @@ ENTITLEMENT_CLASSES = [ |
1646 | fips.FIPSEntitlement, |
1647 | fips.FIPSUpdatesEntitlement, |
1648 | LivepatchEntitlement, |
1649 | + RealtimeKernelEntitlement, |
1650 | ROSEntitlement, |
1651 | ROSUpdatesEntitlement, |
1652 | ] # type: List[Type[UAEntitlement]] |
1653 | diff --git a/uaclient/entitlements/base.py b/uaclient/entitlements/base.py |
1654 | index bf1b926..4606b5c 100644 |
1655 | --- a/uaclient/entitlements/base.py |
1656 | +++ b/uaclient/entitlements/base.py |
1657 | @@ -209,7 +209,8 @@ class UAEntitlement(metaclass=abc.ABCMeta): |
1658 | populated CanEnableFailure reason. This may expand to |
1659 | include other types of reasons in the future. |
1660 | """ |
1661 | - msg_ops = self.messaging.get("pre_enable", []) |
1662 | + |
1663 | + msg_ops = self.messaging.get("pre_can_enable", []) |
1664 | if not util.handle_message_operations(msg_ops): |
1665 | return False, None |
1666 | |
1667 | @@ -237,6 +238,10 @@ class UAEntitlement(metaclass=abc.ABCMeta): |
1668 | # every other reason means we can't continue |
1669 | return False, fail |
1670 | |
1671 | + msg_ops = self.messaging.get("pre_enable", []) |
1672 | + if not util.handle_message_operations(msg_ops): |
1673 | + return False, None |
1674 | + |
1675 | ret = self._perform_enable(silent=silent) |
1676 | if not ret: |
1677 | return False, None |
1678 | @@ -449,7 +454,7 @@ class UAEntitlement(metaclass=abc.ABCMeta): |
1679 | path_to_value="features.block_disable_on_enable", |
1680 | ) |
1681 | for service in self.blocking_incompatible_services(): |
1682 | - ent = service.entitlement(self.cfg) |
1683 | + ent = service.entitlement(self.cfg, assume_yes=True) |
1684 | |
1685 | user_msg = messages.INCOMPATIBLE_SERVICE.format( |
1686 | service_being_enabled=self.title, |
1687 | @@ -474,7 +479,7 @@ class UAEntitlement(metaclass=abc.ABCMeta): |
1688 | ) |
1689 | event.info(disable_msg) |
1690 | |
1691 | - ret = ent.disable() |
1692 | + ret = ent.disable(silent=True) |
1693 | if not ret: |
1694 | return ret, None |
1695 | |
1696 | @@ -664,7 +669,7 @@ class UAEntitlement(metaclass=abc.ABCMeta): |
1697 | event.info(info_msg=msg.msg, file_type=sys.stderr) |
1698 | return False, msg |
1699 | |
1700 | - ent = ent_cls(self.cfg) |
1701 | + ent = ent_cls(cfg=self.cfg, assume_yes=True) |
1702 | |
1703 | is_service_enabled = ( |
1704 | ent.application_status()[0] == status.ApplicationStatus.ENABLED |
1705 | @@ -710,13 +715,16 @@ class UAEntitlement(metaclass=abc.ABCMeta): |
1706 | """Check if system needs to be rebooted.""" |
1707 | return util.should_reboot() |
1708 | |
1709 | - def _check_for_reboot_msg(self, operation: str) -> None: |
1710 | + def _check_for_reboot_msg( |
1711 | + self, operation: str, silent: bool = False |
1712 | + ) -> None: |
1713 | """Check if user should be alerted that a reboot must be performed. |
1714 | |
1715 | @param operation: The operation being executed. |
1716 | + @param silent: Boolean set True to silence print/log of messages |
1717 | """ |
1718 | - if self._check_for_reboot(): |
1719 | - print( |
1720 | + if self._check_for_reboot() and not silent: |
1721 | + event.info( |
1722 | messages.ENABLE_REBOOT_REQUIRED_TMPL.format( |
1723 | operation=operation |
1724 | ) |
1725 | @@ -763,7 +771,9 @@ class UAEntitlement(metaclass=abc.ABCMeta): |
1726 | if not util.handle_message_operations(msg_ops): |
1727 | return False, None |
1728 | |
1729 | - self._check_for_reboot_msg(operation="disable operation") |
1730 | + self._check_for_reboot_msg( |
1731 | + operation="disable operation", silent=silent |
1732 | + ) |
1733 | return True, None |
1734 | |
1735 | def contract_status(self) -> ContractStatus: |
1736 | @@ -836,7 +846,7 @@ class UAEntitlement(metaclass=abc.ABCMeta): |
1737 | transition_to_unentitled = bool(delta_entitlement == util.DROPPED_KEY) |
1738 | if not transition_to_unentitled: |
1739 | if delta_entitlement: |
1740 | - util.apply_series_overrides(deltas) |
1741 | + util.apply_contract_overrides(deltas) |
1742 | delta_entitlement = deltas["entitlement"] |
1743 | if orig_access and "entitled" in delta_entitlement: |
1744 | transition_to_unentitled = delta_entitlement["entitled"] in ( |
1745 | diff --git a/uaclient/entitlements/cis.py b/uaclient/entitlements/cis.py |
1746 | index 07a6a2e..b5c81f4 100644 |
1747 | --- a/uaclient/entitlements/cis.py |
1748 | +++ b/uaclient/entitlements/cis.py |
1749 | @@ -29,7 +29,7 @@ class CISEntitlement(repo.RepoEntitlement): |
1750 | ] |
1751 | } # type: MessagingOperationsDict |
1752 | if "usg" in self.valid_names: |
1753 | - messages["pre_enable"] = [ |
1754 | + messages["pre_can_enable"] = [ |
1755 | "From Ubuntu 20.04 and onwards 'ua enable cis' has been", |
1756 | "replaced by 'ua enable usg'. See more information at:", |
1757 | USG_DOCS_URL, |
1758 | diff --git a/uaclient/entitlements/fips.py b/uaclient/entitlements/fips.py |
1759 | index 7c78543..b83b47e 100644 |
1760 | --- a/uaclient/entitlements/fips.py |
1761 | +++ b/uaclient/entitlements/fips.py |
1762 | @@ -87,6 +87,27 @@ class FIPSCommonEntitlement(repo.RepoEntitlement): |
1763 | |
1764 | help_doc_url = "https://ubuntu.com/security/certifications#fips" |
1765 | |
1766 | + fips_pro_package_holds = [ |
1767 | + "fips-initramfs", |
1768 | + "libssl1.1", |
1769 | + "libssl1.1-hmac", |
1770 | + "libssl1.0.0", |
1771 | + "libssl1.0.0-hmac", |
1772 | + "libssl1.0.0", |
1773 | + "libssl1.0.0-hmac", |
1774 | + "linux-fips", |
1775 | + "openssh-client", |
1776 | + "openssh-client-hmac", |
1777 | + "openssh-server", |
1778 | + "openssh-server-hmac", |
1779 | + "openssl", |
1780 | + "strongswan", |
1781 | + "strongswan-hmac", |
1782 | + "libgcrypt20", |
1783 | + "libgcrypt20-hmac", |
1784 | + "fips-initramfs-generic", |
1785 | + ] |
1786 | + |
1787 | @property |
1788 | def conditional_packages(self): |
1789 | """ |
1790 | @@ -155,19 +176,23 @@ class FIPSCommonEntitlement(repo.RepoEntitlement): |
1791 | ) |
1792 | ) |
1793 | |
1794 | - def _check_for_reboot_msg(self, operation: str) -> None: |
1795 | + def _check_for_reboot_msg( |
1796 | + self, operation: str, silent: bool = False |
1797 | + ) -> None: |
1798 | """Check if user should be alerted that a reboot must be performed. |
1799 | |
1800 | @param operation: The operation being executed. |
1801 | + @param silent: Boolean set True to silence print/log of messages |
1802 | """ |
1803 | reboot_required = util.should_reboot() |
1804 | event.needs_reboot(reboot_required) |
1805 | if reboot_required: |
1806 | - event.info( |
1807 | - messages.ENABLE_REBOOT_REQUIRED_TMPL.format( |
1808 | - operation=operation |
1809 | + if not silent: |
1810 | + event.info( |
1811 | + messages.ENABLE_REBOOT_REQUIRED_TMPL.format( |
1812 | + operation=operation |
1813 | + ) |
1814 | ) |
1815 | - ) |
1816 | if operation == "install": |
1817 | self.cfg.add_notice( |
1818 | "", messages.FIPS_SYSTEM_REBOOT_REQUIRED.msg |
1819 | @@ -361,6 +386,27 @@ class FIPSCommonEntitlement(repo.RepoEntitlement): |
1820 | |
1821 | return False |
1822 | |
1823 | + def setup_apt_config(self, silent: bool = False) -> None: |
1824 | + """Setup apt config based on the resourceToken and directives. |
1825 | + |
1826 | + FIPS-specifically handle apt-mark unhold |
1827 | + |
1828 | + :raise UserFacingError: on failure to setup any aspect of this apt |
1829 | + configuration |
1830 | + """ |
1831 | + cmd = ["apt-mark", "showholds"] |
1832 | + holds = apt.run_apt_command(cmd, " ".join(cmd) + " failed.") |
1833 | + unholds = [] |
1834 | + for hold in holds.splitlines(): |
1835 | + if hold in self.fips_pro_package_holds: |
1836 | + unholds.append(hold) |
1837 | + if unholds: |
1838 | + unhold_cmd = ["apt-mark", "unhold"] + unholds |
1839 | + holds = apt.run_apt_command( |
1840 | + unhold_cmd, " ".join(unhold_cmd) + " failed." |
1841 | + ) |
1842 | + super().setup_apt_config(silent=silent) |
1843 | + |
1844 | |
1845 | class FIPSEntitlement(FIPSCommonEntitlement): |
1846 | |
1847 | @@ -369,27 +415,10 @@ class FIPSEntitlement(FIPSCommonEntitlement): |
1848 | description = "NIST-certified core packages" |
1849 | origin = "UbuntuFIPS" |
1850 | |
1851 | - fips_pro_package_holds = [ |
1852 | - "fips-initramfs", |
1853 | - "libssl1.1", |
1854 | - "libssl1.1-hmac", |
1855 | - "libssl1.0.0", |
1856 | - "libssl1.0.0-hmac", |
1857 | - "libssl1.0.0", |
1858 | - "libssl1.0.0-hmac", |
1859 | - "linux-fips", |
1860 | - "openssh-client", |
1861 | - "openssh-client-hmac", |
1862 | - "openssh-server", |
1863 | - "openssh-server-hmac", |
1864 | - "openssl", |
1865 | - "strongswan", |
1866 | - "strongswan-hmac", |
1867 | - ] |
1868 | - |
1869 | @property |
1870 | def incompatible_services(self) -> Tuple[IncompatibleService, ...]: |
1871 | from uaclient.entitlements.livepatch import LivepatchEntitlement |
1872 | + from uaclient.entitlements.realtime import RealtimeKernelEntitlement |
1873 | |
1874 | return ( |
1875 | IncompatibleService( |
1876 | @@ -398,6 +427,9 @@ class FIPSEntitlement(FIPSCommonEntitlement): |
1877 | IncompatibleService( |
1878 | FIPSUpdatesEntitlement, messages.FIPS_UPDATES_INVALIDATES_FIPS |
1879 | ), |
1880 | + IncompatibleService( |
1881 | + RealtimeKernelEntitlement, messages.REALTIME_FIPS_INCOMPATIBLE |
1882 | + ), |
1883 | ) |
1884 | |
1885 | @property |
1886 | @@ -464,27 +496,6 @@ class FIPSEntitlement(FIPSCommonEntitlement): |
1887 | ], |
1888 | } |
1889 | |
1890 | - def setup_apt_config(self, silent: bool = False) -> None: |
1891 | - """Setup apt config based on the resourceToken and directives. |
1892 | - |
1893 | - FIPS-specifically handle apt-mark unhold |
1894 | - |
1895 | - :raise UserFacingError: on failure to setup any aspect of this apt |
1896 | - configuration |
1897 | - """ |
1898 | - cmd = ["apt-mark", "showholds"] |
1899 | - holds = apt.run_apt_command(cmd, " ".join(cmd) + " failed.") |
1900 | - unholds = [] |
1901 | - for hold in holds.splitlines(): |
1902 | - if hold in self.fips_pro_package_holds: |
1903 | - unholds.append(hold) |
1904 | - if unholds: |
1905 | - unhold_cmd = ["apt-mark", "unhold"] + unholds |
1906 | - holds = apt.run_apt_command( |
1907 | - unhold_cmd, " ".join(unhold_cmd) + " failed." |
1908 | - ) |
1909 | - super().setup_apt_config(silent=silent) |
1910 | - |
1911 | def _perform_enable(self, silent: bool = False) -> bool: |
1912 | cloud_type, error = get_cloud_type() |
1913 | if cloud_type is None and error == NoCloudTypeReason.CLOUD_ID_ERROR: |
1914 | @@ -507,6 +518,20 @@ class FIPSUpdatesEntitlement(FIPSCommonEntitlement): |
1915 | description = "NIST-certified core packages with priority security updates" |
1916 | |
1917 | @property |
1918 | + def incompatible_services(self) -> Tuple[IncompatibleService, ...]: |
1919 | + from uaclient.entitlements.realtime import RealtimeKernelEntitlement |
1920 | + |
1921 | + return ( |
1922 | + IncompatibleService( |
1923 | + FIPSEntitlement, messages.FIPS_INVALIDATES_FIPS_UPDATES |
1924 | + ), |
1925 | + IncompatibleService( |
1926 | + RealtimeKernelEntitlement, |
1927 | + messages.REALTIME_FIPS_UPDATES_INCOMPATIBLE, |
1928 | + ), |
1929 | + ) |
1930 | + |
1931 | + @property |
1932 | def messaging(self,) -> MessagingOperationsDict: |
1933 | post_enable = None # type: Optional[MessagingOperations] |
1934 | if util.is_container(): |
1935 | diff --git a/uaclient/entitlements/livepatch.py b/uaclient/entitlements/livepatch.py |
1936 | index f652eb0..4fc9127 100644 |
1937 | --- a/uaclient/entitlements/livepatch.py |
1938 | +++ b/uaclient/entitlements/livepatch.py |
1939 | @@ -109,11 +109,16 @@ class LivepatchEntitlement(UAEntitlement): |
1940 | @property |
1941 | def incompatible_services(self) -> Tuple[IncompatibleService, ...]: |
1942 | from uaclient.entitlements.fips import FIPSEntitlement |
1943 | + from uaclient.entitlements.realtime import RealtimeKernelEntitlement |
1944 | |
1945 | return ( |
1946 | IncompatibleService( |
1947 | FIPSEntitlement, messages.LIVEPATCH_INVALIDATES_FIPS |
1948 | ), |
1949 | + IncompatibleService( |
1950 | + RealtimeKernelEntitlement, |
1951 | + messages.REALTIME_LIVEPATCH_INCOMPATIBLE, |
1952 | + ), |
1953 | ) |
1954 | |
1955 | @property |
1956 | diff --git a/uaclient/entitlements/realtime.py b/uaclient/entitlements/realtime.py |
1957 | new file mode 100644 |
1958 | index 0000000..35e5561 |
1959 | --- /dev/null |
1960 | +++ b/uaclient/entitlements/realtime.py |
1961 | @@ -0,0 +1,84 @@ |
1962 | +from typing import Tuple |
1963 | + |
1964 | +from uaclient import event_logger, messages, util |
1965 | +from uaclient.entitlements import repo |
1966 | +from uaclient.entitlements.base import IncompatibleService |
1967 | +from uaclient.types import MessagingOperationsDict, StaticAffordance |
1968 | + |
1969 | +event = event_logger.get_event_logger() |
1970 | + |
1971 | +REALTIME_KERNEL_DOCS_URL = "https://ubuntu.com/realtime-kernel" |
1972 | + |
1973 | + |
1974 | +class RealtimeKernelEntitlement(repo.RepoEntitlement): |
1975 | + name = "realtime-kernel" |
1976 | + title = "Real-Time Kernel" |
1977 | + description = "Beta-version Ubuntu Kernel with PREEMPT_RT patches" |
1978 | + help_doc_url = REALTIME_KERNEL_DOCS_URL |
1979 | + repo_key_file = "ubuntu-advantage-realtime-kernel.gpg" |
1980 | + is_beta = True |
1981 | + apt_noninteractive = True |
1982 | + |
1983 | + def _check_for_reboot(self) -> bool: |
1984 | + """Check if system needs to be rebooted.""" |
1985 | + reboot_required = util.should_reboot( |
1986 | + installed_pkgs=set(self.packages), |
1987 | + installed_pkgs_regex=set(["linux-.*-realtime"]), |
1988 | + ) |
1989 | + event.needs_reboot(reboot_required) |
1990 | + return reboot_required |
1991 | + |
1992 | + @property |
1993 | + def incompatible_services(self) -> Tuple[IncompatibleService, ...]: |
1994 | + from uaclient.entitlements.fips import ( |
1995 | + FIPSEntitlement, |
1996 | + FIPSUpdatesEntitlement, |
1997 | + ) |
1998 | + from uaclient.entitlements.livepatch import LivepatchEntitlement |
1999 | + |
2000 | + return ( |
2001 | + IncompatibleService( |
2002 | + FIPSEntitlement, messages.REALTIME_FIPS_INCOMPATIBLE |
2003 | + ), |
2004 | + IncompatibleService( |
2005 | + FIPSUpdatesEntitlement, |
2006 | + messages.REALTIME_FIPS_UPDATES_INCOMPATIBLE, |
2007 | + ), |
2008 | + IncompatibleService( |
2009 | + LivepatchEntitlement, messages.REALTIME_LIVEPATCH_INCOMPATIBLE |
2010 | + ), |
2011 | + ) |
2012 | + |
2013 | + @property |
2014 | + def static_affordances(self) -> Tuple[StaticAffordance, ...]: |
2015 | + return ( |
2016 | + ( |
2017 | + messages.REALTIME_ERROR_INSTALL_ON_CONTAINER, |
2018 | + lambda: util.is_container(), |
2019 | + False, |
2020 | + ), |
2021 | + ) |
2022 | + |
2023 | + @property |
2024 | + def messaging(self,) -> MessagingOperationsDict: |
2025 | + return { |
2026 | + "pre_enable": [ |
2027 | + ( |
2028 | + util.prompt_for_confirmation, |
2029 | + { |
2030 | + "msg": messages.REALTIME_BETA_PROMPT, |
2031 | + "assume_yes": self.assume_yes, |
2032 | + "default": True, |
2033 | + }, |
2034 | + ) |
2035 | + ], |
2036 | + "pre_disable": [ |
2037 | + ( |
2038 | + util.prompt_for_confirmation, |
2039 | + { |
2040 | + "msg": messages.REALTIME_PRE_DISABLE_PROMPT, |
2041 | + "assume_yes": self.assume_yes, |
2042 | + }, |
2043 | + ) |
2044 | + ], |
2045 | + } |
2046 | diff --git a/uaclient/entitlements/tests/test_cc.py b/uaclient/entitlements/tests/test_cc.py |
2047 | index 2e42b5f..362f5ea 100644 |
2048 | --- a/uaclient/entitlements/tests/test_cc.py |
2049 | +++ b/uaclient/entitlements/tests/test_cc.py |
2050 | @@ -110,8 +110,10 @@ class TestCommonCriteriaEntitlementEnable: |
2051 | @mock.patch("uaclient.util.should_reboot") |
2052 | @mock.patch("uaclient.util.subp") |
2053 | @mock.patch("uaclient.util.get_platform_info") |
2054 | + @mock.patch("uaclient.util.apply_contract_overrides") |
2055 | def test_enable_configures_apt_sources_and_auth_files( |
2056 | self, |
2057 | + _m_contract_overrides, |
2058 | m_platform_info, |
2059 | m_subp, |
2060 | m_should_reboot, |
2061 | diff --git a/uaclient/entitlements/tests/test_fips.py b/uaclient/entitlements/tests/test_fips.py |
2062 | index 8cf2898..51dc72f 100644 |
2063 | --- a/uaclient/entitlements/tests/test_fips.py |
2064 | +++ b/uaclient/entitlements/tests/test_fips.py |
2065 | @@ -21,6 +21,7 @@ from uaclient.entitlements.fips import ( |
2066 | FIPSEntitlement, |
2067 | FIPSUpdatesEntitlement, |
2068 | ) |
2069 | +from uaclient.status import CanEnableFailureReason |
2070 | |
2071 | M_PATH = "uaclient.entitlements.fips." |
2072 | M_LIVEPATCH_PATH = "uaclient.entitlements.livepatch.LivepatchEntitlement." |
2073 | @@ -302,9 +303,11 @@ class TestFIPSEntitlementEnable: |
2074 | stack.enter_context( |
2075 | mock.patch.object(type(entitlement), "packages", m_packages) |
2076 | ) |
2077 | + stack.enter_context( |
2078 | + mock.patch("uaclient.util.is_container", return_value=False) |
2079 | + ) |
2080 | |
2081 | m_can_enable.return_value = (True, None) |
2082 | - |
2083 | assert (True, None) == entitlement.enable() |
2084 | |
2085 | repo_url = "http://{}".format(entitlement.name.upper()) |
2086 | @@ -364,27 +367,20 @@ class TestFIPSEntitlementEnable: |
2087 | ) |
2088 | ) |
2089 | |
2090 | - if isinstance(entitlement, FIPSEntitlement): |
2091 | - subp_calls = [ |
2092 | - mock.call( |
2093 | - ["apt-mark", "showholds"], |
2094 | - capture=True, |
2095 | - retry_sleeps=apt.APT_RETRIES, |
2096 | - env={}, |
2097 | - ) |
2098 | - ] |
2099 | - else: |
2100 | - subp_calls = [] |
2101 | - subp_calls.extend( |
2102 | - [ |
2103 | - mock.call( |
2104 | - ["apt-get", "update"], |
2105 | - capture=True, |
2106 | - retry_sleeps=apt.APT_RETRIES, |
2107 | - env={}, |
2108 | - ) |
2109 | - ] |
2110 | - ) |
2111 | + subp_calls = [ |
2112 | + mock.call( |
2113 | + ["apt-mark", "showholds"], |
2114 | + capture=True, |
2115 | + retry_sleeps=apt.APT_RETRIES, |
2116 | + env={}, |
2117 | + ), |
2118 | + mock.call( |
2119 | + ["apt-get", "update"], |
2120 | + capture=True, |
2121 | + retry_sleeps=apt.APT_RETRIES, |
2122 | + env={}, |
2123 | + ), |
2124 | + ] |
2125 | subp_calls += install_cmd |
2126 | |
2127 | assert [mock.call()] == m_can_enable.call_args_list |
2128 | @@ -1092,6 +1088,10 @@ class TestFipsSetupAPTConfig: |
2129 | "openssh-server\nlibssl1.1-hmac\nasdf\n", |
2130 | ["openssh-server", "libssl1.1-hmac"], |
2131 | ), |
2132 | + ( |
2133 | + "libgcrypt20\nlibgcrypt20-hmac\nwow\n", |
2134 | + ["libgcrypt20", "libgcrypt20-hmac"], |
2135 | + ), |
2136 | ), |
2137 | ) |
2138 | @mock.patch(M_REPOPATH + "RepoEntitlement.setup_apt_config") |
2139 | @@ -1107,19 +1107,12 @@ class TestFipsSetupAPTConfig: |
2140 | """Unmark only fips-specific package holds if present.""" |
2141 | run_apt_command.return_value = held_packages |
2142 | entitlement.setup_apt_config(silent=False) |
2143 | - if isinstance(entitlement, FIPSUpdatesEntitlement): |
2144 | - expected_calls = [] |
2145 | - else: |
2146 | - expected_calls = [ |
2147 | - mock.call( |
2148 | - ["apt-mark", "showholds"], "apt-mark showholds failed." |
2149 | - ) |
2150 | - ] |
2151 | - if unhold_packages: |
2152 | - cmd = ["apt-mark", "unhold"] + unhold_packages |
2153 | - expected_calls.append( |
2154 | - mock.call(cmd, " ".join(cmd) + " failed.") |
2155 | - ) |
2156 | + expected_calls = [ |
2157 | + mock.call(["apt-mark", "showholds"], "apt-mark showholds failed.") |
2158 | + ] |
2159 | + if unhold_packages: |
2160 | + cmd = ["apt-mark", "unhold"] + unhold_packages |
2161 | + expected_calls.append(mock.call(cmd, " ".join(cmd) + " failed.")) |
2162 | assert expected_calls == run_apt_command.call_args_list |
2163 | assert [mock.call(silent=False)] == setup_apt_config.call_args_list |
2164 | |
2165 | @@ -1287,3 +1280,35 @@ class TestFIPSUpdatesEntitlementEnable: |
2166 | else: |
2167 | assert not m_read_cache.call_count |
2168 | assert not m_write_cache.call_count |
2169 | + |
2170 | + |
2171 | +class TestFIPSUpdatesEntitlementCanEnable: |
2172 | + @mock.patch("uaclient.util.is_config_value_true", return_value=False) |
2173 | + def test_can_enable_false_if_fips_enabled( |
2174 | + self, m_is_config_value_true, capsys, entitlement_factory |
2175 | + ): |
2176 | + """When entitlement is disabled, can_enable returns True.""" |
2177 | + entitlement = entitlement_factory(FIPSUpdatesEntitlement) |
2178 | + with mock.patch.object( |
2179 | + entitlement, |
2180 | + "applicability_status", |
2181 | + return_value=(status.ApplicabilityStatus.APPLICABLE, ""), |
2182 | + ): |
2183 | + with mock.patch.object( |
2184 | + entitlement, |
2185 | + "application_status", |
2186 | + return_value=(status.ApplicationStatus.DISABLED, ""), |
2187 | + ): |
2188 | + with mock.patch( |
2189 | + M_PATH + "FIPSEntitlement.application_status" |
2190 | + ) as m_fips_status: |
2191 | + m_fips_status.return_value = ( |
2192 | + status.ApplicationStatus.ENABLED, |
2193 | + None, |
2194 | + ) |
2195 | + actual_ret, reason = entitlement.can_enable() |
2196 | + assert actual_ret is False |
2197 | + assert ( |
2198 | + reason.reason |
2199 | + == CanEnableFailureReason.INCOMPATIBLE_SERVICE |
2200 | + ) |
2201 | diff --git a/uaclient/entitlements/tests/test_livepatch.py b/uaclient/entitlements/tests/test_livepatch.py |
2202 | index 191e91d..50fb50d 100644 |
2203 | --- a/uaclient/entitlements/tests/test_livepatch.py |
2204 | +++ b/uaclient/entitlements/tests/test_livepatch.py |
2205 | @@ -617,6 +617,7 @@ class TestLivepatchEntitlementEnable: |
2206 | @pytest.mark.parametrize("apt_update_success", (True, False)) |
2207 | @mock.patch("uaclient.util.get_platform_info") |
2208 | @mock.patch("uaclient.util.subp") |
2209 | + @mock.patch("uaclient.util.apply_contract_overrides") |
2210 | @mock.patch("uaclient.apt.run_apt_install_command") |
2211 | @mock.patch("uaclient.apt.run_apt_update_command") |
2212 | @mock.patch("uaclient.util.which", return_value=False) |
2213 | @@ -631,6 +632,7 @@ class TestLivepatchEntitlementEnable: |
2214 | m_which, |
2215 | m_run_apt_update, |
2216 | m_run_apt_install, |
2217 | + _m_contract_overrides, |
2218 | m_subp, |
2219 | _m_get_platform_info, |
2220 | m_livepatch_proxy, |
2221 | @@ -678,6 +680,7 @@ class TestLivepatchEntitlementEnable: |
2222 | |
2223 | @mock.patch("uaclient.util.get_platform_info") |
2224 | @mock.patch("uaclient.util.subp", return_value=("snapd", "")) |
2225 | + @mock.patch("uaclient.util.apply_contract_overrides") |
2226 | @mock.patch( |
2227 | "uaclient.util.which", side_effect=lambda cmd: cmd == "/usr/bin/snap" |
2228 | ) |
2229 | @@ -690,6 +693,7 @@ class TestLivepatchEntitlementEnable: |
2230 | m_can_enable, |
2231 | m_app_status, |
2232 | m_which, |
2233 | + _m_contract_overrides, |
2234 | m_subp, |
2235 | _m_get_platform_info, |
2236 | m_livepatch_proxy, |
2237 | @@ -759,6 +763,7 @@ class TestLivepatchEntitlementEnable: |
2238 | @mock.patch("uaclient.apt.get_installed_packages", return_value=["snapd"]) |
2239 | @mock.patch("uaclient.util.get_platform_info") |
2240 | @mock.patch("uaclient.util.subp") |
2241 | + @mock.patch("uaclient.util.apply_contract_overrides") |
2242 | @mock.patch("uaclient.util.which", side_effect=[True, True]) |
2243 | @mock.patch(M_PATH + "LivepatchEntitlement.application_status") |
2244 | @mock.patch( |
2245 | @@ -769,6 +774,7 @@ class TestLivepatchEntitlementEnable: |
2246 | m_can_enable, |
2247 | m_app_status, |
2248 | m_which, |
2249 | + _m_contract_overrides, |
2250 | m_subp, |
2251 | _m_get_platform_info, |
2252 | _m_get_installed_packages, |
2253 | @@ -808,6 +814,7 @@ class TestLivepatchEntitlementEnable: |
2254 | @mock.patch("uaclient.apt.get_installed_packages", return_value=["snapd"]) |
2255 | @mock.patch("uaclient.util.get_platform_info") |
2256 | @mock.patch("uaclient.util.subp") |
2257 | + @mock.patch("uaclient.util.apply_contract_overrides") |
2258 | @mock.patch("uaclient.util.which", side_effect=[True, True]) |
2259 | @mock.patch(M_PATH + "LivepatchEntitlement.application_status") |
2260 | @mock.patch( |
2261 | @@ -818,6 +825,7 @@ class TestLivepatchEntitlementEnable: |
2262 | m_can_enable, |
2263 | m_app_status, |
2264 | m_which, |
2265 | + _m_contract_overrides, |
2266 | m_subp, |
2267 | _m_get_platform_info, |
2268 | _m_get_installed_packages, |
2269 | diff --git a/uaclient/entitlements/tests/test_repo.py b/uaclient/entitlements/tests/test_repo.py |
2270 | index 084bab0..c59cb47 100644 |
2271 | --- a/uaclient/entitlements/tests/test_repo.py |
2272 | +++ b/uaclient/entitlements/tests/test_repo.py |
2273 | @@ -385,23 +385,25 @@ class TestProcessContractDeltas: |
2274 | |
2275 | class TestRepoEnable: |
2276 | @pytest.mark.parametrize( |
2277 | - "pre_enable_msg, output, can_enable_call_count", |
2278 | + "pre_enable_msg, output, perform_enable_call_count", |
2279 | ( |
2280 | (["msg1", (lambda: False, {}), "msg2"], "msg1\n", 0), |
2281 | (["msg1", (lambda: True, {}), "msg2"], "msg1\nmsg2\n", 1), |
2282 | ), |
2283 | ) |
2284 | @mock.patch.object( |
2285 | - RepoTestEntitlement, |
2286 | - "can_enable", |
2287 | - return_value=(False, status.CanEnableFailure(None)), |
2288 | + RepoTestEntitlement, "_perform_enable", return_value=False |
2289 | + ) |
2290 | + @mock.patch.object( |
2291 | + RepoTestEntitlement, "can_enable", return_value=(True, None) |
2292 | ) |
2293 | def test_enable_can_exit_on_pre_enable_messaging_hooks( |
2294 | self, |
2295 | - m_can_enable, |
2296 | + _m_can_enable, |
2297 | + m_perform_enable, |
2298 | pre_enable_msg, |
2299 | output, |
2300 | - can_enable_call_count, |
2301 | + perform_enable_call_count, |
2302 | entitlement, |
2303 | capsys, |
2304 | ): |
2305 | @@ -414,7 +416,7 @@ class TestRepoEnable: |
2306 | entitlement.enable() |
2307 | stdout, _ = capsys.readouterr() |
2308 | assert output == stdout |
2309 | - assert can_enable_call_count == m_can_enable.call_count |
2310 | + assert perform_enable_call_count == m_perform_enable.call_count |
2311 | |
2312 | @pytest.mark.parametrize( |
2313 | "pre_disable_msg,post_disable_msg,output,retval", |
2314 | @@ -734,8 +736,10 @@ class TestRemoveAptConfig: |
2315 | @mock.patch(M_PATH + "apt.remove_apt_list_files") |
2316 | @mock.patch(M_PATH + "apt.run_apt_command") |
2317 | @mock.patch(M_PATH + "util.get_platform_info") |
2318 | + @mock.patch(M_PATH + "util.apply_contract_overrides") |
2319 | def test_repo_pin_priority_int_removes_apt_preferences( |
2320 | self, |
2321 | + _m_contract_overrides, |
2322 | m_get_platform, |
2323 | _m_run_apt_command, |
2324 | _m_remove_apt_list_files, |
2325 | @@ -862,8 +866,10 @@ class TestSetupAptConfig: |
2326 | @mock.patch("uaclient.apt.setup_apt_proxy") |
2327 | @mock.patch(M_PATH + "apt.add_auth_apt_repo") |
2328 | @mock.patch(M_PATH + "apt.run_apt_install_command") |
2329 | + @mock.patch(M_PATH + "util.apply_contract_overrides") |
2330 | def test_install_prerequisite_packages( |
2331 | self, |
2332 | + _m_contract_overrides, |
2333 | m_run_apt_install_command, |
2334 | m_add_auth_repo, |
2335 | _m_setup_apt_proxy, |
2336 | @@ -908,8 +914,10 @@ class TestSetupAptConfig: |
2337 | @mock.patch(M_PATH + "apt.add_auth_apt_repo") |
2338 | @mock.patch(M_PATH + "apt.run_apt_command") |
2339 | @mock.patch(M_PATH + "util.get_platform_info") |
2340 | + @mock.patch(M_PATH + "util.apply_contract_overrides") |
2341 | def test_setup_with_repo_pin_priority_never_removes_apt_preferences_file( |
2342 | self, |
2343 | + _m_contract_overrides, |
2344 | m_get_platform_info, |
2345 | m_run_apt_command, |
2346 | m_add_auth_repo, |
2347 | @@ -940,8 +948,10 @@ class TestSetupAptConfig: |
2348 | @mock.patch(M_PATH + "apt.run_apt_update_command") |
2349 | @mock.patch(M_PATH + "apt.add_ppa_pinning") |
2350 | @mock.patch(M_PATH + "util.get_platform_info") |
2351 | + @mock.patch(M_PATH + "util.apply_contract_overrides") |
2352 | def test_setup_with_repo_pin_priority_int_adds_a_pins_repo_apt_preference( |
2353 | self, |
2354 | + _m_apply_overrides, |
2355 | m_get_platform_info, |
2356 | m_add_ppa_pinning, |
2357 | m_run_apt_update_command, |
2358 | diff --git a/uaclient/messages.py b/uaclient/messages.py |
2359 | index b7640b8..e9f5d9c 100644 |
2360 | --- a/uaclient/messages.py |
2361 | +++ b/uaclient/messages.py |
2362 | @@ -22,6 +22,7 @@ class TxtColor: |
2363 | OKGREEN = "\033[92m" |
2364 | DISABLEGREY = "\033[37m" |
2365 | FAIL = "\033[91m" |
2366 | + BOLD = "\033[1m" |
2367 | ENDC = "\033[0m" |
2368 | |
2369 | |
2370 | @@ -661,6 +662,12 @@ FIPS_UPDATES_INVALIDATES_FIPS = NamedMessage( |
2371 | " FIPS Updates installs security patches that aren't officially" |
2372 | " certified.", |
2373 | ) |
2374 | +FIPS_INVALIDATES_FIPS_UPDATES = NamedMessage( |
2375 | + "fips-invalidates-fips-updates", |
2376 | + "FIPS Updates cannot be enabled if FIPS is enabled." |
2377 | + " FIPS Updates installs security patches that aren't officially" |
2378 | + " certified.", |
2379 | +) |
2380 | LIVEPATCH_INVALIDATES_FIPS = NamedMessage( |
2381 | "livepatch-invalidates-fips", |
2382 | "Livepatch cannot be enabled while running the official FIPS" |
2383 | @@ -668,6 +675,45 @@ LIVEPATCH_INVALIDATES_FIPS = NamedMessage( |
2384 | " with additional bug fixes and security updates, you can use" |
2385 | " the FIPS Updates service with Livepatch.", |
2386 | ) |
2387 | +REALTIME_FIPS_INCOMPATIBLE = NamedMessage( |
2388 | + "realtime-fips-incompatible", |
2389 | + "Realtime and FIPS require different kernels, so you cannot enable" |
2390 | + " both at the same time.", |
2391 | +) |
2392 | +REALTIME_FIPS_UPDATES_INCOMPATIBLE = NamedMessage( |
2393 | + "realtime-fips-updates-incompatible", |
2394 | + "Realtime and FIPS Updates require different kernels, so you cannot enable" |
2395 | + " both at the same time.", |
2396 | +) |
2397 | +REALTIME_LIVEPATCH_INCOMPATIBLE = NamedMessage( |
2398 | + "realtime-livepatch-incompatible", |
2399 | + "Livepatch is not currently supported for the real-time kernel.", |
2400 | +) |
2401 | +REALTIME_BETA_FLAG_REQUIRED = NamedMessage( |
2402 | + "beta-flag-required", |
2403 | + "Use `ua enable realtime-kernel --beta` to acknowledge the real-time" |
2404 | + " kernel is currently in beta and comes with no support.", |
2405 | +) |
2406 | +REALTIME_BETA_PROMPT = """\ |
2407 | +The real-time kernel is a beta version of the 22.04 Ubuntu kernel with the |
2408 | +PREEMPT_RT patchset integrated for x86_64 and ARM64. |
2409 | + |
2410 | +{bold}You will not be able to revert to your original kernel after enabling\ |
2411 | + real-time.{end_bold} |
2412 | + |
2413 | +Do you want to continue? [ default = Yes ]: (Y/n) """.format( |
2414 | + bold=TxtColor.BOLD, end_bold=TxtColor.ENDC |
2415 | +) |
2416 | +REALTIME_PRE_DISABLE_PROMPT = """\ |
2417 | +This will disable the Real-Time Kernel entitlement but the Real-Time Kernel\ |
2418 | + will remain installed. |
2419 | +Are you sure? (y/N) """ |
2420 | + |
2421 | +REALTIME_ERROR_INSTALL_ON_CONTAINER = NamedMessage( |
2422 | + "realtime-error-install-on-container", |
2423 | + "Cannot install Real-Time Kernel on a container.", |
2424 | +) |
2425 | + |
2426 | |
2427 | LOG_CONNECTIVITY_ERROR_TMPL = CONNECTIVITY_ERROR.msg + " {error}" |
2428 | LOG_CONNECTIVITY_ERROR_WITH_URL_TMPL = ( |
2429 | diff --git a/uaclient/status.py b/uaclient/status.py |
2430 | index 7dd5ba2..3db4b67 100644 |
2431 | --- a/uaclient/status.py |
2432 | +++ b/uaclient/status.py |
2433 | @@ -225,17 +225,17 @@ Open a browser to: {}/subscribe""".format( |
2434 | BASE_UA_URL |
2435 | ) |
2436 | |
2437 | -STATUS_UNATTACHED_TMPL = "{name: <14}{available: <11}{description}" |
2438 | +STATUS_UNATTACHED_TMPL = "{name: <17}{available: <11}{description}" |
2439 | |
2440 | STATUS_SIMULATED_TMPL = """\ |
2441 | -{name: <14}{available: <11}{entitled: <11}{auto_enabled: <14}{description}""" |
2442 | +{name: <17}{available: <11}{entitled: <11}{auto_enabled: <14}{description}""" |
2443 | |
2444 | -STATUS_HEADER = "SERVICE ENTITLED STATUS DESCRIPTION" |
2445 | +STATUS_HEADER = "SERVICE ENTITLED STATUS DESCRIPTION" |
2446 | # The widths listed below for entitled and status are actually 9 characters |
2447 | # less than reality because we colorize the values in entitled and status |
2448 | # columns. Colorizing has an opening and closing set of unprintable characters |
2449 | # that factor into formats len() calculations |
2450 | -STATUS_TMPL = "{name: <14}{entitled: <19}{status: <19}{description}" |
2451 | +STATUS_TMPL = "{name: <17}{entitled: <19}{status: <19}{description}" |
2452 | |
2453 | |
2454 | def colorize(string: str) -> str: |
2455 | diff --git a/uaclient/tests/test_cli_attach.py b/uaclient/tests/test_cli_attach.py |
2456 | index 75cd0e1..e568f5f 100644 |
2457 | --- a/uaclient/tests/test_cli_attach.py |
2458 | +++ b/uaclient/tests/test_cli_attach.py |
2459 | @@ -532,14 +532,14 @@ class TestActionAttach: |
2460 | assert expected == json.loads(fake_stdout.getvalue()) |
2461 | |
2462 | @mock.patch("uaclient.contract.process_entitlement_delta") |
2463 | - @mock.patch("uaclient.util.apply_series_overrides") |
2464 | + @mock.patch("uaclient.util.apply_contract_overrides") |
2465 | @mock.patch("uaclient.contract.UAContractClient.request_url") |
2466 | @mock.patch("uaclient.jobs.update_messaging.update_apt_and_motd_messages") |
2467 | def test_attach_when_one_service_fails_to_enable( |
2468 | self, |
2469 | _m_update_messages, |
2470 | m_request_url, |
2471 | - _m_apply_series_overrides, |
2472 | + _m_apply_contract_overrides, |
2473 | m_process_entitlement_delta, |
2474 | _m_getuid, |
2475 | FakeConfig, |
2476 | diff --git a/uaclient/tests/test_cli_collect_logs.py b/uaclient/tests/test_cli_collect_logs.py |
2477 | index df6feba..accf283 100644 |
2478 | --- a/uaclient/tests/test_cli_collect_logs.py |
2479 | +++ b/uaclient/tests/test_cli_collect_logs.py |
2480 | @@ -124,8 +124,8 @@ class TestActionCollectLogs: |
2481 | ), |
2482 | ] |
2483 | |
2484 | - assert m_copy.call_count == 14 |
2485 | - assert redact.call_count == 14 |
2486 | + assert m_copy.call_count == 15 |
2487 | + assert redact.call_count == 15 |
2488 | |
2489 | |
2490 | class TestParser: |
2491 | diff --git a/uaclient/tests/test_cli_status.py b/uaclient/tests/test_cli_status.py |
2492 | index 125a896..1331955 100644 |
2493 | --- a/uaclient/tests/test_cli_status.py |
2494 | +++ b/uaclient/tests/test_cli_status.py |
2495 | @@ -24,6 +24,7 @@ RESPONSE_AVAILABLE_SERVICES = [ |
2496 | {"name": "esm-infra", "available": False}, |
2497 | {"name": "esm-apps", "available": True}, |
2498 | {"name": "fips-updates", "available": False}, |
2499 | + {"name": "realtime-kernel", "available": False}, |
2500 | {"name": "ros", "available": False}, |
2501 | {"name": "ros-updates", "available": False}, |
2502 | ] |
2503 | @@ -68,41 +69,34 @@ RESPONSE_CONTRACT_INFO = { |
2504 | } |
2505 | |
2506 | SIMULATED_STATUS = """\ |
2507 | -SERVICE AVAILABLE ENTITLED AUTO_ENABLED DESCRIPTION |
2508 | -esm-infra no yes yes UA Infra: Extended Security\ |
2509 | - Maintenance (ESM) |
2510 | -fips no no no NIST-certified core packages |
2511 | -fips-updates no no no NIST-certified core packages\ |
2512 | - with priority security updates |
2513 | -livepatch yes yes no Canonical Livepatch service |
2514 | -""" |
2515 | +SERVICE AVAILABLE ENTITLED AUTO_ENABLED DESCRIPTION |
2516 | +esm-infra no yes yes UA Infra: Extended Security Maintenance (ESM) |
2517 | +fips no no no NIST-certified core packages |
2518 | +fips-updates no no no NIST-certified core packages with priority security updates |
2519 | +livepatch yes yes no Canonical Livepatch service |
2520 | +""" # noqa: E501 |
2521 | |
2522 | UNATTACHED_STATUS = """\ |
2523 | -SERVICE AVAILABLE DESCRIPTION |
2524 | -esm-infra no UA Infra: Extended Security Maintenance (ESM) |
2525 | -fips no NIST-certified core packages |
2526 | -fips-updates no NIST-certified core packages with priority\ |
2527 | - security updates |
2528 | -livepatch yes Canonical Livepatch service |
2529 | +SERVICE AVAILABLE DESCRIPTION |
2530 | +esm-infra no UA Infra: Extended Security Maintenance (ESM) |
2531 | +fips no NIST-certified core packages |
2532 | +fips-updates no NIST-certified core packages with priority security updates |
2533 | +livepatch yes Canonical Livepatch service |
2534 | |
2535 | This machine is not attached to a UA subscription. |
2536 | See https://ubuntu.com/advantage |
2537 | -""" |
2538 | +""" # noqa: E501 |
2539 | |
2540 | ATTACHED_STATUS = """\ |
2541 | -SERVICE ENTITLED STATUS DESCRIPTION |
2542 | -esm-apps no {dash} UA Apps: Extended Security Maintenance\ |
2543 | - (ESM) |
2544 | -esm-infra no {dash} UA Infra: Extended Security Maintenance\ |
2545 | - (ESM) |
2546 | -fips no {dash} NIST-certified core packages |
2547 | -fips-updates no {dash} NIST-certified core packages with\ |
2548 | - priority security updates |
2549 | -livepatch no {dash} Canonical Livepatch service |
2550 | -ros no {dash} Security Updates for the Robot\ |
2551 | - Operating System |
2552 | -ros-updates no {dash} All Updates for the Robot Operating\ |
2553 | - System |
2554 | +SERVICE ENTITLED STATUS DESCRIPTION |
2555 | +esm-apps no {dash} UA Apps: Extended Security Maintenance (ESM) |
2556 | +esm-infra no {dash} UA Infra: Extended Security Maintenance (ESM) |
2557 | +fips no {dash} NIST-certified core packages |
2558 | +fips-updates no {dash} NIST-certified core packages with priority security updates |
2559 | +livepatch no {dash} Canonical Livepatch service |
2560 | +realtime-kernel no {dash} Beta-version Ubuntu Kernel with PREEMPT_RT patches |
2561 | +ros no {dash} Security Updates for the Robot Operating System |
2562 | +ros-updates no {dash} All Updates for the Robot Operating System |
2563 | {notices} |
2564 | Enable services with: ua enable <service> |
2565 | |
2566 | @@ -110,17 +104,15 @@ Enable services with: ua enable <service> |
2567 | Subscription: test_contract |
2568 | Valid until: 2040-05-08 19:02:26+00:00 |
2569 | Technical support level: n/a |
2570 | -""" |
2571 | +""" # noqa: E501 |
2572 | |
2573 | # Omit beta services from status |
2574 | ATTACHED_STATUS_NOBETA = """\ |
2575 | -SERVICE ENTITLED STATUS DESCRIPTION |
2576 | -esm-infra no {dash} UA Infra: Extended Security Maintenance\ |
2577 | - (ESM) |
2578 | -fips no {dash} NIST-certified core packages |
2579 | -fips-updates no {dash} NIST-certified core packages with\ |
2580 | - priority security updates |
2581 | -livepatch no {dash} Canonical Livepatch service |
2582 | +SERVICE ENTITLED STATUS DESCRIPTION |
2583 | +esm-infra no {dash} UA Infra: Extended Security Maintenance (ESM) |
2584 | +fips no {dash} NIST-certified core packages |
2585 | +fips-updates no {dash} NIST-certified core packages with priority security updates |
2586 | +livepatch no {dash} Canonical Livepatch service |
2587 | {notices} |
2588 | Enable services with: ua enable <service> |
2589 | |
2590 | @@ -128,9 +120,9 @@ Enable services with: ua enable <service> |
2591 | Subscription: test_contract |
2592 | Valid until: 2040-05-08 19:02:26+00:00 |
2593 | Technical support level: n/a |
2594 | -""" |
2595 | +""" # noqa: E501 |
2596 | |
2597 | -BETA_SVC_NAMES = ["esm-apps", "ros", "ros-updates"] |
2598 | +BETA_SVC_NAMES = ["esm-apps", "realtime-kernel", "ros", "ros-updates"] |
2599 | |
2600 | SERVICES_JSON_ALL = [ |
2601 | { |
2602 | @@ -186,6 +178,16 @@ SERVICES_JSON_ALL = [ |
2603 | "blocked_by": [], |
2604 | }, |
2605 | { |
2606 | + "description": "TODO", |
2607 | + "description_override": None, |
2608 | + "entitled": "no", |
2609 | + "name": "realtime-kernel", |
2610 | + "status": "—", |
2611 | + "status_details": "", |
2612 | + "available": "yes", |
2613 | + "blocked_by": [], |
2614 | + }, |
2615 | + { |
2616 | "description": "Security Updates for the Robot Operating System", |
2617 | "description_override": None, |
2618 | "entitled": "no", |
2619 | @@ -739,6 +741,14 @@ class TestActionStatus: |
2620 | { |
2621 | "auto_enabled": "no", |
2622 | "available": "no", |
2623 | + "description": "Beta-version Ubuntu Kernel with PREEMPT_RT" |
2624 | + " patches", |
2625 | + "entitled": "no", |
2626 | + "name": "realtime-kernel", |
2627 | + }, |
2628 | + { |
2629 | + "auto_enabled": "no", |
2630 | + "available": "no", |
2631 | "description": "Security Updates for the Robot Operating" |
2632 | " System", |
2633 | "entitled": "no", |
2634 | @@ -754,7 +764,7 @@ class TestActionStatus: |
2635 | ] |
2636 | |
2637 | if not use_all: |
2638 | - expected_services = expected_services[1:-2] |
2639 | + expected_services = expected_services[1:-3] |
2640 | |
2641 | expected = { |
2642 | "_doc": "Content provided in json response is currently considered" |
2643 | diff --git a/uaclient/tests/test_upgrade_lts_contract.py b/uaclient/tests/test_upgrade_lts_contract.py |
2644 | index 231fa17..7f76620 100644 |
2645 | --- a/uaclient/tests/test_upgrade_lts_contract.py |
2646 | +++ b/uaclient/tests/test_upgrade_lts_contract.py |
2647 | @@ -16,7 +16,7 @@ class TestUpgradeLTSContract: |
2648 | def test_unattached_noops(self, m_is_attached, capsys, caplog_text): |
2649 | expected_logs = [ |
2650 | "Check whether to upgrade-lts-contract", |
2651 | - "Skiping upgrade-lts-contract. Machine is unattached", |
2652 | + "Skipping upgrade-lts-contract. Machine is unattached", |
2653 | ] |
2654 | |
2655 | process_contract_delta_after_apt_lock() |
2656 | @@ -67,6 +67,72 @@ class TestUpgradeLTSContract: |
2657 | ) |
2658 | @mock.patch("lib.upgrade_lts_contract.parse_os_release") |
2659 | @mock.patch("lib.upgrade_lts_contract.subp") |
2660 | + def test_upgrade_cancel_when_current_version_not_supported( |
2661 | + self, m_subp, m_parse_os, m_is_attached, capsys, caplog_text |
2662 | + ): |
2663 | + m_parse_os.return_value = {"VERSION_ID": "NOT-SUPPORTED"} |
2664 | + m_subp.return_value = ("", "") |
2665 | + |
2666 | + expected_msgs = [ |
2667 | + "Starting upgrade-lts-contract.", |
2668 | + "Unable to get release codename for version: NOT-SUPPORTED", |
2669 | + ] |
2670 | + expected_logs = ["Check whether to upgrade-lts-contract"] |
2671 | + with pytest.raises(SystemExit) as execinfo: |
2672 | + process_contract_delta_after_apt_lock() |
2673 | + |
2674 | + assert 1 == execinfo.value.code |
2675 | + assert 1 == m_is_attached.call_count |
2676 | + assert 1 == m_parse_os.call_count |
2677 | + assert 1 == m_subp.call_count |
2678 | + out, _err = capsys.readouterr() |
2679 | + assert out == "\n".join(expected_msgs) + "\n" |
2680 | + debug_logs = caplog_text() |
2681 | + for log in expected_msgs + expected_logs: |
2682 | + assert log in debug_logs |
2683 | + |
2684 | + @mock.patch( |
2685 | + "uaclient.config.UAConfig.is_attached", |
2686 | + new_callable=mock.PropertyMock, |
2687 | + return_value=True, |
2688 | + ) |
2689 | + @mock.patch("lib.upgrade_lts_contract.parse_os_release") |
2690 | + @mock.patch("lib.upgrade_lts_contract.subp") |
2691 | + def test_upgrade_cancel_when_past_version_not_supported( |
2692 | + self, m_subp, m_parse_os, m_is_attached, capsys, caplog_text |
2693 | + ): |
2694 | + m_parse_os.return_value = {"VERSION_ID": "20.10"} |
2695 | + m_subp.return_value = ("", "") |
2696 | + |
2697 | + expected_msgs = [ |
2698 | + "Starting upgrade-lts-contract.", |
2699 | + "Could not find past release for: groovy", |
2700 | + ] |
2701 | + expected_logs = ["Check whether to upgrade-lts-contract"] |
2702 | + with pytest.raises(SystemExit) as execinfo: |
2703 | + with mock.patch( |
2704 | + "lib.upgrade_lts_contract.version_to_codename", |
2705 | + {"20.10": "groovy"}, |
2706 | + ): |
2707 | + process_contract_delta_after_apt_lock() |
2708 | + |
2709 | + assert 1 == execinfo.value.code |
2710 | + assert 1 == m_is_attached.call_count |
2711 | + assert 1 == m_parse_os.call_count |
2712 | + assert 1 == m_subp.call_count |
2713 | + out, _err = capsys.readouterr() |
2714 | + assert out == "\n".join(expected_msgs) + "\n" |
2715 | + debug_logs = caplog_text() |
2716 | + for log in expected_msgs + expected_logs: |
2717 | + assert log in debug_logs |
2718 | + |
2719 | + @mock.patch( |
2720 | + "uaclient.config.UAConfig.is_attached", |
2721 | + new_callable=mock.PropertyMock, |
2722 | + return_value=True, |
2723 | + ) |
2724 | + @mock.patch("lib.upgrade_lts_contract.parse_os_release") |
2725 | + @mock.patch("lib.upgrade_lts_contract.subp") |
2726 | @mock.patch("lib.upgrade_lts_contract.process_entitlements_delta") |
2727 | @mock.patch("lib.upgrade_lts_contract.time.sleep") |
2728 | def test_upgrade_contract_when_apt_lock_is_held( |
2729 | diff --git a/uaclient/tests/test_util.py b/uaclient/tests/test_util.py |
2730 | index 35bd8c0..99a7aa2 100644 |
2731 | --- a/uaclient/tests/test_util.py |
2732 | +++ b/uaclient/tests/test_util.py |
2733 | @@ -474,57 +474,244 @@ class TestGetPlatformInfo: |
2734 | assert expected == util.get_platform_info.__wrapped__() |
2735 | |
2736 | |
2737 | -class TestApplySeriesOverrides: |
2738 | +class TestApplyContractOverrides: |
2739 | + @pytest.mark.parametrize( |
2740 | + "override_selector,expected_weight", |
2741 | + ( |
2742 | + ({"selector1": "valueX", "selector2": "valueZ"}, 0), |
2743 | + ({"selector1": "valueA", "selector2": "valueZ"}, 0), |
2744 | + ({"selector1": "valueX", "selector2": "valueB"}, 0), |
2745 | + ({"selector1": "valueA"}, 1), |
2746 | + ({"selector2": "valueB"}, 2), |
2747 | + ({"selector1": "valueA", "selector2": "valueB"}, 3), |
2748 | + ), |
2749 | + ) |
2750 | + def test_get_override_weight(self, override_selector, expected_weight): |
2751 | + selector_values = {"selector1": "valueA", "selector2": "valueB"} |
2752 | + selector_weights = {"selector1": 1, "selector2": 2} |
2753 | + with mock.patch( |
2754 | + "uaclient.util.OVERRIDE_SELECTOR_WEIGHTS", selector_weights |
2755 | + ): |
2756 | + assert expected_weight == util._get_override_weight( |
2757 | + override_selector, selector_values |
2758 | + ) |
2759 | + |
2760 | def test_error_on_non_entitlement_dict(self): |
2761 | """Raise a runtime error when seeing invalid dict type.""" |
2762 | with pytest.raises(RuntimeError) as exc: |
2763 | - util.apply_series_overrides({"some": "dict"}) |
2764 | + util.apply_contract_overrides({"some": "dict"}) |
2765 | error = ( |
2766 | 'Expected entitlement access dict. Missing "entitlement" key:' |
2767 | " {'some': 'dict'}" |
2768 | ) |
2769 | assert error == str(exc.value) |
2770 | |
2771 | + @pytest.mark.parametrize("include_overrides", (True, False)) |
2772 | @mock.patch( |
2773 | - "uaclient.util.get_platform_info", return_value={"series": "xenial"} |
2774 | + "uaclient.util.get_platform_info", return_value={"series": "ubuntuX"} |
2775 | ) |
2776 | - def test_mutates_orig_access_dict(self, _): |
2777 | - """Mutate orig_access dict when called.""" |
2778 | + @mock.patch( |
2779 | + "uaclient.clouds.identity.get_cloud_type", return_value=(None, "") |
2780 | + ) |
2781 | + def test_return_same_dict_when_no_overrides_match( |
2782 | + self, _m_cloud_type, _m_platform_info, include_overrides |
2783 | + ): |
2784 | orig_access = { |
2785 | "entitlement": { |
2786 | - "a": {"a1": "av1", "a2": {"aa2": "aav2"}}, |
2787 | - "b": "b1", |
2788 | - "c": "c1", |
2789 | + "affordances": {"some_affordance": ["ubuntuX"]}, |
2790 | + "directives": {"some_directive": ["ubuntuX"]}, |
2791 | + "obligations": {"some_obligation": False}, |
2792 | + } |
2793 | + } |
2794 | + # exactly the same |
2795 | + expected = { |
2796 | + "entitlement": { |
2797 | + "affordances": {"some_affordance": ["ubuntuX"]}, |
2798 | + "directives": {"some_directive": ["ubuntuX"]}, |
2799 | + "obligations": {"some_obligation": False}, |
2800 | + } |
2801 | + } |
2802 | + if include_overrides: |
2803 | + orig_access["entitlement"].update( |
2804 | + { |
2805 | + "series": { |
2806 | + "dontMatch": { |
2807 | + "affordances": { |
2808 | + "some_affordance": ["ubuntuX-series-overriden"] |
2809 | + } |
2810 | + } |
2811 | + }, |
2812 | + "overrides": [ |
2813 | + { |
2814 | + "selector": {"series": "dontMatch"}, |
2815 | + "affordances": { |
2816 | + "some_affordance": ["ubuntuX-series-overriden"] |
2817 | + }, |
2818 | + }, |
2819 | + { |
2820 | + "selector": {"cloud": "dontMatch"}, |
2821 | + "affordances": { |
2822 | + "some_affordance": ["ubuntuX-cloud-overriden"] |
2823 | + }, |
2824 | + }, |
2825 | + ], |
2826 | + } |
2827 | + ) |
2828 | + |
2829 | + util.apply_contract_overrides(orig_access) |
2830 | + assert expected == orig_access |
2831 | + |
2832 | + @mock.patch( |
2833 | + "uaclient.util.get_platform_info", return_value={"series": "ubuntuX"} |
2834 | + ) |
2835 | + def test_missing_keys_are_included(self, _m_platform_info): |
2836 | + orig_access = { |
2837 | + "entitlement": { |
2838 | + "series": {"ubuntuX": {"directives": {"suites": ["ubuntuX"]}}} |
2839 | + } |
2840 | + } |
2841 | + expected = {"entitlement": {"directives": {"suites": ["ubuntuX"]}}} |
2842 | + |
2843 | + util.apply_contract_overrides(orig_access) |
2844 | + |
2845 | + assert expected == orig_access |
2846 | + |
2847 | + @pytest.mark.parametrize( |
2848 | + "series_selector,cloud_selector,series_cloud_selector,expected_value", |
2849 | + ( |
2850 | + # apply_overrides_when_only_series_match |
2851 | + ("no-match", "no-match", "no-match", "old_series_overriden"), |
2852 | + # series selector is applied over old series override |
2853 | + ("ubuntuX", "no-match", "no-match", "series_overriden"), |
2854 | + # cloud selector is applied over series override |
2855 | + ("no-match", "cloudX", "no-match", "cloud_overriden"), |
2856 | + # cloud selector is applied over series selector |
2857 | + ("ubuntuX", "cloudX", "no-match", "cloud_overriden"), |
2858 | + # cloud and series together are applied over others |
2859 | + ("ubuntuX", "cloudX", "cloudX", "both_overriden"), |
2860 | + ), |
2861 | + ) |
2862 | + @mock.patch( |
2863 | + "uaclient.util.get_platform_info", return_value={"series": "ubuntuX"} |
2864 | + ) |
2865 | + @mock.patch( |
2866 | + "uaclient.clouds.identity.get_cloud_type", |
2867 | + return_value=("cloudX", None), |
2868 | + ) |
2869 | + def test_applies_contract_overrides_respecting_weight( |
2870 | + self, |
2871 | + _m_cloud_type, |
2872 | + _m_platform_info, |
2873 | + series_selector, |
2874 | + cloud_selector, |
2875 | + series_cloud_selector, |
2876 | + expected_value, |
2877 | + ): |
2878 | + """Apply the expected overrides to orig_access dict when called.""" |
2879 | + orig_access = { |
2880 | + "entitlement": { |
2881 | + "affordances": {"some_affordance": ["original_affordance"]}, |
2882 | "series": { |
2883 | - "trusty": {"a": "t1"}, |
2884 | - "xenial": {"a": {"a2": {"aa2": "xxv2"}}, "b": "bx1"}, |
2885 | + "ubuntuX": { |
2886 | + "affordances": { |
2887 | + "some_affordance": ["old_series_overriden"] |
2888 | + } |
2889 | + } |
2890 | }, |
2891 | + "overrides": [ |
2892 | + { |
2893 | + "selector": {"series": series_selector}, |
2894 | + "affordances": { |
2895 | + "some_affordance": ["series_overriden"] |
2896 | + }, |
2897 | + }, |
2898 | + { |
2899 | + "selector": {"cloud": cloud_selector}, |
2900 | + "affordances": { |
2901 | + "some_affordance": ["cloud_overriden"] |
2902 | + }, |
2903 | + }, |
2904 | + { |
2905 | + "selector": { |
2906 | + "series": series_selector, |
2907 | + "cloud": series_cloud_selector, |
2908 | + }, |
2909 | + "affordances": {"some_affordance": ["both_overriden"]}, |
2910 | + }, |
2911 | + ], |
2912 | } |
2913 | } |
2914 | + |
2915 | expected = { |
2916 | "entitlement": { |
2917 | - "a": {"a1": "av1", "a2": {"aa2": "xxv2"}}, |
2918 | - "b": "bx1", |
2919 | - "c": "c1", |
2920 | + "affordances": {"some_affordance": [expected_value]} |
2921 | } |
2922 | } |
2923 | - util.apply_series_overrides(orig_access) |
2924 | + |
2925 | + util.apply_contract_overrides(orig_access) |
2926 | assert orig_access == expected |
2927 | |
2928 | @mock.patch( |
2929 | - "uaclient.util.get_platform_info", return_value={"series": "xenial"} |
2930 | + "uaclient.util.get_platform_info", return_value={"series": "ubuntuX"} |
2931 | + ) |
2932 | + @mock.patch( |
2933 | + "uaclient.clouds.identity.get_cloud_type", |
2934 | + return_value=("cloudX", None), |
2935 | ) |
2936 | - def test_missing_keys_are_handled(self, _): |
2937 | + def test_different_overrides_applied_together( |
2938 | + self, _m_cloud_type, _m_platform_info |
2939 | + ): |
2940 | + """Apply different overrides from different matching selectors.""" |
2941 | orig_access = { |
2942 | "entitlement": { |
2943 | - "series": {"xenial": {"directives": {"suites": ["xenial"]}}} |
2944 | + "affordances": {"some_affordance": ["original_affordance"]}, |
2945 | + "directives": {"some_directive": ["original_directive"]}, |
2946 | + "obligations": {"some_obligation": False}, |
2947 | + "series": { |
2948 | + "ubuntuX": { |
2949 | + "affordances": { |
2950 | + "new_affordance": ["new_affordance_value"] |
2951 | + } |
2952 | + } |
2953 | + }, |
2954 | + "overrides": [ |
2955 | + { |
2956 | + "selector": {"series": "ubuntuX"}, |
2957 | + "affordances": { |
2958 | + "some_affordance": ["series_overriden"] |
2959 | + }, |
2960 | + }, |
2961 | + { |
2962 | + "selector": {"cloud": "cloudX"}, |
2963 | + "directives": {"some_directive": ["cloud_overriden"]}, |
2964 | + }, |
2965 | + { |
2966 | + "selector": {"series": "ubuntuX", "cloud": "cloudX"}, |
2967 | + "obligations": { |
2968 | + "new_obligation": True, |
2969 | + "some_obligation": True, |
2970 | + }, |
2971 | + }, |
2972 | + ], |
2973 | } |
2974 | } |
2975 | - expected = {"entitlement": {"directives": {"suites": ["xenial"]}}} |
2976 | |
2977 | - util.apply_series_overrides(orig_access) |
2978 | + expected = { |
2979 | + "entitlement": { |
2980 | + "affordances": { |
2981 | + "new_affordance": ["new_affordance_value"], |
2982 | + "some_affordance": ["series_overriden"], |
2983 | + }, |
2984 | + "directives": {"some_directive": ["cloud_overriden"]}, |
2985 | + "obligations": { |
2986 | + "new_obligation": True, |
2987 | + "some_obligation": True, |
2988 | + }, |
2989 | + } |
2990 | + } |
2991 | |
2992 | - assert expected == orig_access |
2993 | + util.apply_contract_overrides(orig_access) |
2994 | + assert orig_access == expected |
2995 | |
2996 | |
2997 | class TestGetMachineId: |
2998 | @@ -1263,13 +1450,18 @@ class TestShouldReboot: |
2999 | assert 1 == m_load_file.call_count |
3000 | |
3001 | @pytest.mark.parametrize( |
3002 | - "installed_pkgs,reboot_required_pkgs,expected_ret", |
3003 | + "installed_pkgs,installed_pkgs_regex,reboot_required_pkgs," |
3004 | + "expected_ret", |
3005 | ( |
3006 | - (set(["a", "b", "c"]), "", False), |
3007 | - (set(["a", "b", "c"]), "a", True), |
3008 | - (set(["a", "b", "c"]), "a\ne", True), |
3009 | - (set(["a", "b", "c"]), "d\ne", False), |
3010 | - (None, "a\ne", True), |
3011 | + (set(["a", "b", "c"]), None, "", False), |
3012 | + (set(["a", "b", "c"]), None, "a", True), |
3013 | + (set(["a", "b", "c"]), None, "a\ne", True), |
3014 | + (set(["a", "b", "c"]), None, "d\ne", False), |
3015 | + (set(["a", "b", "c"]), set(["t.."]), "a\ne", True), |
3016 | + (set(["a", "b", "c"]), set(["t.."]), "one\ntwo", True), |
3017 | + (None, set(["^t..$"]), "one\ntwo", True), |
3018 | + (None, set(["^t..$"]), "one\nthree", False), |
3019 | + (None, None, "a\ne", True), |
3020 | ), |
3021 | ) |
3022 | @mock.patch("os.path.exists") |
3023 | @@ -1279,11 +1471,13 @@ class TestShouldReboot: |
3024 | m_load_file, |
3025 | m_path, |
3026 | installed_pkgs, |
3027 | + installed_pkgs_regex, |
3028 | reboot_required_pkgs, |
3029 | expected_ret, |
3030 | ): |
3031 | m_path.return_value = True |
3032 | m_load_file.return_value = reboot_required_pkgs |
3033 | assert expected_ret == util.should_reboot( |
3034 | - installed_pkgs=installed_pkgs |
3035 | + installed_pkgs=installed_pkgs, |
3036 | + installed_pkgs_regex=installed_pkgs_regex, |
3037 | ) |
3038 | diff --git a/uaclient/util.py b/uaclient/util.py |
3039 | index 674f302..346f202 100644 |
3040 | --- a/uaclient/util.py |
3041 | +++ b/uaclient/util.py |
3042 | @@ -44,6 +44,8 @@ PROXY_VALIDATION_APT_HTTPS_URL = "https://esm.ubuntu.com" |
3043 | PROXY_VALIDATION_SNAP_HTTP_URL = "http://api.snapcraft.io" |
3044 | PROXY_VALIDATION_SNAP_HTTPS_URL = "https://api.snapcraft.io" |
3045 | |
3046 | +OVERRIDE_SELECTOR_WEIGHTS = {"series_overrides": 1, "series": 2, "cloud": 3} |
3047 | + |
3048 | event = event_logger.get_event_logger() |
3049 | |
3050 | |
3051 | @@ -100,7 +102,43 @@ class DatetimeAwareJSONDecoder(json.JSONDecoder): |
3052 | return o |
3053 | |
3054 | |
3055 | -def apply_series_overrides( |
3056 | +def _get_override_weight( |
3057 | + override_selector: Dict[str, str], selector_values: Dict[str, str] |
3058 | +) -> int: |
3059 | + override_weight = 0 |
3060 | + for selector, value in override_selector.items(): |
3061 | + if (selector, value) not in selector_values.items(): |
3062 | + return 0 |
3063 | + override_weight += OVERRIDE_SELECTOR_WEIGHTS[selector] |
3064 | + |
3065 | + return override_weight |
3066 | + |
3067 | + |
3068 | +def _select_overrides( |
3069 | + entitlement: Dict[str, Any], series_name: str, cloud_type: str |
3070 | +) -> Dict[int, Dict[str, Any]]: |
3071 | + overrides = {} |
3072 | + |
3073 | + selector_values = {"series": series_name, "cloud": cloud_type} |
3074 | + |
3075 | + series_overrides = entitlement.pop("series", {}).pop(series_name, {}) |
3076 | + if series_overrides: |
3077 | + overrides[ |
3078 | + OVERRIDE_SELECTOR_WEIGHTS["series_overrides"] |
3079 | + ] = series_overrides |
3080 | + |
3081 | + general_overrides = entitlement.pop("overrides", []) |
3082 | + for override in general_overrides: |
3083 | + weight = _get_override_weight( |
3084 | + override.pop("selector"), selector_values |
3085 | + ) |
3086 | + if weight: |
3087 | + overrides[weight] = override |
3088 | + |
3089 | + return overrides |
3090 | + |
3091 | + |
3092 | +def apply_contract_overrides( |
3093 | orig_access: Dict[str, Any], series: str = None |
3094 | ) -> None: |
3095 | """Apply series-specific overrides to an entitlement dict. |
3096 | @@ -117,23 +155,30 @@ def apply_series_overrides( |
3097 | |
3098 | :param orig_access: Dict with original entitlement access details |
3099 | """ |
3100 | + from uaclient.clouds.identity import get_cloud_type |
3101 | + |
3102 | if not all([isinstance(orig_access, dict), "entitlement" in orig_access]): |
3103 | raise RuntimeError( |
3104 | 'Expected entitlement access dict. Missing "entitlement" key:' |
3105 | " {}".format(orig_access) |
3106 | ) |
3107 | + |
3108 | series_name = get_platform_info()["series"] if series is None else series |
3109 | + cloud_type, _ = get_cloud_type() |
3110 | orig_entitlement = orig_access.get("entitlement", {}) |
3111 | - overrides = orig_entitlement.pop("series", {}).pop(series_name, {}) |
3112 | - for key, value in overrides.items(): |
3113 | - current = orig_access["entitlement"].get(key) |
3114 | - if isinstance(current, dict): |
3115 | - # If the key already exists and is a dict, update that dict using |
3116 | - # the override |
3117 | - current.update(value) |
3118 | - else: |
3119 | - # Otherwise, replace it wholesale |
3120 | - orig_access["entitlement"][key] = value |
3121 | + |
3122 | + overrides = _select_overrides(orig_entitlement, series_name, cloud_type) |
3123 | + |
3124 | + for _weight, overrides_to_apply in sorted(overrides.items()): |
3125 | + for key, value in overrides_to_apply.items(): |
3126 | + current = orig_access["entitlement"].get(key) |
3127 | + if isinstance(current, dict): |
3128 | + # If the key already exists and is a dict, |
3129 | + # update that dict using the override |
3130 | + current.update(value) |
3131 | + else: |
3132 | + # Otherwise, replace it wholesale |
3133 | + orig_access["entitlement"][key] = value |
3134 | |
3135 | |
3136 | def del_file(path: str) -> None: |
3137 | @@ -431,13 +476,16 @@ def prompt_choices(msg: str = "", valid_choices: List[str] = []) -> str: |
3138 | return value |
3139 | |
3140 | |
3141 | -def prompt_for_confirmation(msg: str = "", assume_yes: bool = False) -> bool: |
3142 | +def prompt_for_confirmation( |
3143 | + msg: str = "", assume_yes: bool = False, default: bool = False |
3144 | +) -> bool: |
3145 | """ |
3146 | Display a confirmation prompt, returning a bool indicating the response |
3147 | |
3148 | :param msg: String custom prompt text to emit from input call. |
3149 | :param assume_yes: Boolean set True to skip confirmation input and return |
3150 | True. |
3151 | + :param default: Boolean to return when user doesn't enter any text |
3152 | |
3153 | This function will only prompt a single time, and defaults to "no" (i.e. it |
3154 | returns False). |
3155 | @@ -446,8 +494,10 @@ def prompt_for_confirmation(msg: str = "", assume_yes: bool = False) -> bool: |
3156 | return True |
3157 | if not msg: |
3158 | msg = status.PROMPT_YES_NO |
3159 | - value = input(msg) |
3160 | - if value.lower().strip() in ["y", "yes"]: |
3161 | + value = input(msg).lower().strip() |
3162 | + if value == "": |
3163 | + return default |
3164 | + if value in ["y", "yes"]: |
3165 | return True |
3166 | return False |
3167 | |
3168 | @@ -756,14 +806,26 @@ def redact_sensitive_logs( |
3169 | return redacted_log |
3170 | |
3171 | |
3172 | -def should_reboot(installed_pkgs: Optional[Set[str]] = None) -> bool: |
3173 | +def should_reboot( |
3174 | + installed_pkgs: Optional[Set[str]] = None, |
3175 | + installed_pkgs_regex: Optional[Set[str]] = None, |
3176 | +) -> bool: |
3177 | """Check if the system needs to be rebooted. |
3178 | |
3179 | - :param installed_pkgs: If provided, verify if the any packages in |
3180 | - the list are present on /var/run/reboot-required.pkgs. If that |
3181 | - param is provided, we will only return true if we have the |
3182 | - reboot-required marker file and any package in reboot-required.pkgs |
3183 | - file. |
3184 | + :param installed_pkgs: If provided, verify if the any packages in |
3185 | + the list are present on /var/run/reboot-required.pkgs. If that |
3186 | + param is provided, we will only return true if we have the |
3187 | + reboot-required marker file and any package in reboot-required.pkgs |
3188 | + file. When both installed_pkgs and installed_pkgs_regex are |
3189 | + provided, they act as an OR, so only one of the two lists must have |
3190 | + a match to return True. |
3191 | + :param installed_pkgs_regex: If provided, verify if the any regex in |
3192 | + the list matches any line in /var/run/reboot-required.pkgs. If that |
3193 | + param is provided, we will only return true if we have the |
3194 | + reboot-required marker file and any match in reboot-required.pkgs |
3195 | + file. When both installed_pkgs and installed_pkgs_regex are |
3196 | + provided, they act as an OR, so only one of the two lists must have |
3197 | + a match to return True. |
3198 | """ |
3199 | |
3200 | # If the reboot marker file doesn't exist, we don't even |
3201 | @@ -773,7 +835,7 @@ def should_reboot(installed_pkgs: Optional[Set[str]] = None) -> bool: |
3202 | |
3203 | # If there is no installed_pkgs to check, we will rely only |
3204 | # on the existence of the reboot marker file |
3205 | - if installed_pkgs is None: |
3206 | + if installed_pkgs is None and installed_pkgs_regex is None: |
3207 | return True |
3208 | |
3209 | try: |
3210 | @@ -784,8 +846,18 @@ def should_reboot(installed_pkgs: Optional[Set[str]] = None) -> bool: |
3211 | # If the file doesn't exist, we will default to the |
3212 | # reboot marker file |
3213 | return True |
3214 | - else: |
3215 | - return len(installed_pkgs.intersection(reboot_required_pkgs)) != 0 |
3216 | + |
3217 | + if installed_pkgs is not None: |
3218 | + if len(installed_pkgs.intersection(reboot_required_pkgs)) != 0: |
3219 | + return True |
3220 | + |
3221 | + if installed_pkgs_regex is not None: |
3222 | + for pkg_name in reboot_required_pkgs: |
3223 | + for pkg_regex in installed_pkgs_regex: |
3224 | + if re.search(pkg_regex, pkg_name): |
3225 | + return True |
3226 | + |
3227 | + return False |
3228 | |
3229 | |
3230 | def is_installed(package_name: str) -> bool: |
3231 | diff --git a/uaclient/version.py b/uaclient/version.py |
3232 | index f65a60c..b99afa0 100644 |
3233 | --- a/uaclient/version.py |
3234 | +++ b/uaclient/version.py |
3235 | @@ -8,7 +8,7 @@ import os.path |
3236 | |
3237 | from uaclient import exceptions, util |
3238 | |
3239 | -__VERSION__ = "27.7" |
3240 | +__VERSION__ = "27.8" |
3241 | PACKAGED_VERSION = "@@PACKAGED_VERSION@@" |
3242 | VERSION_TMPL = "{version}{feature_suffix}" |
3243 |
+1 from an SRU perspective. I would like the usual QA done on this though. For a 0-day SRU, I'm not sure how this would work and have asked in #ubuntu-release. The upload can go in now though as it'll be held in Unapproved since it's seeded.