Merge ~orndorffgrant/ubuntu/+source/ubuntu-advantage-tools:upload-27.7-jammy into ubuntu/+source/ubuntu-advantage-tools:ubuntu/devel
- Git
- lp:~orndorffgrant/ubuntu/+source/ubuntu-advantage-tools
- upload-27.7-jammy
- Merge into ubuntu/devel
Status: | Needs review |
---|---|
Proposed branch: | ~orndorffgrant/ubuntu/+source/ubuntu-advantage-tools:upload-27.7-jammy |
Merge into: | ubuntu/+source/ubuntu-advantage-tools:ubuntu/devel |
Diff against target: |
17891 lines (+8036/-2570) 109 files modified
Jenkinsfile (+36/-0) Makefile (+1/-0) README.md (+27/-6) RELEASES.md (+14/-22) apt-hook/json-hook-src/json-hook_test.go (+40/-40) debian/changelog (+37/-0) debian/ubuntu-advantage-tools.logrotate (+1/-0) debian/ubuntu-advantage-tools.postinst (+7/-8) features/_version.feature (+2/-2) features/attach_invalidtoken.feature (+6/-2) features/attach_validtoken.feature (+150/-8) features/attached_commands.feature (+97/-73) features/attached_enable.feature (+85/-22) features/attached_status.feature (+2/-13) features/aws-ids.yaml (+5/-3) features/azure-ids.yaml (+2/-0) features/cloud.py (+6/-3) features/detached_auto_attach.feature (+32/-0) features/enable_fips_container.feature (+144/-0) features/enable_fips_vm.feature (+60/-1) features/install_uninstall.feature (+0/-1) features/license_check.feature (+3/-3) features/proxy_config.feature (+24/-5) features/schemas/ua_operation.json (+76/-0) features/schemas/ua_security_status.json (+81/-0) features/schemas/ua_status.json (+247/-0) features/steps/steps.py (+138/-35) features/ubuntu_pro.feature (+104/-9) features/ubuntu_pro_fips.feature (+210/-0) features/ubuntu_upgrade.feature (+3/-3) features/ubuntu_upgrade_unattached.feature (+3/-3) features/unattached_commands.feature (+75/-23) features/unattached_status.feature (+100/-48) features/util.py (+7/-0) integration-requirements.txt (+1/-0) lib/reboot_cmds.py (+11/-12) setup.py (+3/-11) sru/release-27.7/test_world_readable_logs.sh (+66/-0) tools/create-lp-release-branches.sh (+1/-2) tools/refresh-aws-pro-ids (+23/-12) tools/run-integration-tests.py (+3/-4) tox.ini (+14/-8) uaclient/actions.py (+60/-10) uaclient/apt.py (+70/-19) uaclient/cli.py (+345/-162) uaclient/clouds/gcp.py (+1/-0) uaclient/clouds/identity.py (+2/-2) uaclient/clouds/tests/test_aws.py (+4/-2) uaclient/clouds/tests/test_identity.py (+9/-11) uaclient/config.py (+119/-58) uaclient/conftest.py (+25/-0) uaclient/contract.py (+97/-109) uaclient/data_types.py (+196/-0) uaclient/defaults.py (+1/-0) uaclient/entitlements/__init__.py (+7/-1) uaclient/entitlements/base.py (+246/-132) uaclient/entitlements/cc.py (+2/-3) uaclient/entitlements/cis.py (+4/-3) uaclient/entitlements/esm.py (+7/-4) uaclient/entitlements/fips.py (+148/-62) uaclient/entitlements/livepatch.py (+54/-36) uaclient/entitlements/repo.py (+53/-38) uaclient/entitlements/tests/test_base.py (+247/-39) uaclient/entitlements/tests/test_cc.py (+2/-2) uaclient/entitlements/tests/test_entitlements.py (+3/-2) uaclient/entitlements/tests/test_esm.py (+10/-8) uaclient/entitlements/tests/test_fips.py (+163/-57) uaclient/entitlements/tests/test_livepatch.py (+43/-36) uaclient/entitlements/tests/test_repo.py (+26/-32) uaclient/event_logger.py (+221/-0) uaclient/exceptions.py (+251/-26) uaclient/jobs/metering.py (+2/-9) uaclient/jobs/update_messaging.py (+21/-22) uaclient/messages.py (+674/-0) uaclient/security.py (+123/-86) uaclient/security_status.py (+55/-34) uaclient/serviceclient.py (+4/-4) uaclient/snap.py (+5/-3) uaclient/status.py (+38/-395) uaclient/testing/fakes.py (+17/-0) uaclient/tests/test_actions.py (+15/-15) uaclient/tests/test_apt.py (+11/-14) uaclient/tests/test_cli.py (+11/-11) uaclient/tests/test_cli_attach.py (+413/-27) uaclient/tests/test_cli_auto_attach.py (+7/-7) uaclient/tests/test_cli_detach.py (+170/-24) uaclient/tests/test_cli_disable.py (+310/-47) uaclient/tests/test_cli_enable.py (+406/-83) uaclient/tests/test_cli_refresh.py (+10/-10) uaclient/tests/test_cli_security_status.py (+2/-27) uaclient/tests/test_cli_status.py (+167/-13) uaclient/tests/test_config.py (+79/-15) uaclient/tests/test_contract.py (+93/-93) uaclient/tests/test_data_types.py (+386/-0) uaclient/tests/test_event_logger.py (+141/-0) uaclient/tests/test_gpg.py (+9/-6) uaclient/tests/test_lock.py (+3/-3) uaclient/tests/test_reboot_cmds.py (+3/-3) uaclient/tests/test_security.py (+303/-215) uaclient/tests/test_security_status.py (+79/-19) uaclient/tests/test_serviceclient.py (+4/-4) uaclient/tests/test_snap.py (+7/-4) uaclient/tests/test_update_messaging.py (+22/-36) uaclient/tests/test_util.py (+37/-30) uaclient/tests/test_version.py (+2/-2) uaclient/types.py (+7/-2) uaclient/util.py (+23/-67) uaclient/version.py (+3/-3) ubuntu-advantage.1 (+11/-1) |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Paride Legovini (community) | Approve | ||
Canonical Server Core Reviewers | Pending | ||
Review via email: mp+416678@code.launchpad.net |
Commit message
Description of the change
This is release 27.7 of ubuntu-
Please review the FFe request here: https:/
And the SRU bug here: https:/
- bc721e4... by Renan Rodrigo
-
gcp: add pro license for Jammy
Signed-off-by: Renan Rodrigo <email address hidden>
Lucas Albuquerque Medeiros de Moura (lamoura) wrote : | # |
We have found an issue in the current release. We have addressed this problem on this MR:
https:/
Please do any type of review there instead
Unmerged commits
- bc721e4... by Renan Rodrigo
-
gcp: add pro license for Jammy
Signed-off-by: Renan Rodrigo <email address hidden>
- 9433db4... by Grant Orndorff
-
changelog: fix trailer line for 27.4.1
- cd08064... by Lucas Albuquerque Medeiros de Moura
-
fix ubuntu upgrade tests for jammy
- 5b135d4... by Lucas Albuquerque Medeiros de Moura
-
fix integration test failures
- feff165... by Grant Orndorff
-
release 27.7 changelog entry
- 68ca8e6... by Grant Orndorff
-
chore: bump version to 27.7
- cf59d1d... by Renan Rodrigo
-
chore: bump security-status schema version to 0.1
Signed-off-by: Renan Rodrigo <email address hidden>
- 7db6f2d... by Renan Rodrigo
-
cli: include the origin site for security-status updates
Signed-off-by: Renan Rodrigo <email address hidden>
- 8eb6694... by Renan Rodrigo
-
cli: include installed ESM package counts in security-status
Signed-off-by: Renan Rodrigo <email address hidden>
- 90d18b1... by Renan Rodrigo
-
cli: remove beta flag from the security-status command
Signed-off-by: Renan Rodrigo <email address hidden>
Preview Diff
1 | diff --git a/Jenkinsfile b/Jenkinsfile |
2 | index f9ca868..9c71624 100644 |
3 | --- a/Jenkinsfile |
4 | +++ b/Jenkinsfile |
5 | @@ -141,6 +141,27 @@ pipeline { |
6 | ''' |
7 | } |
8 | } |
9 | + stage ('Package build: 22.04') { |
10 | + environment { |
11 | + BUILD_SERIES = "jammy" |
12 | + SERIES_VERSION = "22.04" |
13 | + PKG_VERSION = sh(returnStdout: true, script: "dpkg-parsechangelog --show-field Version").trim() |
14 | + NEW_PKG_VERSION = "${PKG_VERSION}~${SERIES_VERSION}~${JOB_SUFFIX}" |
15 | + ARTIFACT_DIR = "${TMPDIR}${BUILD_SERIES}" |
16 | + } |
17 | + steps { |
18 | + sh ''' |
19 | + set -x |
20 | + mkdir ${ARTIFACT_DIR} |
21 | + cp debian/changelog ${WORKSPACE}/debian/changelog-${SERIES_VERSION} |
22 | + sed -i "s/${PKG_VERSION}/${NEW_PKG_VERSION}/" ${WORKSPACE}/debian/changelog-${SERIES_VERSION} |
23 | + dpkg-source -l${WORKSPACE}/debian/changelog-${SERIES_VERSION} -b . |
24 | + sbuild --resolve-alternatives --nolog --verbose --dist=${BUILD_SERIES} --no-run-lintian --append-to-version=~${SERIES_VERSION} ../ubuntu-advantage-tools*${NEW_PKG_VERSION}*dsc |
25 | + cp ./ubuntu-advantage-tools*${SERIES_VERSION}*.deb ${ARTIFACT_DIR}/ubuntu-advantage-tools-${BUILD_SERIES}.deb |
26 | + cp ./ubuntu-advantage-pro*${SERIES_VERSION}*.deb ${ARTIFACT_DIR}/ubuntu-advantage-pro-${BUILD_SERIES}.deb |
27 | + ''' |
28 | + } |
29 | + } |
30 | } |
31 | } |
32 | stage ('Integration Tests') { |
33 | @@ -190,6 +211,21 @@ pipeline { |
34 | ''' |
35 | } |
36 | } |
37 | + stage("lxc 22.04") { |
38 | + environment { |
39 | + UACLIENT_BEHAVE_DEBS_PATH = "${TMPDIR}jammy/" |
40 | + UACLIENT_BEHAVE_ARTIFACT_DIR = "artifacts/behave-lxd-22.04" |
41 | + UACLIENT_BEHAVE_EPHEMERAL_INSTANCE = 1 |
42 | + UACLIENT_BEHAVE_SNAPSHOT_STRATEGY = 1 |
43 | + } |
44 | + steps { |
45 | + sh ''' |
46 | + set +x |
47 | + . $TMPDIR/bin/activate |
48 | + tox --parallel--safe-build -e behave-lxd-22.04 -- --tags="~slow" |
49 | + ''' |
50 | + } |
51 | + } |
52 | stage("lxc vm 20.04") { |
53 | environment { |
54 | UACLIENT_BEHAVE_DEBS_PATH = "${TMPDIR}focal/" |
55 | diff --git a/Makefile b/Makefile |
56 | index e8ce957..87932a8 100644 |
57 | --- a/Makefile |
58 | +++ b/Makefile |
59 | @@ -33,6 +33,7 @@ ifneq (,$(findstring trusty,$(TOXENV))) |
60 | endif |
61 | pip install tox |
62 | pip install tox-pip-version |
63 | + pip install tox-setuptools-version |
64 | |
65 | travis-deb-install: |
66 | git fetch --unshallow |
67 | diff --git a/README.md b/README.md |
68 | index a9040e2..8d413c5 100644 |
69 | --- a/README.md |
70 | +++ b/README.md |
71 | @@ -33,7 +33,7 @@ Below is a list of platforms and releases ubuntu-advantage-tools supports |
72 | | Bionic | amd64, arm64, armhf, i386, ppc64el, s390x | Active SRU of all features | |
73 | | Focal | amd64, arm64, armhf, ppc64el, riscv64, s390x | Active SRU of all features | |
74 | | Groovy | amd64, arm64, armhf, ppc64el, riscv64, s390x | Last release 27.1 | |
75 | -| Hirsute | amd64, arm64, armhf, ppc64el, riscv64, s390x | Active SRU of all features | |
76 | +| Hirsute | amd64, arm64, armhf, ppc64el, riscv64, s390x | Last release 27.5 | |
77 | | Impish | amd64, arm64, armhf, ppc64el, riscv64, s390x | Active SRU of all features | |
78 | |
79 | Note: ppc64el will not have support for APT JSON hook messaging due to insufficient golang packages |
80 | @@ -107,6 +107,27 @@ https://ubuntu.com/advantage. |
81 | * UA client auto-enables any services defined with |
82 | `obligations:{enableByDefault: true}` |
83 | |
84 | +#### Attaching with --attach-config |
85 | +Running `ua attach` with the `--attach-config` may be better suited to certain scenarios. |
86 | + |
87 | +When using `--attach-config` the token must be passed in the file rather than on the command line. This is useful in situations where it is preffered to keep the secret token in a file. |
88 | + |
89 | +Optionally, the attach config file can be used to override the services that are automatically enabled as a part of the attach process. |
90 | + |
91 | +An attach config file looks like this: |
92 | +```yaml |
93 | +token: YOUR_TOKEN_HERE # required |
94 | +enable_services: # optional list of service names to auto-enable |
95 | + - esm-infra |
96 | + - esm-apps |
97 | + - cis |
98 | +``` |
99 | + |
100 | +And can be passed on the cli like this: |
101 | +```shell |
102 | +sudo ua attach --attach-config /path/to/file.yaml |
103 | +``` |
104 | + |
105 | ### Enabling a service |
106 | Each service controlled by UA client will have a python module in |
107 | uaclient/entitlements/\*.py which handles setup and teardown of services when |
108 | @@ -367,9 +388,9 @@ when you should set UACLIENT_BEHAVE_SNAPSHOT_STRATEGY=1 |
109 | The following tox environments allow for testing focal on EC2: |
110 | |
111 | ``` |
112 | - # To test ubuntu-pro-images on EC2 |
113 | + # To test ubuntu-pro-images |
114 | tox -e behave-awspro-20.04 |
115 | - # To test Canonical cloud images (non-ubuntu-pro) on EC2 |
116 | + # To test Canonical cloud images (non-ubuntu-pro) |
117 | tox -e behave-awsgeneric-20.04 |
118 | ``` |
119 | |
120 | @@ -417,9 +438,9 @@ UACLIENT_BEHAVE_REUSE_IMAGE=your-custom-ami tox -e behave-awspro-20.04 |
121 | The following tox environments allow for testing focal on Azure: |
122 | |
123 | ``` |
124 | - # To test ubuntu-pro-images on EC2 |
125 | + # To test ubuntu-pro-images |
126 | tox -e behave-azurepro-20.04 |
127 | - # To test Canonical cloud images (non-ubuntu-pro) on EC2 |
128 | + # To test Canonical cloud images (non-ubuntu-pro) |
129 | tox -e behave-azuregeneric-20.04 |
130 | ``` |
131 | |
132 | @@ -563,7 +584,7 @@ the project, you should install them via `dev-requirements.txt`.) |
133 | ## Daily Builds |
134 | |
135 | On Launchpad, there is a [daily build recipe](https://code.launchpad.net/~canonical-server/+recipe/ua-client-daily), |
136 | -which will build the client and place it in the [ua-client-daily PPA](https://code.launchpad.net/~canonical-server/+archive/ubuntu/ua-client-daily). |
137 | +which will build the client and place it in the [ua-client-daily PPA](https://code.launchpad.net/~ua-client/+archive/ubuntu/daily). |
138 | |
139 | ## Remastering custom golden images based on Ubuntu PRO |
140 | |
141 | diff --git a/RELEASES.md b/RELEASES.md |
142 | index 20096a2..3ea848a 100644 |
143 | --- a/RELEASES.md |
144 | +++ b/RELEASES.md |
145 | @@ -226,9 +226,11 @@ If this is your first time releasing ubuntu-advantage-tools, you'll need to do t |
146 | lxc exec dev-i -- bash /setup_proposed.sh |
147 | ``` |
148 | |
149 | - e. Once [ubuntu-advantage-tools shows up in the pending_sru page](https://people.canonical.com/~ubuntu-archive/pending-sru.html), perform the [Ubuntu-advantage-client SRU verification steps](https://wiki.ubuntu.com/UbuntuAdvantageToolsUpdates). This typically involves running all behave targets with `UACLIENT_BEHAVE_ENABLE_PROPOSED=1 UACLIENT_BEHAVE_CHECK_VERSION=<this-version>` and saving the output. |
150 | + e. With the package in proposed, perform the steps from `I.3` above but use a `~stableppaX` suffix instead of `~rcX` in the version name, and upload to `ppa:ua-client/stable` instead of staging. |
151 | |
152 | - f. After all tests have passed, tarball all of the output files and upload them to the SRU bug with a message that looks like this: |
153 | + f. Once [ubuntu-advantage-tools shows up in the pending_sru page](https://people.canonical.com/~ubuntu-archive/pending-sru.html), perform the [Ubuntu-advantage-client SRU verification steps](https://wiki.ubuntu.com/UbuntuAdvantageToolsUpdates). This typically involves running all behave targets with `UACLIENT_BEHAVE_ENABLE_PROPOSED=1 UACLIENT_BEHAVE_CHECK_VERSION=<this-version>` and saving the output. |
154 | + |
155 | + g. After all tests have passed, tarball all of the output files and upload them to the SRU bug with a message that looks like this: |
156 | ``` |
157 | We have run the full ubuntu-advantage-tools integration test suite against the version in -proposed. The results are attached. All tests passed (or call out specific explained failures). |
158 | |
159 | @@ -238,33 +240,23 @@ If this is your first time releasing ubuntu-advantage-tools, you'll need to do t |
160 | ``` |
161 | Change the tags on the bug from `verification-needed` to `verification-done` (including the verification tags for each release). |
162 | |
163 | - g. For any other related Launchpad bugs that are fixed in this release. Perform the verification steps necessary for those bugs and mark them `verification-done` as needed. This will likely involve following the test steps, but instead of adding the staging PPA, enabling -proposed. |
164 | + h. For any other related Launchpad bugs that are fixed in this release. Perform the verification steps necessary for those bugs and mark them `verification-done` as needed. This will likely involve following the test steps, but instead of adding the staging PPA, enabling -proposed. |
165 | |
166 | - h. Once all SRU bugs are tagged as `verification*-done`, all SRU-bugs should be listed as green in [the pending_sru page](https://people.canonical.com/~ubuntu-archive/pending-sru.html). |
167 | + i. Once all SRU bugs are tagged as `verification*-done`, all SRU-bugs should be listed as green in [the pending_sru page](https://people.canonical.com/~ubuntu-archive/pending-sru.html). |
168 | |
169 | - i. After the pending sru page says that ubuntu-advantage-tools has been in proposed for 7 days, it is now time to ping the [current SRU vanguard](https://wiki.ubuntu.com/StableReleaseUpdates#Publishing) for acceptance of ubuntu-advantage-tools into -updates. |
170 | + j. After the pending sru page says that ubuntu-advantage-tools has been in proposed for 7 days, it is now time to ping the [current SRU vanguard](https://wiki.ubuntu.com/StableReleaseUpdates#Publishing) for acceptance of ubuntu-advantage-tools into -updates. |
171 | |
172 | - j. Ping the Ubuntu Server team member who approved the version in step `II.4` to now upload to the devel release. |
173 | + k. Ping the Ubuntu Server team member who approved the version in step `II.4` to now upload to the devel release. |
174 | |
175 | - k. Check `rmadison ubuntu-advantage-tools` for updated version in devel release |
176 | + l. Check `rmadison ubuntu-advantage-tools` for updated version in devel release |
177 | |
178 | - l. Confirm availability in <devel-series>-updates pocket via `lxc launch ubuntu-daily:<devel-series> dev-i; lxc exec dev-i -- apt update; lxc exec dev-i -- apt-cache policy ubuntu-advantage-tools` |
179 | + m. Confirm availability in <devel-series>-updates pocket via `lxc launch ubuntu-daily:<devel-series> dev-i; lxc exec dev-i -- apt update; lxc exec dev-i -- apt-cache policy ubuntu-advantage-tools` |
180 | |
181 | -### III. Final release to team infrastructure |
182 | +### III. Github Repository Post-release Update |
183 | |
184 | 1. Ensure the version tag is correct on github. The `version` git tag should point to the commit that was released as that version to ubuntu -updates. If changes were made in response to feedback during the release process, the tag may have to be moved. |
185 | -2. Perform the steps from `I.3` above but use a `~stableppaX` suffix instead of `~rcX` in the version name, and upload to `ppa:ua-client/stable` instead of staging. |
186 | -3. Bring in any changes that were made to the release branch into `main` via PR (e.g. Changelog edits). |
187 | - |
188 | -## Ubuntu PRO Release Process |
189 | +2. Bring in any changes that were made to the release branch into `main` via PR (e.g. Changelog edits). |
190 | |
191 | -Below is the procedure used to release ubuntu-advantage-tools to Ubuntu PRO images: |
192 | +## Cloud Images Update |
193 | |
194 | - 1. [Open Daily PPA copy-package operation](https://code.launchpad.net/~ua-client/+archive/ubuntu/daily/+copy-packages) |
195 | - 2. Check Xenial, Bionic, Focal, Hirsute, Impish packages |
196 | - 3. Select Destination PPA: UA Client Premium [~ua-client/ubuntu/staging] |
197 | - 4. Select Destination series: The same series |
198 | - 5. Copy options: "Copy existing binaries" |
199 | - 6. Click Copy packages |
200 | - 7. Notify Pro Image creators about expected Premium PPA version (patviafore/powersj) |
201 | - 8. Once new PRO AMIs are publicly available run `./tools/refresh-aws-pro-ids` to update AMIs we test during CI runs |
202 | +After the release process is finished, CPC must be informed. They will be responsible to update the cloud images using the package from the pockets it was released to (whether it is the `stable` PPA or the`-updates` pocket). |
203 | diff --git a/apt-hook/json-hook-src/json-hook_test.go b/apt-hook/json-hook-src/json-hook_test.go |
204 | index 0a2a2eb..695f323 100644 |
205 | --- a/apt-hook/json-hook-src/json-hook_test.go |
206 | +++ b/apt-hook/json-hook-src/json-hook_test.go |
207 | @@ -114,9 +114,9 @@ const mockJson = ` |
208 | "pin": 500, |
209 | "origins": [ |
210 | { |
211 | - "archive": "hirsute-apps-security", |
212 | - "codename": "hirsute", |
213 | - "version": "21.04", |
214 | + "archive": "focal-apps-security", |
215 | + "codename": "focal", |
216 | + "version": "20.04", |
217 | "origin": "UbuntuESMApps", |
218 | "label": "Ubuntu", |
219 | "site": "" |
220 | @@ -130,9 +130,9 @@ const mockJson = ` |
221 | "pin": 500, |
222 | "origins": [ |
223 | { |
224 | - "archive": "hirsute-apps-security", |
225 | - "codename": "hirsute", |
226 | - "version": "21.04", |
227 | + "archive": "focal-apps-security", |
228 | + "codename": "focal", |
229 | + "version": "20.04", |
230 | "origin": "UbuntuESMApps", |
231 | "label": "Ubuntu", |
232 | "site": "" |
233 | @@ -162,9 +162,9 @@ const mockJson = ` |
234 | "pin": 500, |
235 | "origins": [ |
236 | { |
237 | - "archive": "hirsute-apps-security", |
238 | - "codename": "hirsute", |
239 | - "version": "21.04", |
240 | + "archive": "focal-apps-security", |
241 | + "codename": "focal", |
242 | + "version": "20.04", |
243 | "origin": "UbuntuESMApps", |
244 | "label": "Ubuntu", |
245 | "site": "" |
246 | @@ -178,9 +178,9 @@ const mockJson = ` |
247 | "pin": 500, |
248 | "origins": [ |
249 | { |
250 | - "archive": "hirsute-apps-security", |
251 | - "codename": "hirsute", |
252 | - "version": "21.04", |
253 | + "archive": "focal-apps-security", |
254 | + "codename": "focal", |
255 | + "version": "20.04", |
256 | "origin": "UbuntuESMApps", |
257 | "label": "Ubuntu", |
258 | "site": "" |
259 | @@ -210,17 +210,17 @@ const mockJson = ` |
260 | "pin": 500, |
261 | "origins": [ |
262 | { |
263 | - "archive": "hirsute-infra-security", |
264 | - "codename": "hirsute", |
265 | - "version": "21.04", |
266 | + "archive": "focal-infra-security", |
267 | + "codename": "focal", |
268 | + "version": "20.04", |
269 | "origin": "UbuntuESM", |
270 | "label": "Ubuntu", |
271 | "site": "" |
272 | }, |
273 | { |
274 | - "archive": "hirsute", |
275 | - "codename": "hirsute", |
276 | - "version": "21.04", |
277 | + "archive": "focal", |
278 | + "codename": "focal", |
279 | + "version": "20.04", |
280 | "origin": "Ubuntu", |
281 | "label": "Ubuntu", |
282 | "site": "" |
283 | @@ -234,17 +234,17 @@ const mockJson = ` |
284 | "pin": 500, |
285 | "origins": [ |
286 | { |
287 | - "archive": "hirsute-infra-security", |
288 | - "codename": "hirsute", |
289 | - "version": "21.04", |
290 | + "archive": "focal-infra-security", |
291 | + "codename": "focal", |
292 | + "version": "20.04", |
293 | "origin": "UbuntuESM", |
294 | "label": "Ubuntu", |
295 | "site": "" |
296 | }, |
297 | { |
298 | - "archive": "hirsute", |
299 | - "codename": "hirsute", |
300 | - "version": "21.04", |
301 | + "archive": "focal", |
302 | + "codename": "focal", |
303 | + "version": "20.04", |
304 | "origin": "Ubuntu", |
305 | "label": "Ubuntu", |
306 | "site": "" |
307 | @@ -274,9 +274,9 @@ const mockJson = ` |
308 | "pin": 500, |
309 | "origins": [ |
310 | { |
311 | - "archive": "hirsute-infra-security", |
312 | - "codename": "hirsute", |
313 | - "version": "21.04", |
314 | + "archive": "focal-infra-security", |
315 | + "codename": "focal", |
316 | + "version": "20.04", |
317 | "origin": "UbuntuESM", |
318 | "label": "Ubuntu", |
319 | "site": "" |
320 | @@ -290,9 +290,9 @@ const mockJson = ` |
321 | "pin": 500, |
322 | "origins": [ |
323 | { |
324 | - "archive": "hirsute-infra-security", |
325 | - "codename": "hirsute", |
326 | - "version": "21.04", |
327 | + "archive": "focal-infra-security", |
328 | + "codename": "focal", |
329 | + "version": "20.04", |
330 | "origin": "UbuntuESM", |
331 | "label": "Ubuntu", |
332 | "site": "" |
333 | @@ -322,8 +322,8 @@ const mockJson = ` |
334 | "pin": 500, |
335 | "origins": [ |
336 | { |
337 | - "archive": "hirsute-apps-security", |
338 | - "codename": "hirsute", |
339 | + "archive": "focal-apps-security", |
340 | + "codename": "focal", |
341 | "version": "1.0", |
342 | "origin": "UbuntuESMApps", |
343 | "label": "Google", |
344 | @@ -338,8 +338,8 @@ const mockJson = ` |
345 | "pin": 500, |
346 | "origins": [ |
347 | { |
348 | - "archive": "hirsute-apps-security", |
349 | - "codename": "hirsute", |
350 | + "archive": "focal-apps-security", |
351 | + "codename": "focal", |
352 | "version": "1.0", |
353 | "origin": "UbuntuESMApps", |
354 | "label": "Google", |
355 | @@ -370,9 +370,9 @@ const mockJson = ` |
356 | "pin": 500, |
357 | "origins": [ |
358 | { |
359 | - "archive": "hirsute-security", |
360 | - "codename": "hirsute", |
361 | - "version": "21.04", |
362 | + "archive": "focal-security", |
363 | + "codename": "focal", |
364 | + "version": "20.04", |
365 | "origin": "Ubuntu", |
366 | "label": "Ubuntu", |
367 | "site": "" |
368 | @@ -386,9 +386,9 @@ const mockJson = ` |
369 | "pin": 500, |
370 | "origins": [ |
371 | { |
372 | - "archive": "hirsute-security", |
373 | - "codename": "hirsute", |
374 | - "version": "21.04", |
375 | + "archive": "focal-security", |
376 | + "codename": "focal", |
377 | + "version": "20.04", |
378 | "origin": "Ubuntu", |
379 | "label": "Ubuntu", |
380 | "site": "" |
381 | diff --git a/debian/changelog b/debian/changelog |
382 | index 6feeb98..60f3d35 100644 |
383 | --- a/debian/changelog |
384 | +++ b/debian/changelog |
385 | @@ -1,3 +1,40 @@ |
386 | +ubuntu-advantage-tools (27.7~22.04.1) jammy; urgency=medium |
387 | + |
388 | + * d/changelog: |
389 | + - fix changelog trailer line for 27.4.1 |
390 | + * d/logrotate: |
391 | + - make new logs world readable |
392 | + * d/tools.postinst: |
393 | + - refactor to catch exception from entitlement_factory |
394 | + - no longer always set log file to only root readable |
395 | + - when creating log file for the first time, make world readable |
396 | + * New upstream release 27.7 (LP: #1964028) |
397 | + - attach: --attach-config option for customizing auto-enabled services |
398 | + and supplying token via a file |
399 | + - auto-attach: fix bug where auto-attach caused a manually attached |
400 | + machine to detach |
401 | + - cli: |
402 | + + support --format=json for attach |
403 | + + support --format=json for detach |
404 | + + support --format=json for enable |
405 | + + support --format=json for disable |
406 | + - contract: include activity info when updating contract |
407 | + - detach: no longer contacts contract server on detach |
408 | + - fips: allow fips on containers |
409 | + - fix: support USNs that don't have related CVEs |
410 | + - logs: make all newly created logs world-readable |
411 | + - security-status: |
412 | + + show already installed esm package counts |
413 | + + include APT origin for each potential update |
414 | + + bump schema version to "0.1" |
415 | + + remove previously required --beta flag |
416 | + - status: |
417 | + + include blocked_by information in service status when format=json |
418 | + + --simulate-with-token now reports expired tokens as errors |
419 | + + --simulate-with-token now returns errors in the specified format |
420 | + |
421 | + -- Grant Orndorff <grant.orndorff@canonical.com> Mon, 07 Mar 2022 13:14:57 -0500 |
422 | + |
423 | ubuntu-advantage-tools (27.6~22.04.1) jammy; urgency=medium |
424 | |
425 | * New upstream release 27.6 (LP: #1958556) |
426 | diff --git a/debian/ubuntu-advantage-tools.logrotate b/debian/ubuntu-advantage-tools.logrotate |
427 | index 76e6b47..7c64857 100644 |
428 | --- a/debian/ubuntu-advantage-tools.logrotate |
429 | +++ b/debian/ubuntu-advantage-tools.logrotate |
430 | @@ -2,6 +2,7 @@ |
431 | # of /var/log/ubuntu-advantage*.log files. |
432 | /var/log/ubuntu-advantage*.log { |
433 | su root root |
434 | + create 0644 root root |
435 | rotate 6 |
436 | monthly |
437 | compress |
438 | diff --git a/debian/ubuntu-advantage-tools.postinst b/debian/ubuntu-advantage-tools.postinst |
439 | index 191f0db..014c044 100644 |
440 | --- a/debian/ubuntu-advantage-tools.postinst |
441 | +++ b/debian/ubuntu-advantage-tools.postinst |
442 | @@ -119,12 +119,12 @@ check_service_is_beta() { |
443 | _IS_BETA_SVC=$(/usr/bin/python3 -c " |
444 | from uaclient.config import UAConfig |
445 | from uaclient.entitlements import entitlement_factory |
446 | -ent_cls = entitlement_factory('${service_name}') |
447 | -if ent_cls: |
448 | +try: |
449 | + ent_cls = entitlement_factory('${service_name}') |
450 | cfg = UAConfig() |
451 | allow_beta = cfg.features.get('allow_beta', False) |
452 | print(all([ent_cls.is_beta, not allow_beta])) |
453 | -else: |
454 | +except Exception: |
455 | print(True) |
456 | ") |
457 | if [ "${_IS_BETA_SVC}" = "True" ]; then |
458 | @@ -419,15 +419,14 @@ case "$1" in |
459 | fi |
460 | fi |
461 | |
462 | - # We modify permissions for ubuntu-advantage.log because |
463 | - # in a past version of UA, this log file was world readable. |
464 | - # This isn't necessary for the timer/license-check log files, |
465 | - # because they have always been only root-readable. |
466 | + # log files need to be world-readable |
467 | if [ ! -f /var/log/ubuntu-advantage.log ]; then |
468 | touch /var/log/ubuntu-advantage.log |
469 | + # We are only making new log files world readable |
470 | + chmod 0644 /var/log/ubuntu-advantage.log |
471 | fi |
472 | - chmod 0600 /var/log/ubuntu-advantage.log |
473 | chown root:root /var/log/ubuntu-advantage.log |
474 | + |
475 | private_dir="/var/lib/ubuntu-advantage/private" |
476 | if [ -d "$private_dir" ]; then |
477 | chmod 0700 "$private_dir" |
478 | diff --git a/features/_version.feature b/features/_version.feature |
479 | index e265769..b972500 100644 |
480 | --- a/features/_version.feature |
481 | +++ b/features/_version.feature |
482 | @@ -6,8 +6,10 @@ Feature: UA is expected version |
483 | @uses.config.machine_type.lxd.vm |
484 | @uses.config.machine_type.aws.generic |
485 | @uses.config.machine_type.aws.pro |
486 | + @uses.config.machine_type.aws.pro.fips |
487 | @uses.config.machine_type.azure.generic |
488 | @uses.config.machine_type.azure.pro |
489 | + @uses.config.machine_type.azure.pro.fips |
490 | @uses.config.machine_type.gcp.generic |
491 | @uses.config.machine_type.gcp.pro |
492 | Scenario Outline: Check ua version |
493 | @@ -30,7 +32,6 @@ Feature: UA is expected version |
494 | | xenial | |
495 | | bionic | |
496 | | focal | |
497 | - | hirsute | |
498 | | impish | |
499 | | jammy | |
500 | |
501 | @@ -58,5 +59,4 @@ Feature: UA is expected version |
502 | | xenial | |
503 | | bionic | |
504 | | focal | |
505 | - | hirsute | |
506 | | impish | |
507 | diff --git a/features/attach_invalidtoken.feature b/features/attach_invalidtoken.feature |
508 | index 6ad2d93..59435c2 100644 |
509 | --- a/features/attach_invalidtoken.feature |
510 | +++ b/features/attach_invalidtoken.feature |
511 | @@ -15,12 +15,17 @@ Feature: Command behaviour when trying to attach a machine to an Ubuntu |
512 | """ |
513 | This command must be run as root (try using sudo). |
514 | """ |
515 | + When I verify that running `ua attach invalid-token --format json` `with sudo` exits `1` |
516 | + Then I will see the following on stdout: |
517 | + """ |
518 | + {"_schema_version": "0.1", "errors": [{"message": "Invalid token. See https://ubuntu.com/advantage", "message_code": "attach-invalid-token", "service": null, "type": "system"}], "failed_services": [], "needs_reboot": false, "processed_services": [], "result": "failure", "warnings": []} |
519 | + """ |
520 | + |
521 | Examples: ubuntu release |
522 | | release | |
523 | | xenial | |
524 | | bionic | |
525 | | focal | |
526 | - | hirsute | |
527 | | impish | |
528 | | jammy | |
529 | |
530 | @@ -41,6 +46,5 @@ Feature: Command behaviour when trying to attach a machine to an Ubuntu |
531 | | xenial | |
532 | | bionic | |
533 | | focal | |
534 | - | hirsute | |
535 | | impish | |
536 | | jammy | |
537 | diff --git a/features/attach_validtoken.feature b/features/attach_validtoken.feature |
538 | index 8045591..25f763b 100644 |
539 | --- a/features/attach_validtoken.feature |
540 | +++ b/features/attach_validtoken.feature |
541 | @@ -3,7 +3,6 @@ Feature: Command behaviour when attaching a machine to an Ubuntu Advantage |
542 | subscription using a valid token |
543 | |
544 | @series.jammy |
545 | - @series.hirsute |
546 | @series.impish |
547 | @uses.config.machine_type.lxd.container |
548 | Scenario Outline: Attached command in a non-lts ubuntu machine |
549 | @@ -24,7 +23,6 @@ Feature: Command behaviour when attaching a machine to an Ubuntu Advantage |
550 | |
551 | Examples: ubuntu release |
552 | | release | |
553 | - | hirsute | |
554 | | impish | |
555 | | jammy | |
556 | |
557 | @@ -67,8 +65,8 @@ Feature: Command behaviour when attaching a machine to an Ubuntu Advantage |
558 | """ |
559 | esm-apps +yes +enabled +UA Apps: Extended Security Maintenance \(ESM\) |
560 | esm-infra +yes +enabled +UA Infra: Extended Security Maintenance \(ESM\) |
561 | - fips +yes +n/a +NIST-certified core packages |
562 | - fips-updates +yes +n/a +NIST-certified core packages with priority security updates |
563 | + fips +yes +disabled +NIST-certified core packages |
564 | + fips-updates +yes +disabled +NIST-certified core packages with priority security updates |
565 | livepatch +yes +n/a +Canonical Livepatch service |
566 | """ |
567 | And stdout matches regexp: |
568 | @@ -173,6 +171,115 @@ Feature: Command behaviour when attaching a machine to an Ubuntu Advantage |
569 | | bionic | libkrad0=1.16-2build1 | disabled | cis | |
570 | | focal | hello=2.10-2ubuntu2 | n/a | usg | |
571 | |
572 | + @series.lts |
573 | + @uses.config.machine_type.lxd.container |
574 | + Scenario Outline: Attach command with attach config |
575 | + Given a `<release>` machine with ubuntu-advantage-tools installed |
576 | + # simplest happy path |
577 | + When I create the file `/tmp/attach.yaml` with the following |
578 | + """ |
579 | + token: <contract_token> |
580 | + """ |
581 | + When I replace `<contract_token>` in `/tmp/attach.yaml` with token `contract_token` |
582 | + When I run `ua attach --attach-config /tmp/attach.yaml` with sudo |
583 | + Then stdout matches regexp: |
584 | + """ |
585 | + esm-apps +yes +enabled |
586 | + """ |
587 | + And stdout matches regexp: |
588 | + """ |
589 | + esm-infra +yes +enabled |
590 | + """ |
591 | + And stdout matches regexp: |
592 | + """ |
593 | + <cis_or_usg> +yes +disabled |
594 | + """ |
595 | + When I run `ua detach --assume-yes` with sudo |
596 | + # don't allow both token on cli and config |
597 | + Then I verify that running `ua attach TOKEN --attach-config /tmp/attach.yaml` `with sudo` exits `1` |
598 | + Then stderr matches regexp: |
599 | + """ |
600 | + Do not pass the TOKEN arg if you are using --attach-config. |
601 | + Include the token in the attach-config file instead. |
602 | + """ |
603 | + # happy path with service overrides |
604 | + When I create the file `/tmp/attach.yaml` with the following |
605 | + """ |
606 | + token: <contract_token> |
607 | + enable_services: |
608 | + - esm-apps |
609 | + - <cis_or_usg> |
610 | + """ |
611 | + When I replace `<contract_token>` in `/tmp/attach.yaml` with token `contract_token` |
612 | + When I run `ua attach --attach-config /tmp/attach.yaml` with sudo |
613 | + Then stdout matches regexp: |
614 | + """ |
615 | + esm-apps +yes +enabled |
616 | + """ |
617 | + And stdout matches regexp: |
618 | + """ |
619 | + esm-infra +yes +disabled |
620 | + """ |
621 | + And stdout matches regexp: |
622 | + """ |
623 | + <cis_or_usg> +yes +enabled |
624 | + """ |
625 | + When I run `ua detach --assume-yes` with sudo |
626 | + # missing token |
627 | + When I create the file `/tmp/attach.yaml` with the following |
628 | + """ |
629 | + enable_services: |
630 | + - esm-apps |
631 | + - <cis_or_usg> |
632 | + """ |
633 | + Then I verify that running `ua attach --attach-config /tmp/attach.yaml` `with sudo` exits `1` |
634 | + Then stderr matches regexp: |
635 | + """ |
636 | + Error while reading /tmp/attach.yaml: Got value with incorrect type for field |
637 | + "token": Expected value with type StringDataValue but got value: None |
638 | + """ |
639 | + # other schema error |
640 | + When I create the file `/tmp/attach.yaml` with the following |
641 | + """ |
642 | + token: <contract_token> |
643 | + enable_services: {cis: true} |
644 | + """ |
645 | + When I replace `<contract_token>` in `/tmp/attach.yaml` with token `contract_token` |
646 | + Then I verify that running `ua attach --attach-config /tmp/attach.yaml` `with sudo` exits `1` |
647 | + Then stderr matches regexp: |
648 | + """ |
649 | + Error while reading /tmp/attach.yaml: Got value with incorrect type for field |
650 | + "enable_services": Expected value with type list but got value: {\'cis\': True} |
651 | + """ |
652 | + # invalid service name |
653 | + When I create the file `/tmp/attach.yaml` with the following |
654 | + """ |
655 | + token: <contract_token> |
656 | + enable_services: |
657 | + - esm-apps |
658 | + - nonexistent |
659 | + - nonexistent2 |
660 | + """ |
661 | + When I replace `<contract_token>` in `/tmp/attach.yaml` with token `contract_token` |
662 | + Then I verify that running `ua attach --attach-config /tmp/attach.yaml` `with sudo` exits `1` |
663 | + Then stdout matches regexp: |
664 | + """ |
665 | + esm-apps +yes +enabled |
666 | + """ |
667 | + And stdout matches regexp: |
668 | + """ |
669 | + esm-infra +yes +disabled |
670 | + """ |
671 | + Then stderr matches regexp: |
672 | + """ |
673 | + Cannot enable unknown service 'nonexistent, nonexistent2'. |
674 | + """ |
675 | + Examples: ubuntu |
676 | + | release | cis_or_usg | |
677 | + | xenial | cis | |
678 | + | bionic | cis | |
679 | + | focal | usg | |
680 | + |
681 | @series.all |
682 | @uses.config.machine_type.aws.generic |
683 | Scenario Outline: Attach command in an generic AWS Ubuntu VM |
684 | @@ -231,7 +338,7 @@ Feature: Command behaviour when attaching a machine to an Ubuntu Advantage |
685 | | release | fips_status |lp_status | lp_desc | cc_status | cis_or_usg | |
686 | | xenial | disabled |enabled | Canonical Livepatch service | disabled | cis | |
687 | | bionic | disabled |enabled | Canonical Livepatch service | disabled | cis | |
688 | - | focal | n/a |enabled | Canonical Livepatch service | n/a | usg | |
689 | + | focal | disabled |enabled | Canonical Livepatch service | n/a | usg | |
690 | |
691 | @series.all |
692 | @uses.config.machine_type.azure.generic |
693 | @@ -290,8 +397,8 @@ Feature: Command behaviour when attaching a machine to an Ubuntu Advantage |
694 | Examples: ubuntu release livepatch status |
695 | | release | lp_status | fips_status | cc_status | cis_or_usg | |
696 | | xenial | enabled | n/a | disabled | cis | |
697 | - | bionic | n/a | disabled | disabled | cis | |
698 | - | focal | enabled | n/a | n/a | usg | |
699 | + | bionic | enabled | disabled | disabled | cis | |
700 | + | focal | enabled | disabled | n/a | usg | |
701 | |
702 | @series.all |
703 | @uses.config.machine_type.gcp.generic |
704 | @@ -351,4 +458,39 @@ Feature: Command behaviour when attaching a machine to an Ubuntu Advantage |
705 | | release | lp_status | fips_status | cc_status | cis_or_usg | |
706 | | xenial | n/a | n/a | disabled | cis | |
707 | | bionic | n/a | disabled | disabled | cis | |
708 | - | focal | enabled | n/a | n/a | usg | |
709 | + | focal | enabled | disabled | n/a | usg | |
710 | + |
711 | + @series.all |
712 | + @uses.config.machine_type.lxd.container |
713 | + Scenario Outline: Attach command with json output |
714 | + Given a `<release>` machine with ubuntu-advantage-tools installed |
715 | + When I verify that running attach `as non-root` with json response exits `1` |
716 | + Then I will see the following on stdout: |
717 | + """ |
718 | + {"_schema_version": "0.1", "errors": [{"message": "This command must be run as root (try using sudo).", "message_code": "nonroot-user", "service": null, "type": "system"}], "failed_services": [], "needs_reboot": false, "processed_services": [], "result": "failure", "warnings": []} |
719 | + """ |
720 | + When I verify that running attach `with sudo` with json response exits `0` |
721 | + Then I will see the following on stdout: |
722 | + """ |
723 | + {"_schema_version": "0.1", "errors": [], "failed_services": [], "needs_reboot": false, "processed_services": ["esm-apps", "esm-infra"], "result": "success", "warnings": []} |
724 | + """ |
725 | + When I run `ua status` with sudo |
726 | + Then stdout matches regexp: |
727 | + """ |
728 | + SERVICE ENTITLED STATUS DESCRIPTION |
729 | + cc-eal +yes +<cc-eal> +Common Criteria EAL2 Provisioning Packages |
730 | + """ |
731 | + And stdout matches regexp: |
732 | + """ |
733 | + esm-apps +yes +enabled +UA Apps: Extended Security Maintenance \(ESM\) |
734 | + esm-infra +yes +enabled +UA Infra: Extended Security Maintenance \(ESM\) |
735 | + fips +yes +disabled +NIST-certified core packages |
736 | + fips-updates +yes +disabled +NIST-certified core packages with priority security updates |
737 | + livepatch +yes +n/a +Canonical Livepatch service |
738 | + """ |
739 | + |
740 | + Examples: ubuntu release |
741 | + | release | cc-eal | |
742 | + | xenial | disabled | |
743 | + | bionic | disabled | |
744 | + | focal | n/a | |
745 | diff --git a/features/attached_commands.feature b/features/attached_commands.feature |
746 | index ca536dd..dd6cf1a 100644 |
747 | --- a/features/attached_commands.feature |
748 | +++ b/features/attached_commands.feature |
749 | @@ -38,7 +38,9 @@ Feature: Command behaviour when attached to an UA subscription |
750 | And I run `sh -c "ls /var/log/ubuntu-advantage* | sort -d"` as non-root |
751 | Then stdout matches regexp: |
752 | """ |
753 | + /var/log/ubuntu-advantage.log |
754 | /var/log/ubuntu-advantage.log.1 |
755 | + /var/log/ubuntu-advantage-timer.log |
756 | /var/log/ubuntu-advantage-timer.log.1 |
757 | """ |
758 | |
759 | @@ -47,79 +49,89 @@ Feature: Command behaviour when attached to an UA subscription |
760 | | bionic | |
761 | | focal | |
762 | | xenial | |
763 | - | hirsute | |
764 | | impish | |
765 | | jammy | |
766 | |
767 | - @series.all |
768 | - @uses.config.machine_type.lxd.container |
769 | - Scenario Outline: Attached and detach correctly reach contract endpoint |
770 | - Given a `<release>` machine with ubuntu-advantage-tools installed |
771 | - When I attach `contract_token` with sudo |
772 | - And I run `ua detach --assume-yes` with sudo |
773 | - Then I verify that running `grep "Found new machine-id. Do not call detach on contract backend" /var/log/ubuntu-advantage.log` `with sudo` exits `1` |
774 | - |
775 | - Examples: ubuntu release |
776 | - | release | |
777 | - | bionic | |
778 | - | focal | |
779 | - | xenial | |
780 | - | hirsute | |
781 | - | impish | |
782 | - | jammy | |
783 | |
784 | @series.all |
785 | @uses.config.machine_type.lxd.container |
786 | - Scenario Outline: Attached and detach don't reach contract endpoint if machine-id changes |
787 | + Scenario Outline: Attached disable of an already disabled service in a ubuntu machine |
788 | Given a `<release>` machine with ubuntu-advantage-tools installed |
789 | When I attach `contract_token` with sudo |
790 | - And I update contract to use `machineId` as `new-machine-id` |
791 | - And I run `ua detach --assume-yes` with sudo |
792 | - Then stdout matches regexp: |
793 | + Then I verify that running `ua disable livepatch` `as non-root` exits `1` |
794 | + And stderr matches regexp: |
795 | """ |
796 | - This machine is now detached. |
797 | + This command must be run as root \(try using sudo\). |
798 | + """ |
799 | + And I verify that running `ua disable livepatch` `with sudo` exits `1` |
800 | + And I will see the following on stdout: |
801 | + """ |
802 | + Livepatch is not currently enabled |
803 | + See: sudo ua status |
804 | """ |
805 | - And I verify that running `grep "Found new machine-id. Do not call detach on contract backend" /var/log/ubuntu-advantage.log` `with sudo` exits `0` |
806 | - When I run `ua status` with sudo |
807 | - Then stdout matches regexp: |
808 | - """ |
809 | - This machine is not attached to a UA subscription. |
810 | - """ |
811 | |
812 | Examples: ubuntu release |
813 | | release | |
814 | | bionic | |
815 | | focal | |
816 | | xenial | |
817 | - | hirsute | |
818 | | impish | |
819 | | jammy | |
820 | |
821 | - @series.all |
822 | + @series.lts |
823 | @uses.config.machine_type.lxd.container |
824 | - Scenario Outline: Attached disable of an already disabled service in a ubuntu machine |
825 | + Scenario Outline: Attached disable with json format |
826 | Given a `<release>` machine with ubuntu-advantage-tools installed |
827 | When I attach `contract_token` with sudo |
828 | - Then I verify that running `ua disable livepatch` `as non-root` exits `1` |
829 | - And stderr matches regexp: |
830 | + Then I verify that running `ua disable foobar --format json` `as non-root` exits `1` |
831 | + And stdout is a json matching the `ua_operation` schema |
832 | + And I will see the following on stdout: |
833 | """ |
834 | - This command must be run as root \(try using sudo\). |
835 | + {"_schema_version": "0.1", "errors": [{"message": "json formatted response requires --assume-yes flag.", "message_code": "json-format-require-assume-yes", "service": null, "type": "system"}], "failed_services": [], "needs_reboot": false, "processed_services": [], "result": "failure", "warnings": []} |
836 | """ |
837 | - And I verify that running `ua disable livepatch` `with sudo` exits `1` |
838 | + Then I verify that running `ua disable foobar --format json` `with sudo` exits `1` |
839 | + And stdout is a json matching the `ua_operation` schema |
840 | And I will see the following on stdout: |
841 | """ |
842 | - Livepatch is not currently enabled |
843 | - See: sudo ua status |
844 | + {"_schema_version": "0.1", "errors": [{"message": "json formatted response requires --assume-yes flag.", "message_code": "json-format-require-assume-yes", "service": null, "type": "system"}], "failed_services": [], "needs_reboot": false, "processed_services": [], "result": "failure", "warnings": []} |
845 | + """ |
846 | + Then I verify that running `ua disable foobar --format json --assume-yes` `as non-root` exits `1` |
847 | + And stdout is a json matching the `ua_operation` schema |
848 | + And I will see the following on stdout: |
849 | + """ |
850 | + {"_schema_version": "0.1", "errors": [{"message": "This command must be run as root (try using sudo).", "message_code": "nonroot-user", "service": null, "type": "system"}], "failed_services": [], "needs_reboot": false, "processed_services": [], "result": "failure", "warnings": []} |
851 | + """ |
852 | + And I verify that running `ua disable foobar --format json --assume-yes` `with sudo` exits `1` |
853 | + And stdout is a json matching the `ua_operation` schema |
854 | + And I will see the following on stdout: |
855 | + """ |
856 | + {"_schema_version": "0.1", "errors": [{"message": "Cannot disable unknown service 'foobar'.\nTry <valid_services>", "message_code": "invalid-service-or-failure", "service": null, "type": "system"}], "failed_services": [], "needs_reboot": false, "processed_services": [], "result": "failure", "warnings": []} |
857 | """ |
858 | + And I verify that running `ua disable livepatch --format json --assume-yes` `with sudo` exits `1` |
859 | + And stdout is a json matching the `ua_operation` schema |
860 | + And I will see the following on stdout: |
861 | + """ |
862 | + {"_schema_version": "0.1", "errors": [{"message": "Livepatch is not currently enabled\nSee: sudo ua status", "message_code": "service-already-disabled", "service": "livepatch", "type": "service"}], "failed_services": ["livepatch"], "needs_reboot": false, "processed_services": [], "result": "failure", "warnings": []} |
863 | + """ |
864 | + And I verify that running `ua disable esm-infra esm-apps --format json --assume-yes` `with sudo` exits `0` |
865 | + And stdout is a json matching the `ua_operation` schema |
866 | + And I will see the following on stdout: |
867 | + """ |
868 | + {"_schema_version": "0.1", "errors": [], "failed_services": [], "needs_reboot": false, "processed_services": ["esm-apps", "esm-infra"], "result": "success", "warnings": []} |
869 | + """ |
870 | + When I run `ua enable esm-infra` with sudo |
871 | + Then I verify that running `ua disable esm-infra foobar --format json --assume-yes` `with sudo` exits `1` |
872 | + And stdout is a json matching the `ua_operation` schema |
873 | + And I will see the following on stdout: |
874 | + """ |
875 | + {"_schema_version": "0.1", "errors": [{"message": "Cannot disable unknown service 'foobar'.\nTry <valid_services>", "message_code": "invalid-service-or-failure", "service": null, "type": "system"}], "failed_services": [], "needs_reboot": false, "processed_services": ["esm-infra"], "result": "failure", "warnings": []} |
876 | + """ |
877 | |
878 | Examples: ubuntu release |
879 | - | release | |
880 | - | bionic | |
881 | - | focal | |
882 | - | xenial | |
883 | - | hirsute | |
884 | - | impish | |
885 | - | jammy | |
886 | + | release | valid_services | |
887 | + | xenial | cc-eal, cis, esm-apps, esm-infra, fips, fips-updates, livepatch, ros,\nros-updates. | |
888 | + | bionic | cc-eal, cis, esm-apps, esm-infra, fips, fips-updates, livepatch, ros,\nros-updates. | |
889 | + | focal | cc-eal, esm-apps, esm-infra, fips, fips-updates, livepatch, ros,\nros-updates, usg. | |
890 | |
891 | @series.xenial |
892 | @series.bionic |
893 | @@ -241,6 +253,31 @@ Feature: Command behaviour when attached to an UA subscription |
894 | This machine is not attached to a UA subscription. |
895 | """ |
896 | And I verify that running `apt update` `with sudo` exits `0` |
897 | + When I attach `contract_token` with sudo |
898 | + Then I verify that running `ua enable foobar --format json` `as non-root` exits `1` |
899 | + And stdout is a json matching the `ua_operation` schema |
900 | + And I will see the following on stdout: |
901 | + """ |
902 | + {"_schema_version": "0.1", "errors": [{"message": "json formatted response requires --assume-yes flag.", "message_code": "json-format-require-assume-yes", "service": null, "type": "system"}], "failed_services": [], "needs_reboot": false, "processed_services": [], "result": "failure", "warnings": []} |
903 | + """ |
904 | + Then I verify that running `ua enable foobar --format json` `with sudo` exits `1` |
905 | + And stdout is a json matching the `ua_operation` schema |
906 | + And I will see the following on stdout: |
907 | + """ |
908 | + {"_schema_version": "0.1", "errors": [{"message": "json formatted response requires --assume-yes flag.", "message_code": "json-format-require-assume-yes", "service": null, "type": "system"}], "failed_services": [], "needs_reboot": false, "processed_services": [], "result": "failure", "warnings": []} |
909 | + """ |
910 | + Then I verify that running `ua detach --format json --assume-yes` `as non-root` exits `1` |
911 | + And stdout is a json matching the `ua_operation` schema |
912 | + And I will see the following on stdout: |
913 | + """ |
914 | + {"_schema_version": "0.1", "errors": [{"message": "This command must be run as root (try using sudo).", "message_code": "nonroot-user", "service": null, "type": "system"}], "failed_services": [], "needs_reboot": false, "processed_services": [], "result": "failure", "warnings": []} |
915 | + """ |
916 | + When I run `ua detach --format json --assume-yes` with sudo |
917 | + Then stdout is a json matching the `ua_operation` schema |
918 | + And I will see the following on stdout: |
919 | + """ |
920 | + {"_schema_version": "0.1", "errors": [], "failed_services": [], "needs_reboot": false, "processed_services": ["esm-apps", "esm-infra"], "result": "success", "warnings": []} |
921 | + """ |
922 | |
923 | Examples: ubuntu release |
924 | | release | esm-apps | cc-eal | cis | fips | fips-update | ros | cis_or_usg | |
925 | @@ -269,7 +306,6 @@ Feature: Command behaviour when attached to an UA subscription |
926 | | bionic | |
927 | | focal | |
928 | | xenial | |
929 | - | hirsute | |
930 | | impish | |
931 | | jammy | |
932 | |
933 | @@ -292,7 +328,6 @@ Feature: Command behaviour when attached to an UA subscription |
934 | | bionic | |
935 | | focal | |
936 | | xenial | |
937 | - | hirsute | |
938 | | impish | |
939 | | jammy | |
940 | |
941 | @@ -344,7 +379,6 @@ Feature: Command behaviour when attached to an UA subscription |
942 | | bionic | |
943 | | focal | |
944 | | xenial | |
945 | - | hirsute | |
946 | | impish | |
947 | | jammy | |
948 | |
949 | @@ -534,7 +568,6 @@ Feature: Command behaviour when attached to an UA subscription |
950 | | release | infra-status | |
951 | | bionic | enabled | |
952 | | xenial | enabled | |
953 | - | hirsute | n/a | |
954 | | impish | n/a | |
955 | | jammy | n/a | |
956 | |
957 | @@ -751,7 +784,6 @@ Feature: Command behaviour when attached to an UA subscription |
958 | | xenial | |
959 | | bionic | |
960 | | focal | |
961 | - | hirsute | |
962 | | impish | |
963 | | jammy | |
964 | |
965 | @@ -884,14 +916,11 @@ Feature: Command behaviour when attached to an UA subscription |
966 | """ |
967 | And I run `dpkg-reconfigure ubuntu-advantage-tools` with sudo |
968 | And I run `apt-get update` with sudo |
969 | - When I run `ua security-status --format json --beta` as non-root |
970 | - Then stdout is formatted as `json` and has keys: |
971 | - """ |
972 | - _schema_version summary packages |
973 | - """ |
974 | + When I run `ua security-status --format json` as non-root |
975 | + Then stdout is a json matching the `ua_security_status` schema |
976 | And stdout matches regexp: |
977 | """ |
978 | - "_schema_version": "0" |
979 | + "_schema_version": "0.1" |
980 | """ |
981 | And stdout matches regexp: |
982 | """ |
983 | @@ -915,13 +944,17 @@ Feature: Command behaviour when attached to an UA subscription |
984 | """ |
985 | And stdout matches regexp: |
986 | """ |
987 | + "origin": "esm.ubuntu.com" |
988 | + """ |
989 | + And stdout matches regexp: |
990 | + """ |
991 | "status": "pending_attach" |
992 | """ |
993 | When I attach `contract_token` with sudo |
994 | - And I run `ua security-status --format json --beta` as non-root |
995 | + And I run `ua security-status --format json` as non-root |
996 | Then stdout matches regexp: |
997 | """ |
998 | - "_schema_version": "0" |
999 | + "_schema_version": "0.1" |
1000 | """ |
1001 | And stdout matches regexp: |
1002 | """ |
1003 | @@ -939,32 +972,23 @@ Feature: Command behaviour when attached to an UA subscription |
1004 | """ |
1005 | "status": "upgrade_available" |
1006 | """ |
1007 | - When I run `ua security-status --format yaml --beta` as non-root |
1008 | - Then stdout is formatted as `yaml` and has keys: |
1009 | - """ |
1010 | - _schema_version summary packages |
1011 | - """ |
1012 | + When I run `ua security-status --format yaml` as non-root |
1013 | + Then stdout is a yaml matching the `ua_security_status` schema |
1014 | And stdout matches regexp: |
1015 | """ |
1016 | - _schema_version: '0' |
1017 | - """ |
1018 | - When I verify that running `ua security-status --format json` `as non-root` exits `2` |
1019 | - Then I will see the following on stderr: |
1020 | - """ |
1021 | - usage: security-status [-h] --format {json,yaml} --beta |
1022 | - the following arguments are required: --beta |
1023 | + _schema_version: '0.1' |
1024 | """ |
1025 | - When I verify that running `ua security-status --format unsupported --beta` `as non-root` exits `2` |
1026 | + When I verify that running `ua security-status --format unsupported` `as non-root` exits `2` |
1027 | Then I will see the following on stderr: |
1028 | """ |
1029 | - usage: security-status [-h] --format {json,yaml} --beta |
1030 | + usage: security-status [-h] --format {json,yaml} |
1031 | argument --format: invalid choice: 'unsupported' (choose from 'json', 'yaml') |
1032 | """ |
1033 | When I verify that running `ua security-status` `as non-root` exits `2` |
1034 | Then I will see the following on stderr: |
1035 | """ |
1036 | - usage: security-status [-h] --format {json,yaml} --beta |
1037 | - the following arguments are required: --format, --beta |
1038 | + usage: security-status [-h] --format {json,yaml} |
1039 | + the following arguments are required: --format |
1040 | """ |
1041 | Examples: ubuntu release |
1042 | | release | package | service | |
1043 | diff --git a/features/attached_enable.feature b/features/attached_enable.feature |
1044 | index 2fda0de..90a62cb 100644 |
1045 | --- a/features/attached_enable.feature |
1046 | +++ b/features/attached_enable.feature |
1047 | @@ -29,7 +29,6 @@ Feature: Enable command behaviour when attached to an UA subscription |
1048 | | bionic | |
1049 | |
1050 | @series.focal |
1051 | - @series.hirsute |
1052 | @series.impish |
1053 | @uses.config.machine_type.lxd.container |
1054 | Scenario Outline: Attached enable Common Criteria service in an ubuntu lxd container |
1055 | @@ -49,11 +48,80 @@ Feature: Enable command behaviour when attached to an UA subscription |
1056 | Examples: ubuntu release |
1057 | | release | version | full_name | |
1058 | | focal | 20.04 LTS | Focal Fossa | |
1059 | - | hirsute | 21.04 | Hirsute Hippo | |
1060 | | impish | 21.10 | Impish Indri | |
1061 | |
1062 | @series.xenial |
1063 | @series.bionic |
1064 | + @series.focal |
1065 | + @uses.config.machine_type.lxd.container |
1066 | + Scenario Outline: Attached enable of different services using json format |
1067 | + Given a `<release>` machine with ubuntu-advantage-tools installed |
1068 | + When I attach `contract_token` with sudo |
1069 | + Then I verify that running `ua enable foobar --format json` `as non-root` exits `1` |
1070 | + And stdout is a json matching the `ua_operation` schema |
1071 | + And I will see the following on stdout: |
1072 | + """ |
1073 | + {"_schema_version": "0.1", "errors": [{"message": "json formatted response requires --assume-yes flag.", "message_code": "json-format-require-assume-yes", "service": null, "type": "system"}], "failed_services": [], "needs_reboot": false, "processed_services": [], "result": "failure", "warnings": []} |
1074 | + """ |
1075 | + Then I verify that running `ua enable foobar --format json` `with sudo` exits `1` |
1076 | + And stdout is a json matching the `ua_operation` schema |
1077 | + And I will see the following on stdout: |
1078 | + """ |
1079 | + {"_schema_version": "0.1", "errors": [{"message": "json formatted response requires --assume-yes flag.", "message_code": "json-format-require-assume-yes", "service": null, "type": "system"}], "failed_services": [], "needs_reboot": false, "processed_services": [], "result": "failure", "warnings": []} |
1080 | + """ |
1081 | + Then I verify that running `ua enable foobar --format json --assume-yes` `as non-root` exits `1` |
1082 | + And stdout is a json matching the `ua_operation` schema |
1083 | + And I will see the following on stdout: |
1084 | + """ |
1085 | + {"_schema_version": "0.1", "errors": [{"message": "This command must be run as root (try using sudo).", "message_code": "nonroot-user", "service": null, "type": "system"}], "failed_services": [], "needs_reboot": false, "processed_services": [], "result": "failure", "warnings": []} |
1086 | + """ |
1087 | + And I verify that running `ua enable foobar --format json --assume-yes` `with sudo` exits `1` |
1088 | + And stdout is a json matching the `ua_operation` schema |
1089 | + And I will see the following on stdout: |
1090 | + """ |
1091 | + {"_schema_version": "0.1", "errors": [{"message": "Cannot enable unknown service 'foobar'.\nTry <valid_services>", "message_code": "invalid-service-or-failure", "service": null, "type": "system"}], "failed_services": ["foobar"], "needs_reboot": false, "processed_services": [], "result": "failure", "warnings": []} |
1092 | + """ |
1093 | + And I verify that running `ua enable ros foobar --format json --assume-yes` `with sudo` exits `1` |
1094 | + And stdout is a json matching the `ua_operation` schema |
1095 | + And I will see the following on stdout: |
1096 | + """ |
1097 | + {"_schema_version": "0.1", "errors": [{"message": "Cannot enable unknown service 'foobar, ros'.\nTry <valid_services>", "message_code": "invalid-service-or-failure", "service": null, "type": "system"}], "failed_services": ["foobar", "ros"], "needs_reboot": false, "processed_services": [], "result": "failure", "warnings": []} |
1098 | + """ |
1099 | + And I verify that running `ua enable esm-infra --format json --assume-yes` `with sudo` exits `1` |
1100 | + And stdout is a json matching the `ua_operation` schema |
1101 | + Then I will see the following on stdout: |
1102 | + """ |
1103 | + {"_schema_version": "0.1", "errors": [{"message": "UA Infra: ESM is already enabled.\nSee: sudo ua status", "message_code": "service-already-enabled", "service": "esm-infra", "type": "service"}], "failed_services": ["esm-infra"], "needs_reboot": false, "processed_services": [], "result": "failure", "warnings": []} |
1104 | + """ |
1105 | + When I run `ua disable esm-infra` with sudo |
1106 | + And I run `ua enable esm-infra --format json --assume-yes` with sudo |
1107 | + Then stdout is a json matching the `ua_operation` schema |
1108 | + And I will see the following on stdout: |
1109 | + """ |
1110 | + {"_schema_version": "0.1", "errors": [], "failed_services": [], "needs_reboot": false, "processed_services": ["esm-infra"], "result": "success", "warnings": []} |
1111 | + """ |
1112 | + When I run `ua disable esm-infra` with sudo |
1113 | + And I verify that running `ua enable esm-infra foobar --format json --assume-yes` `with sudo` exits `1` |
1114 | + Then stdout is a json matching the `ua_operation` schema |
1115 | + And I will see the following on stdout: |
1116 | + """ |
1117 | + {"_schema_version": "0.1", "errors": [{"message": "Cannot enable unknown service 'foobar'.\nTry <valid_services>", "message_code": "invalid-service-or-failure", "service": null, "type": "system"}], "failed_services": ["foobar"], "needs_reboot": false, "processed_services": ["esm-infra"], "result": "failure", "warnings": []} |
1118 | + """ |
1119 | + When I run `ua disable esm-infra esm-apps` with sudo |
1120 | + And I run `ua enable esm-infra esm-apps --beta --format json --assume-yes` with sudo |
1121 | + Then stdout is a json matching the `ua_operation` schema |
1122 | + And I will see the following on stdout: |
1123 | + """ |
1124 | + {"_schema_version": "0.1", "errors": [], "failed_services": [], "needs_reboot": false, "processed_services": ["esm-apps", "esm-infra"], "result": "success", "warnings": []} |
1125 | + """ |
1126 | + |
1127 | + Examples: ubuntu release |
1128 | + | release | valid_services | |
1129 | + | xenial | cc-eal, cis, esm-infra, fips, fips-updates, livepatch. | |
1130 | + | bionic | cc-eal, cis, esm-infra, fips, fips-updates, livepatch. | |
1131 | + | focal | cc-eal, esm-infra, fips, fips-updates, livepatch, usg. | |
1132 | + |
1133 | + @series.lts |
1134 | @uses.config.machine_type.lxd.container |
1135 | Scenario Outline: Attached enable of a service in a ubuntu machine |
1136 | Given a `<release>` machine with ubuntu-advantage-tools installed |
1137 | @@ -84,7 +152,7 @@ Feature: Enable command behaviour when attached to an UA subscription |
1138 | Try cc-eal, cis, esm-infra, fips, fips-updates, livepatch. |
1139 | """ |
1140 | And I verify that running `ua enable esm-infra` `with sudo` exits `1` |
1141 | - Then I will see the following on stdout: |
1142 | + And I will see the following on stdout: |
1143 | """ |
1144 | One moment, checking your subscription first |
1145 | UA Infra: ESM is already enabled. |
1146 | @@ -176,25 +244,12 @@ Feature: Enable command behaviour when attached to an UA subscription |
1147 | One moment, checking your subscription first |
1148 | Cannot install Livepatch on a container. |
1149 | """ |
1150 | - And I verify that running `ua enable fips --assume-yes` `with sudo` exits `1` |
1151 | - And I will see the following on stdout: |
1152 | - """ |
1153 | - One moment, checking your subscription first |
1154 | - Cannot install FIPS on a container. |
1155 | - """ |
1156 | - And I verify that running `ua enable fips-updates --assume-yes` `with sudo` exits `1` |
1157 | - And I will see the following on stdout: |
1158 | - """ |
1159 | - One moment, checking your subscription first |
1160 | - Cannot install FIPS Updates on a container. |
1161 | - """ |
1162 | |
1163 | Examples: Un-supported services in containers |
1164 | | release | |
1165 | | bionic | |
1166 | | focal | |
1167 | | xenial | |
1168 | - | hirsute | |
1169 | | impish | |
1170 | | jammy | |
1171 | |
1172 | @@ -495,7 +550,7 @@ Feature: Enable command behaviour when attached to an UA subscription |
1173 | """ |
1174 | When I run `ua disable livepatch` with sudo |
1175 | Then I verify that running `canonical-livepatch status` `with sudo` exits `1` |
1176 | - And stdout matches regexp: |
1177 | + And stderr matches regexp: |
1178 | """ |
1179 | Machine is not enabled. Please run 'sudo canonical-livepatch enable' with the |
1180 | token obtained from https://ubuntu.com/livepatch. |
1181 | @@ -581,6 +636,11 @@ Feature: Enable command behaviour when attached to an UA subscription |
1182 | One moment, checking your subscription first |
1183 | Cannot enable Livepatch when FIPS is enabled. |
1184 | """ |
1185 | + Then I verify that running `ua enable livepatch --format json --assume-yes` `with sudo` exits `1` |
1186 | + And I will see the following on stdout |
1187 | + """ |
1188 | + {"_schema_version": "0.1", "errors": [{"message": "Cannot enable Livepatch when FIPS is enabled.", "message_code": "livepatch-error-when-fips-enabled", "service": "livepatch", "type": "service"}], "failed_services": ["livepatch"], "needs_reboot": false, "processed_services": [], "result": "failure", "warnings": []} |
1189 | + """ |
1190 | |
1191 | @series.bionic |
1192 | @uses.config.machine_type.lxd.vm |
1193 | @@ -603,11 +663,14 @@ Feature: Enable command behaviour when attached to an UA subscription |
1194 | And I will see the following on stdout |
1195 | """ |
1196 | One moment, checking your subscription first |
1197 | - """ |
1198 | - And I will see the following on stderr |
1199 | - """ |
1200 | Cannot enable FIPS when Livepatch is enabled. |
1201 | """ |
1202 | + Then I verify that running `ua enable fips --assume-yes --format json` `with sudo` exits `1` |
1203 | + And stdout is a json matching the `ua_operation` schema |
1204 | + And I will see the following on stdout: |
1205 | + """ |
1206 | + {"_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": []} |
1207 | + """ |
1208 | |
1209 | @slow |
1210 | @series.xenial |
1211 | @@ -688,7 +751,8 @@ Feature: Enable command behaviour when attached to an UA subscription |
1212 | | bionic | |
1213 | | xenial | |
1214 | |
1215 | - @series.lts |
1216 | + @series.xenial |
1217 | + @series.bionic |
1218 | @uses.config.contract_token |
1219 | @uses.config.machine_type.lxd.container |
1220 | Scenario Outline: Attached enable ros on a machine |
1221 | @@ -741,7 +805,6 @@ Feature: Enable command behaviour when attached to an UA subscription |
1222 | ROS ESM Security Updates cannot be enabled with UA Apps: ESM disabled. |
1223 | Enable UA Apps: ESM and proceed to enable ROS ESM Security Updates\? \(y\/N\) Cannot enable ROS ESM Security Updates when UA Apps: ESM is disabled. |
1224 | """ |
1225 | - |
1226 | When I run `ua enable ros --beta` `with sudo` and stdin `y` |
1227 | Then stdout matches regexp |
1228 | """ |
1229 | diff --git a/features/attached_status.feature b/features/attached_status.feature |
1230 | index 78483ed..59406e7 100644 |
1231 | --- a/features/attached_status.feature |
1232 | +++ b/features/attached_status.feature |
1233 | @@ -7,25 +7,14 @@ Feature: Attached status |
1234 | Given a `<release>` machine with ubuntu-advantage-tools installed |
1235 | When I attach `contract_token` with sudo |
1236 | And I run `ua status --format json` as non-root |
1237 | - Then stdout is formatted as `json` and has keys: |
1238 | - """ |
1239 | - _doc _schema_version account attached config config_path contract effective |
1240 | - environment_vars execution_details execution_status expires machine_id notices |
1241 | - services version simulated |
1242 | - """ |
1243 | + Then stdout is a json matching the `ua_status` schema |
1244 | When I run `ua status --format yaml` as non-root |
1245 | - Then stdout is formatted as `yaml` and has keys: |
1246 | - """ |
1247 | - _doc _schema_version account attached config config_path contract effective |
1248 | - environment_vars execution_details execution_status expires machine_id notices |
1249 | - services version simulated |
1250 | - """ |
1251 | + Then stdout is a yaml matching the `ua_status` schema |
1252 | |
1253 | Examples: ubuntu release |
1254 | | release | |
1255 | | bionic | |
1256 | | focal | |
1257 | | xenial | |
1258 | - | hirsute | |
1259 | | impish | |
1260 | | jammy | |
1261 | diff --git a/features/aws-ids.yaml b/features/aws-ids.yaml |
1262 | index e0198a7..f2376ad 100644 |
1263 | --- a/features/aws-ids.yaml |
1264 | +++ b/features/aws-ids.yaml |
1265 | @@ -1,3 +1,5 @@ |
1266 | -bionic: ami-094e9c95623db463c |
1267 | -focal: ami-0193aa0a9df84a08b |
1268 | -xenial: ami-06e94647aeaed1e5c |
1269 | +bionic: ami-0419d66039473da9d |
1270 | +bionic-fips: ami-03b75f613f80bcff1 |
1271 | +focal: ami-0489b8bdbbf3a3b32 |
1272 | +xenial: ami-011bcfe2bea365b6a |
1273 | +xenial-fips: ami-077e4c339a098fc9f |
1274 | diff --git a/features/azure-ids.yaml b/features/azure-ids.yaml |
1275 | index 4d43f80..735223f 100644 |
1276 | --- a/features/azure-ids.yaml |
1277 | +++ b/features/azure-ids.yaml |
1278 | @@ -1,3 +1,5 @@ |
1279 | bionic: "Canonical:0001-com-ubuntu-pro-bionic:pro-18_04-lts" |
1280 | focal: "Canonical:0001-com-ubuntu-pro-focal:pro-20_04-lts" |
1281 | xenial: "Canonical:0001-com-ubuntu-pro-xenial:pro-16_04-lts" |
1282 | +bionic-fips: "Canonical:0001-com-ubuntu-pro-bionic-fips:pro-fips-18_04" |
1283 | +xenial-fips: "Canonical:0001-com-ubuntu-pro-xenial-fips:pro-fips-16_04-private" |
1284 | diff --git a/features/cloud.py b/features/cloud.py |
1285 | index 4938374..b0df204 100644 |
1286 | --- a/features/cloud.py |
1287 | +++ b/features/cloud.py |
1288 | @@ -218,7 +218,10 @@ class Cloud: |
1289 | if "pro" in self.machine_type: |
1290 | with open(self.pro_ids_path, "r") as stream: |
1291 | pro_ids = yaml.safe_load(stream.read()) |
1292 | - image_name = pro_ids[series] |
1293 | + if "fips" in self.machine_type: |
1294 | + image_name = pro_ids[series + "-fips"] |
1295 | + else: |
1296 | + image_name = pro_ids[series] |
1297 | else: |
1298 | image_name = self.api.daily_image(release=series) |
1299 | |
1300 | @@ -539,7 +542,7 @@ class Azure(Cloud): |
1301 | List of ports to open for network ingress to the instance |
1302 | |
1303 | :returns: |
1304 | - An AWS cloud provider instance |
1305 | + An Azure cloud provider instance |
1306 | """ |
1307 | if not image_name: |
1308 | image_name = self.locate_image_name(series) |
1309 | @@ -654,7 +657,7 @@ class GCP(Cloud): |
1310 | List of ports to open for network ingress to the instance |
1311 | |
1312 | :returns: |
1313 | - An AWS cloud provider instance |
1314 | + An GCP cloud provider instance |
1315 | """ |
1316 | if not image_name: |
1317 | image_name = self.locate_image_name(series) |
1318 | diff --git a/features/detached_auto_attach.feature b/features/detached_auto_attach.feature |
1319 | new file mode 100644 |
1320 | index 0000000..463400a |
1321 | --- /dev/null |
1322 | +++ b/features/detached_auto_attach.feature |
1323 | @@ -0,0 +1,32 @@ |
1324 | +@uses.config.contract_token |
1325 | +Feature: Attached cloud does not detach when auto-attaching after manually attaching |
1326 | + |
1327 | + @series.all |
1328 | + @uses.config.machine_type.aws.generic |
1329 | + @uses.config.machine_type.azure.generic |
1330 | + @uses.config.machine_type.gcp.generic |
1331 | + Scenario Outline: No detaching on manually attached machine on all clouds |
1332 | + Given a `<release>` machine with ubuntu-advantage-tools installed |
1333 | + When I attach `contract_token` with sudo |
1334 | + And I run `ua refresh` with sudo |
1335 | + Then I will see the following on stdout: |
1336 | + """ |
1337 | + Successfully processed your ua configuration. |
1338 | + Successfully refreshed your subscription. |
1339 | + """ |
1340 | + When I run `ua auto-attach` with sudo |
1341 | + Then stderr matches regexp: |
1342 | + """ |
1343 | + Skipping attach: Instance '[0-9a-z\-]+' is already attached. |
1344 | + """ |
1345 | + When I run `ua status` with sudo |
1346 | + Then stdout matches regexp: |
1347 | + """ |
1348 | + esm-infra +yes +<esm-service> +UA Infra: Extended Security Maintenance \(ESM\) |
1349 | + """ |
1350 | + |
1351 | + Examples: ubuntu release |
1352 | + | release | esm-service | |
1353 | + | bionic | enabled | |
1354 | + | focal | enabled | |
1355 | + | xenial | enabled | |
1356 | diff --git a/features/enable_fips_container.feature b/features/enable_fips_container.feature |
1357 | new file mode 100644 |
1358 | index 0000000..8519480 |
1359 | --- /dev/null |
1360 | +++ b/features/enable_fips_container.feature |
1361 | @@ -0,0 +1,144 @@ |
1362 | + |
1363 | +@uses.config.contract_token |
1364 | +Feature: FIPS enablement in lxd containers |
1365 | + |
1366 | + @series.xenial |
1367 | + @series.bionic |
1368 | + @series.focal |
1369 | + @uses.config.machine_type.lxd.container |
1370 | + Scenario Outline: Attached enable of FIPS in an ubuntu lxd container |
1371 | + Given a `<release>` machine with ubuntu-advantage-tools installed |
1372 | + When I attach `contract_token` with sudo |
1373 | + 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 openssl <libssl> libgcrypt20` with sudo, retrying exit [100] |
1374 | + And I run `ua enable fips<updates>` `with sudo` and stdin `y` |
1375 | + Then stdout matches regexp: |
1376 | + """ |
1377 | + Warning: Enabling <fips-name> in a container. |
1378 | + This will install the FIPS packages but not the kernel. |
1379 | + This container must run on a host with <fips-name> enabled to be |
1380 | + compliant. |
1381 | + Warning: This action can take some time and cannot be undone. |
1382 | + """ |
1383 | + And stdout matches regexp: |
1384 | + """ |
1385 | + Updating package lists |
1386 | + Installing <fips-name> packages |
1387 | + <fips-name> enabled |
1388 | + A reboot is required to complete install. |
1389 | + Please run `apt upgrade` to ensure all FIPS packages are updated to the correct |
1390 | + version. |
1391 | + """ |
1392 | + When I run `ua status --all` with sudo |
1393 | + Then stdout matches regexp: |
1394 | + """ |
1395 | + fips<updates> +yes enabled |
1396 | + """ |
1397 | + And stdout matches regexp: |
1398 | + """ |
1399 | + FIPS support requires system reboot to complete configuration |
1400 | + """ |
1401 | + And I verify that running `apt update` `with sudo` exits `0` |
1402 | + And I verify that `openssh-server` is installed from apt source `https://esm.ubuntu.com/fips<updates>/ubuntu <release><updates>/main` |
1403 | + And I verify that `openssh-client` is installed from apt source `https://esm.ubuntu.com/fips<updates>/ubuntu <release><updates>/main` |
1404 | + And I verify that `strongswan` is installed from apt source `https://esm.ubuntu.com/fips<updates>/ubuntu <release><updates>/main` |
1405 | + And I verify that `strongswan-hmac` is installed from apt source `https://esm.ubuntu.com/fips<updates>/ubuntu <release><updates>/main` |
1406 | + And I verify that `openssl` is installed from apt source `https://esm.ubuntu.com/fips<updates>/ubuntu <release><updates>/main` |
1407 | + And I verify that `<libssl>` is installed from apt source `https://esm.ubuntu.com/fips<updates>/ubuntu <release><updates>/main` |
1408 | + And I verify that `<libssl>-hmac` is installed from apt source `https://esm.ubuntu.com/fips<updates>/ubuntu <release><updates>/main` |
1409 | + And I verify that `<additional-fips-packages>` are installed from apt source `https://esm.ubuntu.com/fips<updates>/ubuntu <release><updates>/main` |
1410 | + When I reboot the `<release>` machine |
1411 | + When I run `ua status --all` with sudo |
1412 | + Then stdout does not match regexp: |
1413 | + """ |
1414 | + FIPS support requires system reboot to complete configuration |
1415 | + """ |
1416 | + When I run `ua disable fips<updates>` `with sudo` and stdin `y` |
1417 | + Then stdout matches regexp: |
1418 | + """ |
1419 | + This will disable the FIPS entitlement but the FIPS packages will remain installed. |
1420 | + """ |
1421 | + And stdout matches regexp: |
1422 | + """ |
1423 | + Updating package lists |
1424 | + """ |
1425 | + And stdout does not match regexp: |
1426 | + """ |
1427 | + A reboot is required to complete disable operation |
1428 | + """ |
1429 | + When I run `ua status --all` with sudo |
1430 | + Then stdout matches regexp: |
1431 | + """ |
1432 | + fips<updates> +yes disabled |
1433 | + """ |
1434 | + Then stdout does not match regexp: |
1435 | + """ |
1436 | + Disabling FIPS requires system reboot to complete operation |
1437 | + """ |
1438 | + When I run `apt-cache policy ubuntu-fips` as non-root |
1439 | + Then stdout does not match regexp: |
1440 | + """ |
1441 | + .*Installed: \(none\) |
1442 | + """ |
1443 | + Then I verify that `openssh-server` installed version matches regexp `fips` |
1444 | + And I verify that `openssh-client` installed version matches regexp `fips` |
1445 | + And I verify that `strongswan` installed version matches regexp `fips` |
1446 | + And I verify that `strongswan-hmac` installed version matches regexp `fips` |
1447 | + And I verify that `openssl` installed version matches regexp `fips` |
1448 | + And I verify that `<libssl>` installed version matches regexp `fips` |
1449 | + And I verify that `<libssl>-hmac` installed version matches regexp `fips` |
1450 | + And I verify that packages `<additional-fips-packages>` installed versions match regexp `fips` |
1451 | + |
1452 | + Examples: ubuntu release |
1453 | + | release | fips-name | updates | libssl | additional-fips-packages | |
1454 | + | xenial | FIPS | | libssl1.0.0 | openssh-server-hmac openssh-client-hmac | |
1455 | + | xenial | FIPS Updates | -updates | libssl1.0.0 | openssh-server-hmac openssh-client-hmac | |
1456 | + | bionic | FIPS | | libssl1.1 | openssh-server-hmac openssh-client-hmac libgcrypt20 libgcrypt20-hmac | |
1457 | + | bionic | FIPS Updates | -updates | libssl1.1 | openssh-server-hmac openssh-client-hmac libgcrypt20 libgcrypt20-hmac | |
1458 | + | focal | FIPS | | libssl1.1 | libgcrypt20 libgcrypt20-hmac | |
1459 | + | focal | FIPS Updates | -updates | libssl1.1 | libgcrypt20 libgcrypt20-hmac | |
1460 | + |
1461 | + @series.xenial |
1462 | + @series.bionic |
1463 | + @series.focal |
1464 | + @uses.config.machine_type.lxd.container |
1465 | + Scenario Outline: Try to enable FIPS after FIPS Updates in a lxd container |
1466 | + Given a `<release>` machine with ubuntu-advantage-tools installed |
1467 | + When I attach `contract_token` with sudo |
1468 | + When I run `ua status --all` with sudo |
1469 | + Then stdout matches regexp: |
1470 | + """ |
1471 | + fips-updates +yes +disabled |
1472 | + """ |
1473 | + And stdout matches regexp: |
1474 | + """ |
1475 | + fips +yes +disabled |
1476 | + """ |
1477 | + When I run `ua enable fips-updates --assume-yes` with sudo |
1478 | + When I run `ua status --all` with sudo |
1479 | + Then stdout matches regexp: |
1480 | + """ |
1481 | + fips-updates +yes +enabled |
1482 | + """ |
1483 | + And stdout matches regexp: |
1484 | + """ |
1485 | + fips +yes +n/a |
1486 | + """ |
1487 | + When I verify that running `ua enable fips --assume-yes` `with sudo` exits `1` |
1488 | + Then stdout matches regexp: |
1489 | + """ |
1490 | + Cannot enable FIPS when FIPS Updates is enabled. |
1491 | + """ |
1492 | + When I run `ua status --all` with sudo |
1493 | + Then stdout matches regexp: |
1494 | + """ |
1495 | + fips-updates +yes +enabled |
1496 | + """ |
1497 | + And stdout matches regexp: |
1498 | + """ |
1499 | + fips +yes +n/a |
1500 | + """ |
1501 | + Examples: ubuntu release |
1502 | + | release | |
1503 | + | xenial | |
1504 | + | bionic | |
1505 | + | focal | |
1506 | diff --git a/features/enable_fips_vm.feature b/features/enable_fips_vm.feature |
1507 | index b401bf2..a055354 100644 |
1508 | --- a/features/enable_fips_vm.feature |
1509 | +++ b/features/enable_fips_vm.feature |
1510 | @@ -8,7 +8,12 @@ Feature: FIPS enablement in lxd VMs |
1511 | Scenario Outline: Attached enable of FIPS in an ubuntu lxd vm |
1512 | Given a `<release>` machine with ubuntu-advantage-tools installed |
1513 | When I attach `contract_token` with sudo |
1514 | - And I run `ua disable livepatch` with sudo |
1515 | + When I run `ua status --format json` with sudo |
1516 | + Then stdout contains substring |
1517 | + """ |
1518 | + {"available": "yes", "blocked_by": [{"name": "livepatch", "reason": "Livepatch cannot be enabled while running the official FIPS certified kernel. If you would like a FIPS compliant kernel with additional bug fixes and security updates, you can use the FIPS Updates service with Livepatch.", "reason_code": "livepatch-invalidates-fips"}], "description": "NIST-certified core packages", "description_override": null, "entitled": "yes", "name": "fips", "status": "disabled", "status_details": "FIPS is not configured"} |
1519 | + """ |
1520 | + When I run `ua disable livepatch` with sudo |
1521 | 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] |
1522 | And I run `apt-mark hold openssh-client openssh-server strongswan` with sudo |
1523 | And I run `ua enable <fips-service>` `with sudo` and stdin `y` |
1524 | @@ -40,6 +45,12 @@ Feature: FIPS enablement in lxd VMs |
1525 | And I verify that `openssh-server-hmac` is installed from apt source `<fips-apt-source>` |
1526 | And I verify that `openssh-client-hmac` is installed from apt source `<fips-apt-source>` |
1527 | And I verify that `strongswan-hmac` is installed from apt source `<fips-apt-source>` |
1528 | + When I run `ua status --format json` with sudo |
1529 | + Then stdout contains substring: |
1530 | + """ |
1531 | + {"available": "yes", "blocked_by": [{"name": "fips", "reason": "Livepatch cannot be enabled while running the official FIPS certified kernel. If you would like a FIPS compliant kernel with additional bug fixes and security updates, you can use the FIPS Updates service with Livepatch.", "reason_code": "livepatch-invalidates-fips"}], "description": "Canonical Livepatch service", "description_override": null, "entitled": "yes", "name": "livepatch", "status": "n/a", "status_details": "Cannot enable Livepatch when FIPS is enabled."} |
1532 | + """ |
1533 | + |
1534 | When I reboot the `<release>` machine |
1535 | And I run `uname -r` as non-root |
1536 | Then stdout matches regexp: |
1537 | @@ -99,6 +110,24 @@ Feature: FIPS enablement in lxd VMs |
1538 | """ |
1539 | Disabling FIPS requires system reboot to complete operation |
1540 | """ |
1541 | + When I run `ua enable <fips-service> --assume-yes --format json --assume-yes` with sudo |
1542 | + Then stdout is a json matching the `ua_operation` schema |
1543 | + And I will see the following on stdout: |
1544 | + """ |
1545 | + {"_schema_version": "0.1", "errors": [], "failed_services": [], "needs_reboot": true, "processed_services": ["<fips-service>"], "result": "success", "warnings": []} |
1546 | + """ |
1547 | + When I reboot the `<release>` machine |
1548 | + And I run `ua disable <fips-service> --assume-yes --format json` with sudo |
1549 | + Then stdout is a json matching the `ua_operation` schema |
1550 | + And I will see the following on stdout: |
1551 | + """ |
1552 | + {"_schema_version": "0.1", "errors": [], "failed_services": [], "needs_reboot": true, "processed_services": ["<fips-service>"], "result": "success", "warnings": []} |
1553 | + """ |
1554 | + When I run `ua status --all` with sudo |
1555 | + Then stdout matches regexp: |
1556 | + """ |
1557 | + <fips-service> +yes disabled |
1558 | + """ |
1559 | |
1560 | Examples: ubuntu release |
1561 | | release | fips-name | fips-service |fips-apt-source | |
1562 | @@ -139,6 +168,12 @@ Feature: FIPS enablement in lxd VMs |
1563 | And I verify that `openssh-server-hmac` is installed from apt source `<fips-apt-source>` |
1564 | And I verify that `openssh-client-hmac` is installed from apt source `<fips-apt-source>` |
1565 | And I verify that `strongswan-hmac` is installed from apt source `<fips-apt-source>` |
1566 | + When I run `ua status --format json` with sudo |
1567 | + Then stdout contains substring: |
1568 | + """ |
1569 | + {"available": "yes", "blocked_by": [{"name": "fips-updates", "reason": "FIPS cannot be enabled if FIPS Updates has ever been enabled because FIPS Updates installs security patches that aren't officially certified.", "reason_code": "fips-updates-invalidates-fips"}], "description": "NIST-certified core packages", "description_override": null, "entitled": "yes", "name": "fips", "status": "n/a", "status_details": "Cannot enable FIPS when FIPS Updates is enabled."} |
1570 | + """ |
1571 | + |
1572 | When I reboot the `<release>` machine |
1573 | And I run `uname -r` as non-root |
1574 | Then stdout matches regexp: |
1575 | @@ -207,6 +242,30 @@ Feature: FIPS enablement in lxd VMs |
1576 | """ |
1577 | livepatch +yes +enabled |
1578 | """ |
1579 | + When I run `ua status --format json` with sudo |
1580 | + Then stdout contains substring: |
1581 | + """ |
1582 | + {"available": "yes", "blocked_by": [{"name": "livepatch", "reason": "Livepatch cannot be enabled while running the official FIPS certified kernel. If you would like a FIPS compliant kernel with additional bug fixes and security updates, you can use the FIPS Updates service with Livepatch.", "reason_code": "livepatch-invalidates-fips"}, {"name": "fips-updates", "reason": "FIPS cannot be enabled if FIPS Updates has ever been enabled because FIPS Updates installs security patches that aren't officially certified.", "reason_code": "fips-updates-invalidates-fips"}], "description": "NIST-certified core packages", "description_override": null, "entitled": "yes", "name": "fips", "status": "n/a", "status_details": "Cannot enable FIPS when FIPS Updates is enabled."} |
1583 | + """ |
1584 | + When I run `ua disable <fips-service> --assume-yes` with sudo |
1585 | + And I run `ua enable <fips-service> --assume-yes --format json --assume-yes` with sudo |
1586 | + Then stdout is a json matching the `ua_operation` schema |
1587 | + And I will see the following on stdout: |
1588 | + """ |
1589 | + {"_schema_version": "0.1", "errors": [], "failed_services": [], "needs_reboot": true, "processed_services": ["<fips-service>"], "result": "success", "warnings": []} |
1590 | + """ |
1591 | + When I reboot the `<release>` machine |
1592 | + And I run `ua disable <fips-service> --assume-yes --format json` with sudo |
1593 | + Then stdout is a json matching the `ua_operation` schema |
1594 | + And I will see the following on stdout: |
1595 | + """ |
1596 | + {"_schema_version": "0.1", "errors": [], "failed_services": [], "needs_reboot": true, "processed_services": ["<fips-service>"], "result": "success", "warnings": []} |
1597 | + """ |
1598 | + When I run `ua status --all` with sudo |
1599 | + Then stdout matches regexp: |
1600 | + """ |
1601 | + <fips-service> +yes disabled |
1602 | + """ |
1603 | |
1604 | Examples: ubuntu release |
1605 | | release | fips-name | fips-service |fips-apt-source | |
1606 | diff --git a/features/install_uninstall.feature b/features/install_uninstall.feature |
1607 | index 66426c8..078b1b5 100644 |
1608 | --- a/features/install_uninstall.feature |
1609 | +++ b/features/install_uninstall.feature |
1610 | @@ -12,7 +12,6 @@ Feature: UA Install and Uninstall related tests |
1611 | | xenial | |
1612 | | bionic | |
1613 | | focal | |
1614 | - | hirsute | |
1615 | | impish | |
1616 | | jammy | |
1617 | |
1618 | diff --git a/features/license_check.feature b/features/license_check.feature |
1619 | index 01d4425..b368360 100644 |
1620 | --- a/features/license_check.feature |
1621 | +++ b/features/license_check.feature |
1622 | @@ -38,8 +38,9 @@ Feature: License check timer only runs in environments where necessary |
1623 | | xenial | |
1624 | | bionic | |
1625 | | focal | |
1626 | + | jammy | |
1627 | |
1628 | - @series.hirsute |
1629 | + @series.impish |
1630 | @uses.config.contract_token |
1631 | @uses.config.machine_type.gcp.generic |
1632 | Scenario Outline: license_check is disabled gcp generic non lts |
1633 | @@ -59,7 +60,7 @@ Feature: License check timer only runs in environments where necessary |
1634 | Then I verify the `ua-license-check` systemd timer is disabled |
1635 | Examples: version |
1636 | | release | |
1637 | - | hirsute | |
1638 | + | impish | |
1639 | |
1640 | @series.all |
1641 | @uses.config.contract_token |
1642 | @@ -91,7 +92,6 @@ Feature: License check timer only runs in environments where necessary |
1643 | | xenial | |
1644 | | bionic | |
1645 | | focal | |
1646 | - | hirsute | |
1647 | | impish | |
1648 | | jammy | |
1649 | |
1650 | diff --git a/features/proxy_config.feature b/features/proxy_config.feature |
1651 | index 7ee5c5a..30f03cf 100644 |
1652 | --- a/features/proxy_config.feature |
1653 | +++ b/features/proxy_config.feature |
1654 | @@ -24,12 +24,23 @@ Feature: Proxy configuration |
1655 | https_proxy: http://<ci-proxy-ip>:3128 |
1656 | """ |
1657 | And I verify `/var/log/squid/access.log` is empty on `proxy` machine |
1658 | - And I attach `contract_token` with sudo |
1659 | + # We need this for the route command |
1660 | + And I run `apt-get install net-tools` with sudo |
1661 | + # We will guarantee that the machine will only use the proxy when |
1662 | + # running the ua commands |
1663 | + And I run `route del default` with sudo |
1664 | + And I attach `contract_token` with sudo and options `--no-auto-enable` |
1665 | And I run `cat /var/log/squid/access.log` `with sudo` on the `proxy` machine |
1666 | Then stdout matches regexp: |
1667 | """ |
1668 | .*CONNECT contracts.canonical.com.* |
1669 | """ |
1670 | + When I run `ua status` with sudo |
1671 | + # Just to verify that the machine is attached |
1672 | + Then stdout matches regexp: |
1673 | + """ |
1674 | + esm-infra +yes +disabled +UA Infra: Extended Security Maintenance \(ESM\) |
1675 | + """ |
1676 | When I run `truncate -s 0 /var/log/squid/access.log` `with sudo` on the `proxy` machine |
1677 | When I create the file `/etc/ubuntu-advantage/uaclient.conf` with the following: |
1678 | """ |
1679 | @@ -139,8 +150,12 @@ Feature: Proxy configuration |
1680 | And I run `systemctl restart squid.service` `with sudo` on the `proxy` machine |
1681 | And I run `ua config set http_proxy=http://<ci-proxy-ip>:3128` with sudo |
1682 | And I run `ua config set https_proxy=http://<ci-proxy-ip>:3128` with sudo |
1683 | - And I verify `/var/log/squid/access.log` is empty on `proxy` machine |
1684 | - And I attach `contract_token` with sudo |
1685 | + And I run `cat /var/log/squid/access.log` `with sudo` on the `proxy` machine |
1686 | + Then stdout matches regexp: |
1687 | + """ |
1688 | + .*CONNECT api.snapcraft.io.* |
1689 | + """ |
1690 | + When I attach `contract_token` with sudo |
1691 | Then stdout matches regexp: |
1692 | """ |
1693 | Setting snap proxy |
1694 | @@ -296,8 +311,12 @@ Feature: Proxy configuration |
1695 | And I run `systemctl restart squid.service` `with sudo` on the `proxy` machine |
1696 | And I run `ua config set http_proxy=http://someuser:somepassword@<ci-proxy-ip>:3128` with sudo |
1697 | And I run `ua config set https_proxy=http://someuser:somepassword@<ci-proxy-ip>:3128` with sudo |
1698 | - And I verify `/var/log/squid/access.log` is empty on `proxy` machine |
1699 | - And I attach `contract_token` with sudo |
1700 | + And I run `cat /var/log/squid/access.log` `with sudo` on the `proxy` machine |
1701 | + Then stdout matches regexp: |
1702 | + """ |
1703 | + .*CONNECT api.snapcraft.io:443.* |
1704 | + """ |
1705 | + When I attach `contract_token` with sudo |
1706 | Then stdout matches regexp: |
1707 | """ |
1708 | Setting snap proxy |
1709 | diff --git a/features/schemas/ua_operation.json b/features/schemas/ua_operation.json |
1710 | new file mode 100644 |
1711 | index 0000000..2afb7c8 |
1712 | --- /dev/null |
1713 | +++ b/features/schemas/ua_operation.json |
1714 | @@ -0,0 +1,76 @@ |
1715 | +{ |
1716 | + "type": "object", |
1717 | + "properties": { |
1718 | + "_schema_version": { |
1719 | + "type": "string", |
1720 | + "const": "0.1" |
1721 | + }, |
1722 | + "result": { |
1723 | + "type": "string", |
1724 | + "enum": ["success", "failure"] |
1725 | + }, |
1726 | + "errors": { |
1727 | + "type": "array", |
1728 | + "items": { |
1729 | + "type": "object", |
1730 | + "required": [ "message", "service", "type" ], |
1731 | + "properties": { |
1732 | + "message": { |
1733 | + "type": "string" |
1734 | + }, |
1735 | + "message_code": { |
1736 | + "type": ["null", "string"] |
1737 | + }, |
1738 | + "service": { |
1739 | + "type": ["null", "string"] |
1740 | + } |
1741 | + }, |
1742 | + "patternProperties": { |
1743 | + "^type$": { |
1744 | + "type": "string", |
1745 | + "enum": ["service", "system"] |
1746 | + } |
1747 | + } |
1748 | + } |
1749 | + }, |
1750 | + "warnings": { |
1751 | + "type": "array", |
1752 | + "items": { |
1753 | + "type": "object", |
1754 | + "required": [ "message", "service", "type" ], |
1755 | + "properties": { |
1756 | + "message": { |
1757 | + "type": "string" |
1758 | + }, |
1759 | + "message_code": { |
1760 | + "type": ["null", "string"] |
1761 | + }, |
1762 | + "service": { |
1763 | + "type": ["null", "string"] |
1764 | + } |
1765 | + }, |
1766 | + "patternProperties": { |
1767 | + "^type$": { |
1768 | + "type": "string", |
1769 | + "enum": ["service", "system"] |
1770 | + } |
1771 | + } |
1772 | + } |
1773 | + }, |
1774 | + "failed_services": { |
1775 | + "type": "array", |
1776 | + "items": { |
1777 | + "type": "string" |
1778 | + } |
1779 | + }, |
1780 | + "processed_services": { |
1781 | + "type": "array", |
1782 | + "items": { |
1783 | + "type": "string" |
1784 | + } |
1785 | + }, |
1786 | + "needs_reboot": { |
1787 | + "type": "boolean" |
1788 | + } |
1789 | + } |
1790 | +} |
1791 | diff --git a/features/schemas/ua_security_status.json b/features/schemas/ua_security_status.json |
1792 | new file mode 100644 |
1793 | index 0000000..e099976 |
1794 | --- /dev/null |
1795 | +++ b/features/schemas/ua_security_status.json |
1796 | @@ -0,0 +1,81 @@ |
1797 | +{ |
1798 | + "type": "object", |
1799 | + "properties": { |
1800 | + "_schema_version": { |
1801 | + "type": "string", |
1802 | + "const": "0.1" |
1803 | + }, |
1804 | + "summary": { |
1805 | + "type": "object", |
1806 | + "properties": { |
1807 | + "ua": { |
1808 | + "type": "object", |
1809 | + "properties": { |
1810 | + "attached": { |
1811 | + "type": "boolean" |
1812 | + }, |
1813 | + "enabled_services": { |
1814 | + "type": "array", |
1815 | + "items": { |
1816 | + "type": "string" |
1817 | + } |
1818 | + }, |
1819 | + "entitled_services": { |
1820 | + "type": "array", |
1821 | + "items": { |
1822 | + "type": "string" |
1823 | + } |
1824 | + } |
1825 | + } |
1826 | + }, |
1827 | + "num_installed_packages": { |
1828 | + "type": "integer" |
1829 | + }, |
1830 | + "num_esm_infra_packages": { |
1831 | + "type": "integer" |
1832 | + }, |
1833 | + "num_esm_apps_packages": { |
1834 | + "type": "integer" |
1835 | + }, |
1836 | + "num_esm_infra_updates": { |
1837 | + "type": "integer" |
1838 | + }, |
1839 | + "num_esm_apps_updates": { |
1840 | + "type": "integer" |
1841 | + }, |
1842 | + "num_standard_security_updates": { |
1843 | + "type": "integer" |
1844 | + } |
1845 | + } |
1846 | + }, |
1847 | + "packages": { |
1848 | + "type": "array", |
1849 | + "items": { |
1850 | + "type": "object", |
1851 | + "properties": { |
1852 | + "package": { |
1853 | + "type": "string" |
1854 | + }, |
1855 | + "version": { |
1856 | + "type": "string" |
1857 | + }, |
1858 | + "service_name": { |
1859 | + "type": "string" |
1860 | + }, |
1861 | + "origin": { |
1862 | + "type": "string" |
1863 | + }, |
1864 | + "status": { |
1865 | + "type": "string", |
1866 | + "enum": [ |
1867 | + "upgrade_available", |
1868 | + "pending_attach", |
1869 | + "pending_enable", |
1870 | + "upgrade_unavailable" |
1871 | + ] |
1872 | + } |
1873 | + } |
1874 | + } |
1875 | + } |
1876 | + } |
1877 | +} |
1878 | diff --git a/features/schemas/ua_status.json b/features/schemas/ua_status.json |
1879 | new file mode 100644 |
1880 | index 0000000..ae9fd69 |
1881 | --- /dev/null |
1882 | +++ b/features/schemas/ua_status.json |
1883 | @@ -0,0 +1,247 @@ |
1884 | +{ |
1885 | + "type": "object", |
1886 | + "properties": { |
1887 | + "_doc": { |
1888 | + "type": "string" |
1889 | + }, |
1890 | + "_schema_version": { |
1891 | + "type": "string", |
1892 | + "const": "0.1" |
1893 | + }, |
1894 | + "version": { |
1895 | + "type": "string" |
1896 | + }, |
1897 | + "result": { |
1898 | + "type": "string", |
1899 | + "enum": ["success", "failure"] |
1900 | + }, |
1901 | + "errors": { |
1902 | + "type": "array", |
1903 | + "items": { |
1904 | + "type": "object", |
1905 | + "required": [ "message", "service", "type" ], |
1906 | + "properties": { |
1907 | + "message": { |
1908 | + "type": "string" |
1909 | + }, |
1910 | + "service": { |
1911 | + "type": ["null", "string"] |
1912 | + } |
1913 | + }, |
1914 | + "patternProperties": { |
1915 | + "^type$": { |
1916 | + "type": "string", |
1917 | + "enum": ["service", "system"] |
1918 | + } |
1919 | + } |
1920 | + } |
1921 | + }, |
1922 | + "warnings": { |
1923 | + "type": "array", |
1924 | + "items": { |
1925 | + "type": "object", |
1926 | + "required": [ "message", "service", "type" ], |
1927 | + "properties": { |
1928 | + "message": { |
1929 | + "type": "string" |
1930 | + }, |
1931 | + "service": { |
1932 | + "type": ["null", "string"] |
1933 | + } |
1934 | + }, |
1935 | + "patternProperties": { |
1936 | + "^type$": { |
1937 | + "type": "string", |
1938 | + "enum": ["service", "system"] |
1939 | + } |
1940 | + } |
1941 | + } |
1942 | + }, |
1943 | + "attached": { |
1944 | + "type": "boolean" |
1945 | + }, |
1946 | + "machine_id": { |
1947 | + "type": ["null", "string"] |
1948 | + }, |
1949 | + "effective": { |
1950 | + "type": ["null", "string"] |
1951 | + }, |
1952 | + "expires": { |
1953 | + "type": ["null", "string"] |
1954 | + }, |
1955 | + "execution_status": { |
1956 | + "type": "string", |
1957 | + "enum": ["active", "inactive", "reboot-required"] |
1958 | + }, |
1959 | + "execution_details": { |
1960 | + "type": "string" |
1961 | + }, |
1962 | + "simulated": { |
1963 | + "type": "boolean" |
1964 | + }, |
1965 | + "services": { |
1966 | + "type": "array", |
1967 | + "items": { |
1968 | + "type": "object", |
1969 | + "properties": { |
1970 | + "name": { |
1971 | + "type": "string" |
1972 | + }, |
1973 | + "description": { |
1974 | + "type": "string" |
1975 | + }, |
1976 | + "available": { |
1977 | + "type": "string", |
1978 | + "enum": ["yes", "no"] |
1979 | + }, |
1980 | + "entitled": { |
1981 | + "type": "string", |
1982 | + "enum": ["yes", "no"] |
1983 | + }, |
1984 | + "status": { |
1985 | + "type": "string", |
1986 | + "enum": ["enabled", "disabled", "n/a"] |
1987 | + }, |
1988 | + "status_details": { |
1989 | + "type": "string" |
1990 | + }, |
1991 | + "description_override": { |
1992 | + "type": ["null", "string"] |
1993 | + }, |
1994 | + "blocked_by": { |
1995 | + "type": "array", |
1996 | + "items": { |
1997 | + "type": "object", |
1998 | + "properties": { |
1999 | + "name": { |
2000 | + "type": "string" |
2001 | + }, |
2002 | + "reason": { |
2003 | + "type": "string" |
2004 | + }, |
2005 | + "reason_code": { |
2006 | + "type": "string" |
2007 | + } |
2008 | + } |
2009 | + } |
2010 | + } |
2011 | + } |
2012 | + } |
2013 | + }, |
2014 | + "notices": { |
2015 | + "type": "array", |
2016 | + "items": { |
2017 | + "type": "string" |
2018 | + } |
2019 | + }, |
2020 | + "config_path": { |
2021 | + "type": "string" |
2022 | + }, |
2023 | + "environment_vars": { |
2024 | + "type": "array", |
2025 | + "items": { |
2026 | + "type": "object", |
2027 | + "properties": { |
2028 | + "name": { |
2029 | + "type": "string" |
2030 | + }, |
2031 | + "value": { |
2032 | + "type": "string" |
2033 | + } |
2034 | + } |
2035 | + } |
2036 | + }, |
2037 | + "contract": { |
2038 | + "type": "object", |
2039 | + "properties": { |
2040 | + "id": { |
2041 | + "type": "string" |
2042 | + }, |
2043 | + "name": { |
2044 | + "type": "string" |
2045 | + }, |
2046 | + "created_at": { |
2047 | + "type": "string" |
2048 | + }, |
2049 | + "products": { |
2050 | + "type": "array", |
2051 | + "items": { |
2052 | + "type": "string" |
2053 | + } |
2054 | + }, |
2055 | + "tech_support_level": { |
2056 | + "type": "string" |
2057 | + } |
2058 | + } |
2059 | + }, |
2060 | + "account": { |
2061 | + "type": "object", |
2062 | + "properties": { |
2063 | + "id": { |
2064 | + "type": "string" |
2065 | + }, |
2066 | + "name": { |
2067 | + "type": "string" |
2068 | + }, |
2069 | + "created_at": { |
2070 | + "type": "string" |
2071 | + }, |
2072 | + "external_account_ids": { |
2073 | + "type": "array" |
2074 | + } |
2075 | + } |
2076 | + }, |
2077 | + "config": { |
2078 | + "type": "object", |
2079 | + "properties": { |
2080 | + "contract_url": { |
2081 | + "type": "string" |
2082 | + }, |
2083 | + "security_url": { |
2084 | + "type": "string" |
2085 | + }, |
2086 | + "data_dir": { |
2087 | + "type": "string" |
2088 | + }, |
2089 | + "log_level": { |
2090 | + "type": "string" |
2091 | + }, |
2092 | + "log_file": { |
2093 | + "type": "string" |
2094 | + }, |
2095 | + "timer_log_file": { |
2096 | + "type": "string" |
2097 | + }, |
2098 | + "license_check_log_file": { |
2099 | + "type": "string" |
2100 | + }, |
2101 | + "ua_config": { |
2102 | + "type": "object", |
2103 | + "properties": { |
2104 | + "apt_http_proxy": { |
2105 | + "type": ["null", "string"] |
2106 | + }, |
2107 | + "apt_https_proxy": { |
2108 | + "type": ["null", "string"] |
2109 | + }, |
2110 | + "http_proxy": { |
2111 | + "type": ["null", "string"] |
2112 | + }, |
2113 | + "https_proxy": { |
2114 | + "type": ["null", "string"] |
2115 | + }, |
2116 | + "update_messaging_timer": { |
2117 | + "type": "integer" |
2118 | + }, |
2119 | + "update_status_timer": { |
2120 | + "type": "integer" |
2121 | + }, |
2122 | + "metering_timer": { |
2123 | + "type": "integer" |
2124 | + } |
2125 | + } |
2126 | + } |
2127 | + } |
2128 | + } |
2129 | + } |
2130 | +} |
2131 | diff --git a/features/steps/steps.py b/features/steps/steps.py |
2132 | index 2c0d5bf..e63f625 100644 |
2133 | --- a/features/steps/steps.py |
2134 | +++ b/features/steps/steps.py |
2135 | @@ -6,6 +6,7 @@ import shlex |
2136 | import subprocess |
2137 | import time |
2138 | |
2139 | +import jsonschema # type: ignore |
2140 | import yaml |
2141 | from behave import given, then, when |
2142 | from hamcrest import ( |
2143 | @@ -20,7 +21,12 @@ from features.environment import ( |
2144 | capture_container_as_image, |
2145 | create_instance_with_uat_installed, |
2146 | ) |
2147 | -from features.util import SLOW_CMDS, emit_spinner_on_travis, nullcontext |
2148 | +from features.util import ( |
2149 | + SLOW_CMDS, |
2150 | + SafeLoaderWithoutDatetime, |
2151 | + emit_spinner_on_travis, |
2152 | + nullcontext, |
2153 | +) |
2154 | from uaclient.defaults import DEFAULT_CONFIG_FILE, DEFAULT_MACHINE_TOKEN_PATH |
2155 | from uaclient.util import DatetimeAwareJSONDecoder |
2156 | |
2157 | @@ -191,7 +197,7 @@ def when_i_run_command_on_machine(context, command, user_spec, instance_name): |
2158 | |
2159 | @when("I verify `{file_name}` is empty on `{instance_name}` machine") |
2160 | def when_i_verify_file_is_empty_on_machine(context, file_name, instance_name): |
2161 | - command = 'sh -c "cat {} | wc -l"' |
2162 | + command = 'sh -c "cat {} | wc -l"'.format(file_name) |
2163 | when_i_run_command( |
2164 | context, command, user_spec="with sudo", instance_name=instance_name |
2165 | ) |
2166 | @@ -230,8 +236,8 @@ def when_i_run_command_with_stdin( |
2167 | |
2168 | |
2169 | @when("I do a preflight check for `{contract_token}` {user_spec}") |
2170 | -def when_i_preflight(context, contract_token, user_spec): |
2171 | - token = getattr(context.config, contract_token) |
2172 | +def when_i_preflight(context, contract_token, user_spec, verify_return=True): |
2173 | + token = getattr(context.config, contract_token, "invalid_token") |
2174 | command = "ua status --simulate-with-token {}".format(token) |
2175 | if user_spec == "with the all flag": |
2176 | command += " --all" |
2177 | @@ -239,10 +245,23 @@ def when_i_preflight(context, contract_token, user_spec): |
2178 | output_format = user_spec.split()[2] |
2179 | command += " --format {}".format(output_format) |
2180 | when_i_run_command( |
2181 | - context=context, command=command, user_spec="as non-root" |
2182 | + context=context, |
2183 | + command=command, |
2184 | + user_spec="as non-root", |
2185 | + verify_return=verify_return, |
2186 | ) |
2187 | |
2188 | |
2189 | +@when( |
2190 | + "I verify that a preflight check for `{contract_token}` {user_spec} exits {exit_codes}" # noqa |
2191 | +) |
2192 | +def when_i_attempt_preflight(context, contract_token, user_spec, exit_codes): |
2193 | + when_i_preflight(context, contract_token, user_spec, verify_return=False) |
2194 | + |
2195 | + expected_codes = exit_codes.split(",") |
2196 | + assert str(context.process.returncode) in expected_codes |
2197 | + |
2198 | + |
2199 | @when("I run `{command}` {user_spec}") |
2200 | def when_i_run_command( |
2201 | context, |
2202 | @@ -280,6 +299,9 @@ def when_i_run_command( |
2203 | logging.error("Error executing command: {}".format(command)) |
2204 | logging.error("stdout: {}".format(result.stdout)) |
2205 | logging.error("stderr: {}".format(result.stderr)) |
2206 | + else: |
2207 | + logging.debug("stdout: {}".format(result.stdout)) |
2208 | + logging.debug("stderr: {}".format(result.stderr)) |
2209 | |
2210 | if verify_return: |
2211 | assert_that(process.returncode, equal_to(0)) |
2212 | @@ -290,11 +312,21 @@ def when_i_run_command( |
2213 | @when("I fix `{issue}` by attaching to a subscription with `{token_type}`") |
2214 | def when_i_fix_a_issue_by_attaching(context, issue, token_type): |
2215 | token = getattr(context.config, token_type) |
2216 | + |
2217 | + if ( |
2218 | + token_type == "contract_token_staging" |
2219 | + or token_type == "contract_token_staging_expired" |
2220 | + ): |
2221 | + change_contract_endpoint_to_staging(context, user_spec="with sudo") |
2222 | + else: |
2223 | + change_contract_endpoint_to_production(context, user_spec="with sudo") |
2224 | + |
2225 | when_i_run_command( |
2226 | context=context, |
2227 | command="ua fix {}".format(issue), |
2228 | user_spec="with sudo", |
2229 | stdin="a\n{}\n".format(token), |
2230 | + verify_return=False, |
2231 | ) |
2232 | |
2233 | |
2234 | @@ -340,23 +372,46 @@ def when_i_update_contract_field_to_new_value( |
2235 | ) |
2236 | |
2237 | |
2238 | +def change_contract_endpoint_to_staging(context, user_spec): |
2239 | + when_i_run_command( |
2240 | + context, |
2241 | + "sed -i 's/contracts.can/contracts.staging.can/' {}".format( |
2242 | + DEFAULT_CONFIG_FILE |
2243 | + ), |
2244 | + user_spec, |
2245 | + ) |
2246 | + |
2247 | + |
2248 | +def change_contract_endpoint_to_production(context, user_spec): |
2249 | + when_i_run_command( |
2250 | + context, |
2251 | + "sed -i 's/contracts.staging.can/contracts.can/' {}".format( |
2252 | + DEFAULT_CONFIG_FILE |
2253 | + ), |
2254 | + user_spec, |
2255 | + ) |
2256 | + |
2257 | + |
2258 | +@when("I attach `{token_type}` {user_spec} and options `{options}`") |
2259 | +def when_i_attach_staging_token_with_options( |
2260 | + context, token_type, user_spec, options |
2261 | +): |
2262 | + when_i_attach_staging_token( |
2263 | + context, token_type, user_spec, options=options |
2264 | + ) |
2265 | + |
2266 | + |
2267 | @when("I attach `{token_type}` {user_spec}") |
2268 | def when_i_attach_staging_token( |
2269 | - context, token_type, user_spec, verify_return=True |
2270 | + context, token_type, user_spec, verify_return=True, options="" |
2271 | ): |
2272 | token = getattr(context.config, token_type) |
2273 | if ( |
2274 | token_type == "contract_token_staging" |
2275 | or token_type == "contract_token_staging_expired" |
2276 | ): |
2277 | - when_i_run_command( |
2278 | - context, |
2279 | - "sed -i 's/contracts.can/contracts.staging.can/' {}".format( |
2280 | - DEFAULT_CONFIG_FILE |
2281 | - ), |
2282 | - user_spec, |
2283 | - ) |
2284 | - cmd = "ua attach {}".format(token) |
2285 | + change_contract_endpoint_to_staging(context, user_spec) |
2286 | + cmd = "ua attach {} {}".format(token, options).strip() |
2287 | when_i_run_command(context, cmd, user_spec, verify_return=False) |
2288 | |
2289 | if verify_return: |
2290 | @@ -420,6 +475,25 @@ def when_i_wait(context, seconds): |
2291 | time.sleep(int(seconds)) |
2292 | |
2293 | |
2294 | +@when("I replace `{original}` in `{filename}` with `{new}`") |
2295 | +def when_i_replace_string_in_file(context, original, filename, new): |
2296 | + when_i_run_command( |
2297 | + context, |
2298 | + "sed -i 's/{original}/{new}/' {filename}".format( |
2299 | + original=original, new=new, filename=filename |
2300 | + ), |
2301 | + "with sudo", |
2302 | + ) |
2303 | + |
2304 | + |
2305 | +@when("I replace `{original}` in `{filename}` with token `{token_name}`") |
2306 | +def when_i_replace_string_in_file_with_token( |
2307 | + context, original, filename, token_name |
2308 | +): |
2309 | + token = getattr(context.config, token_name) |
2310 | + when_i_replace_string_in_file(context, original, filename, token) |
2311 | + |
2312 | + |
2313 | @then("I will see the following on stdout") |
2314 | def then_i_will_see_on_stdout(context): |
2315 | assert_that(context.process.stdout.strip(), equal_to(context.text)) |
2316 | @@ -439,27 +513,6 @@ def then_conditional_stdout_does_not_match_regexp(context, value1, value2): |
2317 | then_stream_does_not_match_regexp(context, "stdout") |
2318 | |
2319 | |
2320 | -@then("stdout is formatted as `{output_format}` and has keys") |
2321 | -def then_stdout_is_formatted_and_has_keys(context, output_format): |
2322 | - output = context.process.stdout.strip() |
2323 | - if output_format == "json": |
2324 | - data = json.loads(output) |
2325 | - elif output_format == "yaml": |
2326 | - data = yaml.safe_load(output) |
2327 | - |
2328 | - keys = set(context.text.split()) |
2329 | - output_keys = set(data.keys()) |
2330 | - |
2331 | - if keys != output_keys: |
2332 | - message = """ |
2333 | - Missing keys in output: {} |
2334 | - Extra keys in output: {} |
2335 | - """.format( |
2336 | - keys - output_keys or "", output_keys - keys or "" |
2337 | - ) |
2338 | - raise AssertionError(message) |
2339 | - |
2340 | - |
2341 | @then("{stream} does not match regexp") |
2342 | def then_stream_does_not_match_regexp(context, stream): |
2343 | content = getattr(context.process, stream).strip() |
2344 | @@ -472,6 +525,12 @@ def then_stream_matches_regexp(context, stream): |
2345 | assert_that(content, matches_regexp(context.text)) |
2346 | |
2347 | |
2348 | +@then("{stream} contains substring") |
2349 | +def then_stream_contains_substring(context, stream): |
2350 | + content = getattr(context.process, stream).strip() |
2351 | + assert_that(content, contains_string(context.text)) |
2352 | + |
2353 | + |
2354 | @then("I will see the following on stderr") |
2355 | def then_i_will_see_on_stderr(context): |
2356 | assert_that(context.process.stderr.strip(), equal_to(context.text)) |
2357 | @@ -521,6 +580,16 @@ def then_i_verify_that_running_cmd_with_spec_exits_with_codes( |
2358 | |
2359 | |
2360 | @when( |
2361 | + "I verify that running attach `{spec}` with json response exits `{exit_codes}`" # noqa |
2362 | +) |
2363 | +def when_i_verify_attach_with_json_response(context, spec, exit_codes): |
2364 | + cmd = "ua attach {} --format json".format(context.config.contract_token) |
2365 | + then_i_verify_that_running_cmd_with_spec_exits_with_codes( |
2366 | + context=context, cmd_name=cmd, spec=spec, exit_codes=exit_codes |
2367 | + ) |
2368 | + |
2369 | + |
2370 | +@when( |
2371 | "I verify that running `{cmd_name}` `{spec}` and stdin `{stdin}` exits `{exit_codes}`" # noqa |
2372 | ) |
2373 | def then_i_verify_that_running_cmd_with_spec_and_stdin_exits_with_codes( |
2374 | @@ -581,6 +650,16 @@ def verify_installed_package_matches_version_regexp(context, package, regex): |
2375 | assert_that(context.process.stdout.strip(), matches_regexp(regex)) |
2376 | |
2377 | |
2378 | +@then( |
2379 | + "I verify that packages `{packages}` installed versions match regexp `{regex}`" # noqa: E501 |
2380 | +) |
2381 | +def verify_installed_packages_match_version_regexp(context, packages, regex): |
2382 | + for package in packages.split(" "): |
2383 | + verify_installed_package_matches_version_regexp( |
2384 | + context, package, regex |
2385 | + ) |
2386 | + |
2387 | + |
2388 | @then("I verify that `{package}` is installed from apt source `{apt_source}`") |
2389 | def verify_package_is_installed_from_apt_source(context, package, apt_source): |
2390 | when_i_run_command( |
2391 | @@ -609,6 +688,18 @@ def verify_package_is_installed_from_apt_source(context, package, apt_source): |
2392 | ) |
2393 | |
2394 | |
2395 | +@then( |
2396 | + "I verify that `{packages}` are installed from apt source `{apt_source}`" |
2397 | +) |
2398 | +def verify_packages_are_installed_from_apt_source( |
2399 | + context, packages, apt_source |
2400 | +): |
2401 | + for package in packages.split(" "): |
2402 | + verify_package_is_installed_from_apt_source( |
2403 | + context, package, apt_source |
2404 | + ) |
2405 | + |
2406 | + |
2407 | @then("I verify that the timer interval for `{job}` is `{interval}`") |
2408 | def verify_timer_interval_for_job(context, job, interval): |
2409 | when_i_run_command( |
2410 | @@ -779,6 +870,18 @@ def i_restore_the_saved_key_value_on_contract(context, key): |
2411 | ) |
2412 | |
2413 | |
2414 | +@then("stdout is a {output_format} matching the `{schema}` schema") |
2415 | +def stdout_matches_the_json_schema(context, output_format, schema): |
2416 | + if output_format == "json": |
2417 | + instance = json.loads(context.process.stdout.strip()) |
2418 | + elif output_format == "yaml": |
2419 | + instance = yaml.load( |
2420 | + context.process.stdout.strip(), SafeLoaderWithoutDatetime |
2421 | + ) |
2422 | + with open("features/schemas/{}.json".format(schema), "r") as schema_file: |
2423 | + jsonschema.validate(instance=instance, schema=json.load(schema_file)) |
2424 | + |
2425 | + |
2426 | def get_command_prefix_for_user_spec(user_spec): |
2427 | prefix = [] |
2428 | if user_spec == "with sudo": |
2429 | diff --git a/features/ubuntu_pro.feature b/features/ubuntu_pro.feature |
2430 | index 95d54e1..04ef4fc 100644 |
2431 | --- a/features/ubuntu_pro.feature |
2432 | +++ b/features/ubuntu_pro.feature |
2433 | @@ -40,6 +40,22 @@ Feature: Command behaviour when auto-attached in an ubuntu PRO image |
2434 | """ |
2435 | <cis_or_usg> +yes +<cis-s> +Security compliance and audit tools |
2436 | """ |
2437 | + When I run `ua enable <cis_or_usg>` with sudo |
2438 | + And I run `ua status` with sudo |
2439 | + Then stdout matches regexp: |
2440 | + """ |
2441 | + <cis_or_usg> +yes +enabled +Security compliance and audit tools |
2442 | + """ |
2443 | + When I run `ua disable <cis_or_usg>` with sudo |
2444 | + Then stdout matches regexp: |
2445 | + """ |
2446 | + Updating package lists |
2447 | + """ |
2448 | + When I run `ua status` with sudo |
2449 | + Then stdout matches regexp: |
2450 | + """ |
2451 | + <cis_or_usg> +yes +disabled +Security compliance and audit tools |
2452 | + """ |
2453 | When I run `cat /var/log/squid/access.log` `with sudo` on the `proxy` machine |
2454 | Then stdout matches regexp: |
2455 | """ |
2456 | @@ -53,7 +69,7 @@ Feature: Command behaviour when auto-attached in an ubuntu PRO image |
2457 | | release | fips-s | cc-eal-s | cis-s | cis_or_usg | |
2458 | | xenial | disabled | disabled | disabled | cis | |
2459 | | bionic | disabled | disabled | disabled | cis | |
2460 | - | focal | n/a | n/a | disabled | usg | |
2461 | + | focal | disabled | n/a | disabled | usg | |
2462 | |
2463 | @series.lts |
2464 | @uses.config.machine_type.azure.pro |
2465 | @@ -95,6 +111,22 @@ Feature: Command behaviour when auto-attached in an ubuntu PRO image |
2466 | """ |
2467 | <cis_or_usg> +yes +<cis-s> +Security compliance and audit tools |
2468 | """ |
2469 | + When I run `ua enable <cis_or_usg>` with sudo |
2470 | + And I run `ua status` with sudo |
2471 | + Then stdout matches regexp: |
2472 | + """ |
2473 | + <cis_or_usg> +yes +enabled +Security compliance and audit tools |
2474 | + """ |
2475 | + When I run `ua disable <cis_or_usg>` with sudo |
2476 | + Then stdout matches regexp: |
2477 | + """ |
2478 | + Updating package lists |
2479 | + """ |
2480 | + When I run `ua status` with sudo |
2481 | + Then stdout matches regexp: |
2482 | + """ |
2483 | + <cis_or_usg> +yes +disabled +Security compliance and audit tools |
2484 | + """ |
2485 | When I run `cat /var/log/squid/access.log` `with sudo` on the `proxy` machine |
2486 | Then stdout matches regexp: |
2487 | """ |
2488 | @@ -107,8 +139,8 @@ Feature: Command behaviour when auto-attached in an ubuntu PRO image |
2489 | Examples: ubuntu release |
2490 | | release | fips-s | cc-eal-s | cis-s | livepatch-s | cis_or_usg | |
2491 | | xenial | n/a | disabled | disabled | enabled | cis | |
2492 | - | bionic | disabled | disabled | disabled | n/a | cis | |
2493 | - | focal | n/a | n/a | disabled | enabled | usg | |
2494 | + | bionic | disabled | disabled | disabled | enabled | cis | |
2495 | + | focal | disabled | n/a | disabled | enabled | usg | |
2496 | |
2497 | @series.lts |
2498 | @uses.config.machine_type.gcp.pro |
2499 | @@ -150,6 +182,22 @@ Feature: Command behaviour when auto-attached in an ubuntu PRO image |
2500 | """ |
2501 | <cis_or_usg> +yes +<cis-s> +Security compliance and audit tools |
2502 | """ |
2503 | + When I run `ua enable <cis_or_usg>` with sudo |
2504 | + And I run `ua status` with sudo |
2505 | + Then stdout matches regexp: |
2506 | + """ |
2507 | + <cis_or_usg> +yes +enabled +Security compliance and audit tools |
2508 | + """ |
2509 | + When I run `ua disable <cis_or_usg>` with sudo |
2510 | + Then stdout matches regexp: |
2511 | + """ |
2512 | + Updating package lists |
2513 | + """ |
2514 | + When I run `ua status` with sudo |
2515 | + Then stdout matches regexp: |
2516 | + """ |
2517 | + <cis_or_usg> +yes +disabled +Security compliance and audit tools |
2518 | + """ |
2519 | When I run `cat /var/log/squid/access.log` `with sudo` on the `proxy` machine |
2520 | Then stdout matches regexp: |
2521 | """ |
2522 | @@ -163,7 +211,7 @@ Feature: Command behaviour when auto-attached in an ubuntu PRO image |
2523 | | release | fips-s | cc-eal-s | cis-s | livepatch-s | cis_or_usg | |
2524 | | xenial | n/a | disabled | disabled | n/a | cis | |
2525 | | bionic | disabled | disabled | disabled | n/a | cis | |
2526 | - | focal | n/a | n/a | disabled | enabled | usg | |
2527 | + | focal | disabled | n/a | disabled | enabled | usg | |
2528 | |
2529 | @series.lts |
2530 | @uses.config.machine_type.aws.pro |
2531 | @@ -178,7 +226,6 @@ Feature: Command behaviour when auto-attached in an ubuntu PRO image |
2532 | """ |
2533 | And I run `ua auto-attach` with sudo |
2534 | And I run `ua status --wait` as non-root |
2535 | - And I run `ua status` as non-root |
2536 | Then stdout matches regexp: |
2537 | """ |
2538 | SERVICE ENTITLED STATUS DESCRIPTION |
2539 | @@ -214,6 +261,22 @@ Feature: Command behaviour when auto-attached in an ubuntu PRO image |
2540 | """ |
2541 | <cis_or_usg> +yes +<cis-s> +Security compliance and audit tools |
2542 | """ |
2543 | + When I run `ua enable <cis_or_usg>` with sudo |
2544 | + And I run `ua status` with sudo |
2545 | + Then stdout matches regexp: |
2546 | + """ |
2547 | + <cis_or_usg> +yes +enabled +Security compliance and audit tools |
2548 | + """ |
2549 | + When I run `ua disable <cis_or_usg>` with sudo |
2550 | + Then stdout matches regexp: |
2551 | + """ |
2552 | + Updating package lists |
2553 | + """ |
2554 | + When I run `ua status` with sudo |
2555 | + Then stdout matches regexp: |
2556 | + """ |
2557 | + <cis_or_usg> +yes +disabled +Security compliance and audit tools |
2558 | + """ |
2559 | When I run `systemctl start ua-auto-attach.service` with sudo |
2560 | And I verify that running `systemctl status ua-auto-attach.service` `as non-root` exits `0,3` |
2561 | Then stdout matches regexp: |
2562 | @@ -281,7 +344,7 @@ Feature: Command behaviour when auto-attached in an ubuntu PRO image |
2563 | | release | fips-s | cc-eal-s | cis-s | infra-pkg | apps-pkg | cis_or_usg | |
2564 | | xenial | disabled | disabled | disabled | libkrad0 | jq | cis | |
2565 | | bionic | disabled | disabled | disabled | libkrad0 | bundler | cis | |
2566 | - | focal | n/a | n/a | disabled | hello | ant | usg | |
2567 | + | focal | disabled | n/a | disabled | hello | ant | usg | |
2568 | |
2569 | @series.lts |
2570 | @uses.config.machine_type.azure.pro |
2571 | @@ -332,6 +395,22 @@ Feature: Command behaviour when auto-attached in an ubuntu PRO image |
2572 | """ |
2573 | <cis_or_usg> +yes +<cis-s> +Security compliance and audit tools |
2574 | """ |
2575 | + When I run `ua enable <cis_or_usg>` with sudo |
2576 | + And I run `ua status` with sudo |
2577 | + Then stdout matches regexp: |
2578 | + """ |
2579 | + <cis_or_usg> +yes +enabled +Security compliance and audit tools |
2580 | + """ |
2581 | + When I run `ua disable <cis_or_usg>` with sudo |
2582 | + Then stdout matches regexp: |
2583 | + """ |
2584 | + Updating package lists |
2585 | + """ |
2586 | + When I run `ua status` with sudo |
2587 | + Then stdout matches regexp: |
2588 | + """ |
2589 | + <cis_or_usg> +yes +disabled +Security compliance and audit tools |
2590 | + """ |
2591 | When I run `systemctl start ua-auto-attach.service` with sudo |
2592 | And I verify that running `systemctl status ua-auto-attach.service` `as non-root` exits `0,3` |
2593 | Then stdout matches regexp: |
2594 | @@ -398,8 +477,8 @@ Feature: Command behaviour when auto-attached in an ubuntu PRO image |
2595 | Examples: ubuntu release |
2596 | | release | fips-s | cc-eal-s | cis-s | infra-pkg | apps-pkg | livepatch | cis_or_usg | |
2597 | | xenial | n/a | disabled | disabled | libkrad0 | jq | enabled | cis | |
2598 | - | bionic | disabled | disabled | disabled | libkrad0 | bundler | n/a | cis | |
2599 | - | focal | n/a | n/a | disabled | hello | ant | enabled | usg | |
2600 | + | bionic | disabled | disabled | disabled | libkrad0 | bundler | enabled | cis | |
2601 | + | focal | disabled | n/a | disabled | hello | ant | enabled | usg | |
2602 | |
2603 | @series.lts |
2604 | @uses.config.machine_type.gcp.pro |
2605 | @@ -450,6 +529,22 @@ Feature: Command behaviour when auto-attached in an ubuntu PRO image |
2606 | """ |
2607 | <cis_or_usg> +yes +<cis-s> +Security compliance and audit tools |
2608 | """ |
2609 | + When I run `ua enable <cis_or_usg>` with sudo |
2610 | + And I run `ua status` with sudo |
2611 | + Then stdout matches regexp: |
2612 | + """ |
2613 | + <cis_or_usg> +yes +enabled +Security compliance and audit tools |
2614 | + """ |
2615 | + When I run `ua disable <cis_or_usg>` with sudo |
2616 | + Then stdout matches regexp: |
2617 | + """ |
2618 | + Updating package lists |
2619 | + """ |
2620 | + When I run `ua status` with sudo |
2621 | + Then stdout matches regexp: |
2622 | + """ |
2623 | + <cis_or_usg> +yes +disabled +Security compliance and audit tools |
2624 | + """ |
2625 | When I run `systemctl start ua-auto-attach.service` with sudo |
2626 | And I verify that running `systemctl status ua-auto-attach.service` `as non-root` exits `0,3` |
2627 | Then stdout matches regexp: |
2628 | @@ -517,4 +612,4 @@ Feature: Command behaviour when auto-attached in an ubuntu PRO image |
2629 | | release | fips-s | cc-eal-s | cis-s | infra-pkg | apps-pkg | livepatch | cis_or_usg | |
2630 | | xenial | n/a | disabled | disabled | libkrad0 | jq | n/a | cis | |
2631 | | bionic | disabled | disabled | disabled | libkrad0 | bundler | n/a | cis | |
2632 | - | focal | n/a | n/a | disabled | hello | ant | enabled | usg | |
2633 | + | focal | disabled | n/a | disabled | hello | ant | enabled | usg | |
2634 | diff --git a/features/ubuntu_pro_fips.feature b/features/ubuntu_pro_fips.feature |
2635 | new file mode 100644 |
2636 | index 0000000..7a18b03 |
2637 | --- /dev/null |
2638 | +++ b/features/ubuntu_pro_fips.feature |
2639 | @@ -0,0 +1,210 @@ |
2640 | +Feature: Command behaviour when auto-attached in an ubuntu PRO fips image |
2641 | + |
2642 | + @series.lts |
2643 | + @uses.config.machine_type.azure.pro.fips |
2644 | + Scenario Outline: Check fips is enabled correctly on Ubuntu pro fips Azure machine |
2645 | + Given a `<release>` machine with ubuntu-advantage-tools installed |
2646 | + When I create the file `/etc/ubuntu-advantage/uaclient.conf` with the following: |
2647 | + """ |
2648 | + contract_url: 'https://contracts.canonical.com' |
2649 | + data_dir: /var/lib/ubuntu-advantage |
2650 | + log_level: debug |
2651 | + log_file: /var/log/ubuntu-advantage.log |
2652 | + features: |
2653 | + allow_xenial_fips_on_cloud: true |
2654 | + """ |
2655 | + And I run `ua auto-attach` with sudo |
2656 | + And I run `ua status --wait` as non-root |
2657 | + And I run `ua status` as non-root |
2658 | + Then stdout matches regexp: |
2659 | + """ |
2660 | + esm-apps +yes +enabled +UA Apps: Extended Security Maintenance \(ESM\) |
2661 | + esm-infra +yes +enabled +UA Infra: Extended Security Maintenance \(ESM\) |
2662 | + fips +yes +enabled +NIST-certified core packages |
2663 | + fips-updates +yes +disabled +NIST-certified core packages with priority security updates |
2664 | + livepatch +yes +n/a +Canonical Livepatch service |
2665 | + """ |
2666 | + And I verify that running `apt update` `with sudo` exits `0` |
2667 | + And I verify that running `grep Traceback /var/log/ubuntu-advantage.log` `with sudo` exits `1` |
2668 | + And I verify that `openssh-server` is installed from apt source `<fips-apt-source>` |
2669 | + And I verify that `openssh-client` is installed from apt source `<fips-apt-source>` |
2670 | + And I verify that `strongswan` is installed from apt source `<fips-apt-source>` |
2671 | + And I verify that `openssh-server-hmac` is installed from apt source `<fips-apt-source>` |
2672 | + And I verify that `openssh-client-hmac` is installed from apt source `<fips-apt-source>` |
2673 | + And I verify that `strongswan-hmac` is installed from apt source `<fips-apt-source>` |
2674 | + When I run `uname -r` as non-root |
2675 | + Then stdout matches regexp: |
2676 | + """ |
2677 | + <fips-kernel-version> |
2678 | + """ |
2679 | + When I run `apt-cache policy ubuntu-azure-fips` as non-root |
2680 | + Then stdout does not match regexp: |
2681 | + """ |
2682 | + .*Installed: \(none\) |
2683 | + """ |
2684 | + When I run `cat /proc/sys/crypto/fips_enabled` with sudo |
2685 | + Then I will see the following on stdout: |
2686 | + """ |
2687 | + 1 |
2688 | + """ |
2689 | + When I run `systemctl start ua-auto-attach.service` with sudo |
2690 | + And I verify that running `systemctl status ua-auto-attach.service` `as non-root` exits `0,3` |
2691 | + Then stdout matches regexp: |
2692 | + """ |
2693 | + .*status=0\/SUCCESS.* |
2694 | + """ |
2695 | + And stdout matches regexp: |
2696 | + """ |
2697 | + Skipping attach: Instance '[0-9a-z\-]+' is already attached. |
2698 | + """ |
2699 | + When I run `ua auto-attach` with sudo |
2700 | + Then stderr matches regexp: |
2701 | + """ |
2702 | + Skipping attach: Instance '[0-9a-z\-]+' is already attached. |
2703 | + """ |
2704 | + When I run `apt-cache policy` with sudo |
2705 | + Then apt-cache policy for the following url has permission `500` |
2706 | + """ |
2707 | + https://esm.ubuntu.com/infra/ubuntu <release>-infra-updates/main amd64 Packages |
2708 | + """ |
2709 | + And apt-cache policy for the following url has permission `500` |
2710 | + """ |
2711 | + https://esm.ubuntu.com/infra/ubuntu <release>-infra-security/main amd64 Packages |
2712 | + """ |
2713 | + And apt-cache policy for the following url has permission `500` |
2714 | + """ |
2715 | + https://esm.ubuntu.com/apps/ubuntu <release>-apps-updates/main amd64 Packages |
2716 | + """ |
2717 | + And apt-cache policy for the following url has permission `500` |
2718 | + """ |
2719 | + https://esm.ubuntu.com/apps/ubuntu <release>-apps-security/main amd64 Packages |
2720 | + """ |
2721 | + And I verify that running `apt update` `with sudo` exits `0` |
2722 | + When I run `apt install -y <infra-pkg>/<release>-infra-security` with sudo, retrying exit [100] |
2723 | + And I run `apt-cache policy <infra-pkg>` as non-root |
2724 | + Then stdout matches regexp: |
2725 | + """ |
2726 | + \s*500 https://esm.ubuntu.com/infra/ubuntu <release>-infra-security/main amd64 Packages |
2727 | + \s*500 https://esm.ubuntu.com/infra/ubuntu <release>-infra-updates/main amd64 Packages |
2728 | + """ |
2729 | + And stdout matches regexp: |
2730 | + """ |
2731 | + Installed: .*[~+]esm |
2732 | + """ |
2733 | + When I run `apt install -y <apps-pkg>/<release>-apps-security` with sudo, retrying exit [100] |
2734 | + And I run `apt-cache policy <apps-pkg>` as non-root |
2735 | + Then stdout matches regexp: |
2736 | + """ |
2737 | + Version table: |
2738 | + \s*\*\*\* .* 500 |
2739 | + \s*500 https://esm.ubuntu.com/apps/ubuntu <release>-apps-security/main amd64 Packages |
2740 | + """ |
2741 | + |
2742 | + Examples: ubuntu release |
2743 | + | release | infra-pkg | apps-pkg | fips-apt-source | fips-kernel-version | |
2744 | + | xenial | libkrad0 | jq | https://esm.ubuntu.com/fips/ubuntu xenial/main | fips | |
2745 | + | bionic | libkrad0 | bundler | https://esm.ubuntu.com/fips/ubuntu bionic/main | azure-fips | |
2746 | + |
2747 | + @series.lts |
2748 | + @uses.config.machine_type.aws.pro.fips |
2749 | + Scenario Outline: Check fips is enabled correctly on Ubuntu pro fips AWS machine |
2750 | + Given a `<release>` machine with ubuntu-advantage-tools installed |
2751 | + When I create the file `/etc/ubuntu-advantage/uaclient.conf` with the following: |
2752 | + """ |
2753 | + contract_url: 'https://contracts.canonical.com' |
2754 | + data_dir: /var/lib/ubuntu-advantage |
2755 | + log_level: debug |
2756 | + log_file: /var/log/ubuntu-advantage.log |
2757 | + """ |
2758 | + And I run `ua auto-attach` with sudo |
2759 | + And I run `ua status --wait` as non-root |
2760 | + And I run `ua status` as non-root |
2761 | + Then stdout matches regexp: |
2762 | + """ |
2763 | + esm-apps +yes +enabled +UA Apps: Extended Security Maintenance \(ESM\) |
2764 | + esm-infra +yes +enabled +UA Infra: Extended Security Maintenance \(ESM\) |
2765 | + fips +yes +enabled +NIST-certified core packages |
2766 | + fips-updates +yes +disabled +NIST-certified core packages with priority security updates |
2767 | + livepatch +yes +n/a +Canonical Livepatch service |
2768 | + """ |
2769 | + And I verify that running `apt update` `with sudo` exits `0` |
2770 | + And I verify that running `grep Traceback /var/log/ubuntu-advantage.log` `with sudo` exits `1` |
2771 | + And I verify that `openssh-server` is installed from apt source `<fips-apt-source>` |
2772 | + And I verify that `openssh-client` is installed from apt source `<fips-apt-source>` |
2773 | + And I verify that `strongswan` is installed from apt source `<fips-apt-source>` |
2774 | + And I verify that `openssh-server-hmac` is installed from apt source `<fips-apt-source>` |
2775 | + And I verify that `openssh-client-hmac` is installed from apt source `<fips-apt-source>` |
2776 | + And I verify that `strongswan-hmac` is installed from apt source `<fips-apt-source>` |
2777 | + When I run `uname -r` as non-root |
2778 | + Then stdout matches regexp: |
2779 | + """ |
2780 | + <fips-kernel-version> |
2781 | + """ |
2782 | + When I run `apt-cache policy ubuntu-aws-fips` as non-root |
2783 | + Then stdout does not match regexp: |
2784 | + """ |
2785 | + .*Installed: \(none\) |
2786 | + """ |
2787 | + When I run `cat /proc/sys/crypto/fips_enabled` with sudo |
2788 | + Then I will see the following on stdout: |
2789 | + """ |
2790 | + 1 |
2791 | + """ |
2792 | + When I run `systemctl start ua-auto-attach.service` with sudo |
2793 | + And I verify that running `systemctl status ua-auto-attach.service` `as non-root` exits `0,3` |
2794 | + Then stdout matches regexp: |
2795 | + """ |
2796 | + .*status=0\/SUCCESS.* |
2797 | + """ |
2798 | + And stdout matches regexp: |
2799 | + """ |
2800 | + Skipping attach: Instance '[0-9a-z\-]+' is already attached. |
2801 | + """ |
2802 | + When I run `ua auto-attach` with sudo |
2803 | + Then stderr matches regexp: |
2804 | + """ |
2805 | + Skipping attach: Instance '[0-9a-z\-]+' is already attached. |
2806 | + """ |
2807 | + When I run `apt-cache policy` with sudo |
2808 | + Then apt-cache policy for the following url has permission `500` |
2809 | + """ |
2810 | + https://esm.ubuntu.com/infra/ubuntu <release>-infra-updates/main amd64 Packages |
2811 | + """ |
2812 | + And apt-cache policy for the following url has permission `500` |
2813 | + """ |
2814 | + https://esm.ubuntu.com/infra/ubuntu <release>-infra-security/main amd64 Packages |
2815 | + """ |
2816 | + And apt-cache policy for the following url has permission `500` |
2817 | + """ |
2818 | + https://esm.ubuntu.com/apps/ubuntu <release>-apps-updates/main amd64 Packages |
2819 | + """ |
2820 | + And apt-cache policy for the following url has permission `500` |
2821 | + """ |
2822 | + https://esm.ubuntu.com/apps/ubuntu <release>-apps-security/main amd64 Packages |
2823 | + """ |
2824 | + And I verify that running `apt update` `with sudo` exits `0` |
2825 | + When I run `apt install -y <infra-pkg>/<release>-infra-security` with sudo, retrying exit [100] |
2826 | + And I run `apt-cache policy <infra-pkg>` as non-root |
2827 | + Then stdout matches regexp: |
2828 | + """ |
2829 | + \s*500 https://esm.ubuntu.com/infra/ubuntu <release>-infra-security/main amd64 Packages |
2830 | + \s*500 https://esm.ubuntu.com/infra/ubuntu <release>-infra-updates/main amd64 Packages |
2831 | + """ |
2832 | + And stdout matches regexp: |
2833 | + """ |
2834 | + Installed: .*[~+]esm |
2835 | + """ |
2836 | + When I run `apt install -y <apps-pkg>/<release>-apps-security` with sudo, retrying exit [100] |
2837 | + And I run `apt-cache policy <apps-pkg>` as non-root |
2838 | + Then stdout matches regexp: |
2839 | + """ |
2840 | + Version table: |
2841 | + \s*\*\*\* .* 500 |
2842 | + \s*500 https://esm.ubuntu.com/apps/ubuntu <release>-apps-security/main amd64 Packages |
2843 | + """ |
2844 | + |
2845 | + Examples: ubuntu release |
2846 | + | release | infra-pkg | apps-pkg | fips-apt-source | fips-kernel-version | |
2847 | + | xenial | libkrad0 | jq | https://esm.ubuntu.com/fips/ubuntu xenial/main | fips | |
2848 | + | bionic | libkrad0 | bundler | https://esm.ubuntu.com/fips/ubuntu bionic/main | aws-fips | |
2849 | + |
2850 | diff --git a/features/ubuntu_upgrade.feature b/features/ubuntu_upgrade.feature |
2851 | index fb506b9..4cf3407 100644 |
2852 | --- a/features/ubuntu_upgrade.feature |
2853 | +++ b/features/ubuntu_upgrade.feature |
2854 | @@ -3,7 +3,6 @@ Feature: Upgrade between releases when uaclient is attached |
2855 | |
2856 | @slow |
2857 | @series.focal |
2858 | - @series.hirsute |
2859 | @series.impish |
2860 | @uses.config.machine_type.lxd.container |
2861 | @upgrade |
2862 | @@ -11,6 +10,8 @@ Feature: Upgrade between releases when uaclient is attached |
2863 | Given a `<release>` machine with ubuntu-advantage-tools installed |
2864 | When I attach `contract_token` with sudo |
2865 | And I run `apt-get dist-upgrade --assume-yes` with sudo |
2866 | + # Some packages upgrade may require a reboot |
2867 | + And I reboot the `<release>` machine |
2868 | And I create the file `/etc/update-manager/release-upgrades.d/ua-test.cfg` with the following |
2869 | """ |
2870 | [Sources] |
2871 | @@ -41,8 +42,7 @@ Feature: Upgrade between releases when uaclient is attached |
2872 | |
2873 | Examples: ubuntu release |
2874 | | release | next_release | devel_release | |
2875 | - | focal | hirsute | | |
2876 | - | hirsute | impish | | |
2877 | + | focal | impish | | |
2878 | | impish | jammy | --devel-release | |
2879 | |
2880 | @slow |
2881 | diff --git a/features/ubuntu_upgrade_unattached.feature b/features/ubuntu_upgrade_unattached.feature |
2882 | index 3944dba..0856c92 100644 |
2883 | --- a/features/ubuntu_upgrade_unattached.feature |
2884 | +++ b/features/ubuntu_upgrade_unattached.feature |
2885 | @@ -3,13 +3,14 @@ Feature: Upgrade between releases when uaclient is unattached |
2886 | |
2887 | @slow |
2888 | @series.focal |
2889 | - @series.hirsute |
2890 | @series.impish |
2891 | @uses.config.machine_type.lxd.container |
2892 | @upgrade |
2893 | Scenario Outline: Unattached upgrade across releases |
2894 | Given a `<release>` machine with ubuntu-advantage-tools installed |
2895 | When I run `apt-get dist-upgrade --assume-yes` with sudo |
2896 | + # Some packages upgrade may require a reboot |
2897 | + And I reboot the `<release>` machine |
2898 | And I create the file `/etc/update-manager/release-upgrades.d/ua-test.cfg` with the following |
2899 | """ |
2900 | [Sources] |
2901 | @@ -40,8 +41,7 @@ Feature: Upgrade between releases when uaclient is unattached |
2902 | |
2903 | Examples: ubuntu release |
2904 | | release | next_release | devel_release | |
2905 | - | focal | hirsute | | |
2906 | - | hirsute | impish | | |
2907 | + | focal | impish | | |
2908 | | impish | jammy | --devel-release | |
2909 | |
2910 | @slow |
2911 | diff --git a/features/unattached_commands.feature b/features/unattached_commands.feature |
2912 | index bda7597..7c95ab9 100644 |
2913 | --- a/features/unattached_commands.feature |
2914 | +++ b/features/unattached_commands.feature |
2915 | @@ -27,7 +27,6 @@ Feature: Command behaviour when unattached |
2916 | | bionic | |
2917 | | focal | |
2918 | | xenial | |
2919 | - | hirsute | |
2920 | | impish | |
2921 | | jammy | |
2922 | |
2923 | @@ -131,8 +130,6 @@ Feature: Command behaviour when unattached |
2924 | | focal | refresh | |
2925 | | xenial | detach | |
2926 | | xenial | refresh | |
2927 | - | hirsute | detach | |
2928 | - | hirsute | refresh | |
2929 | | impish | detach | |
2930 | | impish | refresh | |
2931 | | jammy | detach | |
2932 | @@ -169,10 +166,6 @@ Feature: Command behaviour when unattached |
2933 | | xenial | disable | livepatch | |
2934 | | xenial | enable | unknown | |
2935 | | xenial | disable | unknown | |
2936 | - | hirsute | enable | livepatch | |
2937 | - | hirsute | disable | livepatch | |
2938 | - | hirsute | enable | unknown | |
2939 | - | hirsute | disable | unknown | |
2940 | | impish | enable | livepatch | |
2941 | | impish | disable | livepatch | |
2942 | | impish | enable | unknown | |
2943 | @@ -220,7 +213,6 @@ Feature: Command behaviour when unattached |
2944 | | bionic | yes | |
2945 | | focal | yes | |
2946 | | xenial | yes | |
2947 | - | hirsute | no | |
2948 | | impish | no | |
2949 | | jammy | no | |
2950 | |
2951 | @@ -251,7 +243,6 @@ Feature: Command behaviour when unattached |
2952 | | xenial | |
2953 | | bionic | |
2954 | | focal | |
2955 | - | hirsute | |
2956 | | impish | |
2957 | | jammy | |
2958 | |
2959 | @@ -288,7 +279,7 @@ Feature: Command behaviour when unattached |
2960 | USN-4539-1: AWL vulnerability |
2961 | Found CVEs: |
2962 | https://ubuntu.com/security/CVE-2020-11728 |
2963 | - 1 affected package is installed: awl |
2964 | + 1 affected source package is installed: awl |
2965 | \(1/1\) awl: |
2966 | A fix is available in Ubuntu standard updates. |
2967 | .*\{ apt update && apt install --only-upgrade -y libawl-php \}.* |
2968 | @@ -299,7 +290,7 @@ Feature: Command behaviour when unattached |
2969 | """ |
2970 | CVE-2020-28196: Kerberos vulnerability |
2971 | https://ubuntu.com/security/CVE-2020-28196 |
2972 | - 1 affected package is installed: krb5 |
2973 | + 1 affected source package is installed: krb5 |
2974 | \(1/1\) krb5: |
2975 | A fix is available in Ubuntu standard updates. |
2976 | The update is already installed. |
2977 | @@ -323,7 +314,7 @@ Feature: Command behaviour when unattached |
2978 | USN-4539-1: AWL vulnerability |
2979 | Found CVEs: |
2980 | https://ubuntu.com/security/CVE-2020-11728 |
2981 | - 1 affected package is installed: awl |
2982 | + 1 affected source package is installed: awl |
2983 | \(1/1\) awl: |
2984 | Sorry, no fix is available. |
2985 | 1 package is still affected: awl |
2986 | @@ -334,7 +325,7 @@ Feature: Command behaviour when unattached |
2987 | """ |
2988 | CVE-2020-15180: MariaDB vulnerabilities |
2989 | https://ubuntu.com/security/CVE-2020-15180 |
2990 | - No affected packages are installed. |
2991 | + No affected source packages are installed. |
2992 | .*✔.* CVE-2020-15180 does not affect your system. |
2993 | """ |
2994 | When I run `ua fix CVE-2020-28196` as non-root |
2995 | @@ -342,7 +333,7 @@ Feature: Command behaviour when unattached |
2996 | """ |
2997 | CVE-2020-28196: Kerberos vulnerability |
2998 | https://ubuntu.com/security/CVE-2020-28196 |
2999 | - 1 affected package is installed: krb5 |
3000 | + 1 affected source package is installed: krb5 |
3001 | \(1/1\) krb5: |
3002 | A fix is available in Ubuntu standard updates. |
3003 | The update is already installed. |
3004 | @@ -354,7 +345,7 @@ Feature: Command behaviour when unattached |
3005 | """ |
3006 | CVE-2017-9233: Expat vulnerability |
3007 | https://ubuntu.com/security/CVE-2017-9233 |
3008 | - 3 affected packages are installed: expat, matanza, swish-e |
3009 | + 3 affected source packages are installed: expat, matanza, swish-e |
3010 | \(1/3, 2/3\) matanza, swish-e: |
3011 | Sorry, no fix is available. |
3012 | \(3/3\) expat: |
3013 | @@ -363,6 +354,28 @@ Feature: Command behaviour when unattached |
3014 | 2 packages are still affected: matanza, swish-e |
3015 | .*✘.* CVE-2017-9233 is not resolved. |
3016 | """ |
3017 | + When I fix `USN-5079-2` by attaching to a subscription with `contract_token_staging_expired` |
3018 | + Then stdout matches regexp |
3019 | + """ |
3020 | + USN-5079-2: curl vulnerabilities |
3021 | + Found CVEs: |
3022 | + https://ubuntu.com/security/CVE-2021-22946 |
3023 | + https://ubuntu.com/security/CVE-2021-22947 |
3024 | + 1 affected source package is installed: curl |
3025 | + \(1/1\) curl: |
3026 | + A fix is available in UA Infra. |
3027 | + The update is not installed because this system is not attached to a |
3028 | + subscription. |
3029 | + |
3030 | + Choose: \[S\]ubscribe at ubuntu.com \[A\]ttach existing token \[C\]ancel |
3031 | + > Enter your token \(from https://ubuntu.com/advantage\) to attach this system: |
3032 | + > .*\{ ua attach .*\}.* |
3033 | + Attach denied: |
3034 | + Contract ".*" expired on .* |
3035 | + Visit https://ubuntu.com/advantage to manage contract tokens. |
3036 | + 1 package is still affected: curl |
3037 | + .*✘.* USN-5079-2 is not resolved. |
3038 | + """ |
3039 | When I fix `USN-5079-2` by attaching to a subscription with `contract_token` |
3040 | Then stdout matches regexp: |
3041 | """ |
3042 | @@ -370,7 +383,7 @@ Feature: Command behaviour when unattached |
3043 | Found CVEs: |
3044 | https://ubuntu.com/security/CVE-2021-22946 |
3045 | https://ubuntu.com/security/CVE-2021-22947 |
3046 | - 1 affected package is installed: curl |
3047 | + 1 affected source package is installed: curl |
3048 | \(1/1\) curl: |
3049 | A fix is available in UA Infra. |
3050 | The update is not installed because this system is not attached to a |
3051 | @@ -395,7 +408,7 @@ Feature: Command behaviour when unattached |
3052 | USN-5051-2: OpenSSL vulnerability |
3053 | Found CVEs: |
3054 | https://ubuntu.com/security/CVE-2021-3712 |
3055 | - 1 affected package is installed: openssl |
3056 | + 1 affected source package is installed: openssl |
3057 | \(1/1\) openssl: |
3058 | A fix is available in UA Infra. |
3059 | .*\{ apt update && apt install --only-upgrade -y libssl1.0.0 openssl \}.* |
3060 | @@ -440,7 +453,7 @@ Feature: Command behaviour when unattached |
3061 | USN-4539-1: AWL vulnerability |
3062 | Found CVEs: |
3063 | https://ubuntu.com/security/CVE-2020-11728 |
3064 | - 1 affected package is installed: awl |
3065 | + 1 affected source package is installed: awl |
3066 | \(1/1\) awl: |
3067 | Ubuntu security engineers are investigating this issue. |
3068 | 1 package is still affected: awl |
3069 | @@ -451,7 +464,7 @@ Feature: Command behaviour when unattached |
3070 | """ |
3071 | CVE-2020-28196: Kerberos vulnerability |
3072 | https://ubuntu.com/security/CVE-2020-28196 |
3073 | - 1 affected package is installed: krb5 |
3074 | + 1 affected source package is installed: krb5 |
3075 | \(1/1\) krb5: |
3076 | A fix is available in Ubuntu standard updates. |
3077 | The update is already installed. |
3078 | @@ -463,7 +476,7 @@ Feature: Command behaviour when unattached |
3079 | """ |
3080 | CVE-2021-27135: xterm vulnerability |
3081 | https://ubuntu.com/security/CVE-2021-27135 |
3082 | - 1 affected package is installed: xterm |
3083 | + 1 affected source package is installed: xterm |
3084 | \(1/1\) xterm: |
3085 | A fix is available in Ubuntu standard updates. |
3086 | Package fixes cannot be installed. |
3087 | @@ -476,7 +489,7 @@ Feature: Command behaviour when unattached |
3088 | """ |
3089 | CVE-2021-27135: xterm vulnerability |
3090 | https://ubuntu.com/security/CVE-2021-27135 |
3091 | - 1 affected package is installed: xterm |
3092 | + 1 affected source package is installed: xterm |
3093 | \(1/1\) xterm: |
3094 | A fix is available in Ubuntu standard updates. |
3095 | .*\{ apt update && apt install --only-upgrade -y xterm \}.* |
3096 | @@ -487,12 +500,26 @@ Feature: Command behaviour when unattached |
3097 | """ |
3098 | CVE-2021-27135: xterm vulnerability |
3099 | https://ubuntu.com/security/CVE-2021-27135 |
3100 | - 1 affected package is installed: xterm |
3101 | + 1 affected source package is installed: xterm |
3102 | \(1/1\) xterm: |
3103 | A fix is available in Ubuntu standard updates. |
3104 | The update is already installed. |
3105 | .*✔.* CVE-2021-27135 is resolved. |
3106 | """ |
3107 | + When I run `apt-get install libbz2-1.0=1.0.6-8.1 -y --allow-downgrades` with sudo |
3108 | + And I run `apt-get install bzip2=1.0.6-8.1 -y` with sudo |
3109 | + And I run `ua fix USN-4038-3` with sudo |
3110 | + Then stdout matches regexp: |
3111 | + """ |
3112 | + USN-4038-3: bzip2 regression |
3113 | + Found Launchpad bugs: |
3114 | + https://launchpad.net/bugs/1834494 |
3115 | + 1 affected source package is installed: bzip2 |
3116 | + \(1/1\) bzip2: |
3117 | + A fix is available in Ubuntu standard updates. |
3118 | + .*\{ apt update && apt install --only-upgrade -y bzip2 libbz2-1.0 \}.* |
3119 | + .*✔.* USN-4038-3 is resolved. |
3120 | + """ |
3121 | |
3122 | |
3123 | @series.all |
3124 | @@ -535,6 +562,31 @@ Feature: Command behaviour when unattached |
3125 | | release | |
3126 | | bionic | |
3127 | | focal | |
3128 | - | hirsute | |
3129 | + | impish | |
3130 | + | jammy | |
3131 | + |
3132 | + @series.all |
3133 | + @uses.config.machine_type.lxd.container |
3134 | + Scenario Outline: Unattached enable fails in a ubuntu machine |
3135 | + Given a `<release>` machine with ubuntu-advantage-tools installed |
3136 | + When I verify that running `ua enable esm-infra` `with sudo` exits `1` |
3137 | + Then I will see the following on stderr: |
3138 | + """ |
3139 | + To use 'esm-infra' you need an Ubuntu Advantage subscription |
3140 | + Personal and community subscriptions are available at no charge |
3141 | + See https://ubuntu.com/advantage |
3142 | + """ |
3143 | + When I verify that running `ua enable esm-infra --format json --assume-yes` `with sudo` exits `1` |
3144 | + Then stdout is a json matching the `ua_operation` schema |
3145 | + And I will see the following on stdout: |
3146 | + """ |
3147 | + {"_schema_version": "0.1", "errors": [{"message": "To use 'esm-infra' you need an Ubuntu Advantage subscription\nPersonal and community subscriptions are available at no charge\nSee https://ubuntu.com/advantage", "message_code": "enable-failure-unattached", "service": null, "type": "system"}], "failed_services": [], "needs_reboot": false, "processed_services": [], "result": "failure", "warnings": []} |
3148 | + """ |
3149 | + |
3150 | + Examples: ubuntu release |
3151 | + | release | |
3152 | + | xenial | |
3153 | + | bionic | |
3154 | + | focal | |
3155 | | impish | |
3156 | | jammy | |
3157 | diff --git a/features/unattached_status.feature b/features/unattached_status.feature |
3158 | index 7b91df3..08538a2 100644 |
3159 | --- a/features/unattached_status.feature |
3160 | +++ b/features/unattached_status.feature |
3161 | @@ -5,18 +5,31 @@ Feature: Unattached status |
3162 | Scenario Outline: Unattached status in a ubuntu machine - formatted |
3163 | Given a `<release>` machine with ubuntu-advantage-tools installed |
3164 | When I run `ua status --format json` as non-root |
3165 | - Then stdout is formatted as `json` and has keys: |
3166 | + Then stdout is a json matching the `ua_status` schema |
3167 | + When I run `ua status --format yaml` as non-root |
3168 | + Then stdout is a yaml matching the `ua_status` schema |
3169 | + When I run `sed -i 's/contracts.can/invalidurl.notcan/' /etc/ubuntu-advantage/uaclient.conf` with sudo |
3170 | + And I verify that running `ua status --format json` `as non-root` exits `1` |
3171 | + Then stdout is a json matching the `ua_status` schema |
3172 | + And I will see the following on stdout: |
3173 | """ |
3174 | - _doc _schema_version account attached config config_path contract effective |
3175 | - environment_vars execution_details execution_status expires machine_id notices |
3176 | - services version simulated |
3177 | + {"environment_vars": [], "errors": [{"message": "Failed to connect to authentication server\nCheck your Internet connection and try again.", "message_code": "connectivity-error", "service": null, "type": "system"}], "result": "failure", "services": [], "warnings": []} |
3178 | """ |
3179 | - When I run `ua status --format yaml` as non-root |
3180 | - Then stdout is formatted as `yaml` and has keys: |
3181 | + And I verify that running `ua status --format yaml` `as non-root` exits `1` |
3182 | + Then stdout is a yaml matching the `ua_status` schema |
3183 | + And I will see the following on stdout: |
3184 | """ |
3185 | - _doc _schema_version account attached config config_path contract effective |
3186 | - environment_vars execution_details execution_status expires machine_id notices |
3187 | - services version simulated |
3188 | + environment_vars: [] |
3189 | + errors: |
3190 | + - message: 'Failed to connect to authentication server |
3191 | + |
3192 | + Check your Internet connection and try again.' |
3193 | + message_code: connectivity-error |
3194 | + service: null |
3195 | + type: system |
3196 | + result: failure |
3197 | + services: [] |
3198 | + warnings: [] |
3199 | """ |
3200 | |
3201 | Examples: ubuntu release |
3202 | @@ -24,7 +37,6 @@ Feature: Unattached status |
3203 | | bionic | |
3204 | | focal | |
3205 | | xenial | |
3206 | - | hirsute | |
3207 | | impish | |
3208 | | jammy | |
3209 | |
3210 | @@ -32,7 +44,6 @@ Feature: Unattached status |
3211 | @uses.config.machine_type.lxd.container |
3212 | Scenario Outline: Unattached status in a ubuntu machine |
3213 | Given a `<release>` machine with ubuntu-advantage-tools installed |
3214 | - When I run `sed -i 's/contracts.can/contracts.staging.can/' /etc/ubuntu-advantage/uaclient.conf` with sudo |
3215 | When I run `ua status` as non-root |
3216 | Then stdout matches regexp: |
3217 | """ |
3218 | @@ -128,63 +139,104 @@ Feature: Unattached status |
3219 | | xenial | yes | yes | cis | yes | yes | yes | yes | yes | | |
3220 | | bionic | yes | yes | cis | yes | yes | yes | yes | yes | | |
3221 | | focal | yes | no | | yes | yes | yes | no | yes | usg | |
3222 | - | hirsute | no | no | cis | no | no | no | no | no | | |
3223 | | impish | no | no | cis | no | no | no | no | no | | |
3224 | | jammy | no | no | cis | no | no | no | no | no | | |
3225 | |
3226 | @series.all |
3227 | @uses.config.machine_type.lxd.container |
3228 | @uses.config.contract_token |
3229 | + @uses.config.contract_token_staging_expired |
3230 | Scenario Outline: Simulate status in a ubuntu machine |
3231 | Given a `<release>` machine with ubuntu-advantage-tools installed |
3232 | When I do a preflight check for `contract_token` without the all flag |
3233 | Then stdout matches regexp: |
3234 | - """ |
3235 | - SERVICE AVAILABLE ENTITLED AUTO_ENABLED DESCRIPTION |
3236 | - cc-eal <cc-eal> +yes +no +Common Criteria EAL2 Provisioning Packages |
3237 | - ?<cis>( +<cis-available> +yes +no +Security compliance and audit tools)? |
3238 | - ?esm-infra <esm-infra> +yes +yes +UA Infra: Extended Security Maintenance \(ESM\) |
3239 | - fips <fips> +yes +no +NIST-certified core packages |
3240 | - fips-updates <fips> +yes +no +NIST-certified core packages with priority security updates |
3241 | - livepatch <livepatch> +yes +yes +Canonical Livepatch service |
3242 | - ?<usg>( +<cis-available> +yes +no +Security compliance and audit tools)? |
3243 | - """ |
3244 | + """ |
3245 | + SERVICE AVAILABLE ENTITLED AUTO_ENABLED DESCRIPTION |
3246 | + cc-eal <cc-eal> +yes +no +Common Criteria EAL2 Provisioning Packages |
3247 | + ?<cis>( +<cis-available> +yes +no +Security compliance and audit tools)? |
3248 | + ?esm-infra <esm-infra> +yes +yes +UA Infra: Extended Security Maintenance \(ESM\) |
3249 | + fips <fips> +yes +no +NIST-certified core packages |
3250 | + fips-updates <fips> +yes +no +NIST-certified core packages with priority security updates |
3251 | + livepatch <livepatch> +yes +yes +Canonical Livepatch service |
3252 | + ?<usg>( +<cis-available> +yes +no +Security compliance and audit tools)? |
3253 | + """ |
3254 | When I do a preflight check for `contract_token` with the all flag |
3255 | Then stdout matches regexp: |
3256 | - """ |
3257 | - SERVICE AVAILABLE ENTITLED AUTO_ENABLED DESCRIPTION |
3258 | - cc-eal <cc-eal> +yes +no +Common Criteria EAL2 Provisioning Packages |
3259 | - ?<cis>( +<cis-available> +yes +no +Security compliance and audit tools)? |
3260 | - ?esm-apps <esm-apps> +yes +yes +UA Apps: Extended Security Maintenance \(ESM\) |
3261 | - esm-infra <esm-infra> +yes +yes +UA Infra: Extended Security Maintenance \(ESM\) |
3262 | - fips <fips> +yes +no +NIST-certified core packages |
3263 | - fips-updates <fips> +yes +no +NIST-certified core packages with priority security updates |
3264 | - livepatch <livepatch> +yes +yes +Canonical Livepatch service |
3265 | - ros <ros> +yes +no +Security Updates for the Robot Operating System |
3266 | - ros-updates <ros> +yes +no +All Updates for the Robot Operating System |
3267 | - ?<usg>( +<cis-available> +yes +no +Security compliance and audit tools)? |
3268 | - """ |
3269 | + """ |
3270 | + SERVICE AVAILABLE ENTITLED AUTO_ENABLED DESCRIPTION |
3271 | + cc-eal <cc-eal> +yes +no +Common Criteria EAL2 Provisioning Packages |
3272 | + ?<cis>( +<cis-available> +yes +no +Security compliance and audit tools)? |
3273 | + ?esm-apps <esm-apps> +yes +yes +UA Apps: Extended Security Maintenance \(ESM\) |
3274 | + esm-infra <esm-infra> +yes +yes +UA Infra: Extended Security Maintenance \(ESM\) |
3275 | + fips <fips> +yes +no +NIST-certified core packages |
3276 | + fips-updates <fips> +yes +no +NIST-certified core packages with priority security updates |
3277 | + livepatch <livepatch> +yes +yes +Canonical Livepatch service |
3278 | + ros <ros> +yes +no +Security Updates for the Robot Operating System |
3279 | + ros-updates <ros> +yes +no +All Updates for the Robot Operating System |
3280 | + ?<usg>( +<cis-available> +yes +no +Security compliance and audit tools)? |
3281 | + """ |
3282 | When I do a preflight check for `contract_token` formatted as json |
3283 | - Then stdout is formatted as `json` and has keys: |
3284 | - """ |
3285 | - _doc _schema_version account attached config config_path contract effective |
3286 | - environment_vars execution_details execution_status expires machine_id notices |
3287 | - services version simulated |
3288 | - """ |
3289 | + Then stdout is a json matching the `ua_status` schema |
3290 | When I do a preflight check for `contract_token` formatted as yaml |
3291 | - Then stdout is formatted as `yaml` and has keys: |
3292 | - """ |
3293 | - _doc _schema_version account attached config config_path contract effective |
3294 | - environment_vars execution_details execution_status expires machine_id notices |
3295 | - services version simulated |
3296 | - """ |
3297 | + Then stdout is a yaml matching the `ua_status` schema |
3298 | + When I verify that a preflight check for `invalid_token` formatted as json exits 1 |
3299 | + Then stdout is a json matching the `ua_status` schema |
3300 | + And I will see the following on stdout: |
3301 | + """ |
3302 | + {"environment_vars": [], "errors": [{"message": "Invalid token. See https://ubuntu.com/advantage", "message_code": "attach-invalid-token", "service": null, "type": "system"}], "result": "failure", "services": [], "warnings": []} |
3303 | + """ |
3304 | + When I verify that a preflight check for `invalid_token` formatted as yaml exits 1 |
3305 | + Then stdout is a yaml matching the `ua_status` schema |
3306 | + And I will see the following on stdout: |
3307 | + """ |
3308 | + environment_vars: [] |
3309 | + errors: |
3310 | + - message: Invalid token. See https://ubuntu.com/advantage |
3311 | + message_code: attach-invalid-token |
3312 | + service: null |
3313 | + type: system |
3314 | + result: failure |
3315 | + services: [] |
3316 | + warnings: [] |
3317 | + """ |
3318 | + When I run `sed -i 's/contracts.can/contracts.staging.can/' /etc/ubuntu-advantage/uaclient.conf` with sudo |
3319 | + And I verify that a preflight check for `contract_token_staging_expired` formatted as json exits 1 |
3320 | + Then stdout is a json matching the `ua_status` schema |
3321 | + And stdout matches regexp: |
3322 | + """ |
3323 | + \"result\": \"failure\" |
3324 | + """ |
3325 | + And stdout matches regexp: |
3326 | + """ |
3327 | + \"message\": \"Contract .* expired on .*\" |
3328 | + """ |
3329 | + When I verify that a preflight check for `contract_token_staging_expired` formatted as yaml exits 1 |
3330 | + Then stdout is a yaml matching the `ua_status` schema |
3331 | + Then stdout matches regexp: |
3332 | + """ |
3333 | + errors: |
3334 | + - message: Contract .* expired on .* |
3335 | + """ |
3336 | + When I verify that a preflight check for `contract_token_staging_expired` without the all flag exits 1 |
3337 | + Then stdout matches regexp: |
3338 | + """ |
3339 | + This token is not valid. |
3340 | + Contract \".*\" expired on .* |
3341 | |
3342 | + SERVICE AVAILABLE ENTITLED AUTO_ENABLED DESCRIPTION |
3343 | + cc-eal <cc-eal> +yes +no +Common Criteria EAL2 Provisioning Packages |
3344 | + ?<cis>( +<cis-available> +yes +no +Security compliance and audit tools)? |
3345 | + ?esm-infra <esm-infra> +yes +yes +UA Infra: Extended Security Maintenance \(ESM\) |
3346 | + fips <fips> +yes +no +NIST-certified core packages |
3347 | + fips-updates <fips> +yes +no +NIST-certified core packages with priority security updates |
3348 | + livepatch <livepatch> +yes +yes +Canonical Livepatch service |
3349 | + ?<usg>( +<cis-available> +yes +no +Security compliance and audit tools)? |
3350 | + """ |
3351 | |
3352 | Examples: ubuntu release |
3353 | | release | esm-apps | cc-eal | cis | cis-available | fips | esm-infra | ros | livepatch | usg | |
3354 | | xenial | yes | yes | cis | yes | yes | yes | yes | yes | | |
3355 | | bionic | yes | yes | cis | yes | yes | yes | yes | yes | | |
3356 | | focal | yes | no | | yes | yes | yes | no | yes | usg | |
3357 | - | hirsute | no | no | cis | no | no | no | no | no | | |
3358 | | impish | no | no | cis | no | no | no | no | no | | |
3359 | | jammy | no | no | cis | no | no | no | no | no | | |
3360 | diff --git a/features/util.py b/features/util.py |
3361 | index 8bb7dfe..7e00746 100644 |
3362 | --- a/features/util.py |
3363 | +++ b/features/util.py |
3364 | @@ -325,3 +325,10 @@ def emit_spinner_on_travis(msg: str = " "): |
3365 | finally: |
3366 | print() |
3367 | dot_process.terminate() |
3368 | + |
3369 | + |
3370 | +class SafeLoaderWithoutDatetime(yaml.SafeLoader): |
3371 | + yaml_implicit_resolvers = { |
3372 | + k: [r for r in v if r[0] != "tag:yaml.org,2002:timestamp"] |
3373 | + for k, v in yaml.SafeLoader.yaml_implicit_resolvers.items() |
3374 | + } |
3375 | diff --git a/integration-requirements.txt b/integration-requirements.txt |
3376 | index 69471fa..effd7bd 100644 |
3377 | --- a/integration-requirements.txt |
3378 | +++ b/integration-requirements.txt |
3379 | @@ -1,5 +1,6 @@ |
3380 | # Integration testing |
3381 | behave |
3382 | +jsonschema |
3383 | PyHamcrest |
3384 | pycloudlib @ git+https://github.com/canonical/pycloudlib.git@756a2c2de044ca60eaa7cdc76653d23a1339dc0a |
3385 | |
3386 | diff --git a/lib/reboot_cmds.py b/lib/reboot_cmds.py |
3387 | index 569b46a..c819dba 100644 |
3388 | --- a/lib/reboot_cmds.py |
3389 | +++ b/lib/reboot_cmds.py |
3390 | @@ -18,11 +18,10 @@ import logging |
3391 | import os |
3392 | import sys |
3393 | |
3394 | -from uaclient import config, contract, lock, status |
3395 | +from uaclient import config, contract, exceptions, lock, messages |
3396 | from uaclient.cli import setup_logging |
3397 | from uaclient.entitlements.fips import FIPSEntitlement |
3398 | -from uaclient.exceptions import LockHeldError, UserFacingError |
3399 | -from uaclient.util import ProcessExecutionError, UrlError, subp |
3400 | +from uaclient.util import subp |
3401 | |
3402 | # Retry sleep backoff algorithm if lock is held. |
3403 | # Lock may be held by auto-attach on systems with ubuntu-advantage-pro. |
3404 | @@ -34,7 +33,7 @@ def run_command(cmd, cfg): |
3405 | try: |
3406 | out, _ = subp(cmd.split(), capture=True) |
3407 | logging.debug("Successfully executed cmd: {}".format(cmd)) |
3408 | - except ProcessExecutionError as exec_error: |
3409 | + except exceptions.ProcessExecutionError as exec_error: |
3410 | msg = ( |
3411 | "Failed running cmd: {}\n" |
3412 | "Return code: {}\n" |
3413 | @@ -75,7 +74,7 @@ def fix_pro_pkg_holds(cfg): |
3414 | ) |
3415 | try: |
3416 | entitlement.install_packages(cleanup_on_failure=False) |
3417 | - except UserFacingError as e: |
3418 | + except exceptions.UserFacingError as e: |
3419 | logging.error(e.msg) |
3420 | logging.warning( |
3421 | "Failed to install packages at boot: {}".format( |
3422 | @@ -83,22 +82,22 @@ def fix_pro_pkg_holds(cfg): |
3423 | ) |
3424 | ) |
3425 | sys.exit(1) |
3426 | - cfg.remove_notice("", status.MESSAGE_FIPS_REBOOT_REQUIRED) |
3427 | + cfg.remove_notice("", messages.FIPS_SYSTEM_REBOOT_REQUIRED.msg) |
3428 | |
3429 | |
3430 | def refresh_contract(cfg): |
3431 | try: |
3432 | contract.request_updated_contract(cfg) |
3433 | - except UrlError as exc: |
3434 | + except exceptions.UrlError as exc: |
3435 | logging.exception(exc) |
3436 | - logging.warning(status.MESSAGE_REFRESH_CONTRACT_FAILURE) |
3437 | + logging.warning(messages.REFRESH_CONTRACT_FAILURE) |
3438 | sys.exit(1) |
3439 | |
3440 | |
3441 | def process_remaining_deltas(cfg): |
3442 | cmd = "/usr/bin/python3 /usr/lib/ubuntu-advantage/upgrade_lts_contract.py" |
3443 | run_command(cmd=cmd, cfg=cfg) |
3444 | - cfg.remove_notice("", status.MESSAGE_LIVEPATCH_LTS_REBOOT_REQUIRED) |
3445 | + cfg.remove_notice("", messages.LIVEPATCH_LTS_REBOOT_REQUIRED) |
3446 | |
3447 | |
3448 | def process_reboot_operations(cfg): |
3449 | @@ -122,13 +121,13 @@ def process_reboot_operations(cfg): |
3450 | process_remaining_deltas(cfg) |
3451 | |
3452 | cfg.delete_cache_key("marker-reboot-cmds") |
3453 | - cfg.remove_notice("", status.MESSAGE_REBOOT_SCRIPT_FAILED) |
3454 | + cfg.remove_notice("", messages.REBOOT_SCRIPT_FAILED) |
3455 | logging.debug("Successfully ran all commands on reboot.") |
3456 | except Exception as e: |
3457 | msg = "Failed running commands on reboot." |
3458 | msg += str(e) |
3459 | logging.error(msg) |
3460 | - cfg.add_notice("", status.MESSAGE_REBOOT_SCRIPT_FAILED) |
3461 | + cfg.add_notice("", messages.REBOOT_SCRIPT_FAILED) |
3462 | |
3463 | |
3464 | def main(cfg): |
3465 | @@ -145,7 +144,7 @@ def main(cfg): |
3466 | max_retries=MAX_RETRIES_ON_LOCK_HELD, |
3467 | ): |
3468 | process_reboot_operations(cfg=cfg) |
3469 | - except LockHeldError as e: |
3470 | + except exceptions.LockHeldError as e: |
3471 | logging.warning("Lock not released. %s", str(e.msg)) |
3472 | sys.exit(1) |
3473 | |
3474 | diff --git a/setup.py b/setup.py |
3475 | index 4c92683..bcce7c5 100644 |
3476 | --- a/setup.py |
3477 | +++ b/setup.py |
3478 | @@ -5,7 +5,7 @@ import glob |
3479 | |
3480 | import setuptools |
3481 | |
3482 | -from uaclient import defaults, util, version |
3483 | +from uaclient import defaults, version |
3484 | |
3485 | NAME = "ubuntu-advantage-tools" |
3486 | |
3487 | @@ -39,7 +39,7 @@ def _get_version(): |
3488 | |
3489 | |
3490 | def _get_data_files(): |
3491 | - data_files = [ |
3492 | + return [ |
3493 | ("/etc/ubuntu-advantage", ["uaclient.conf", "help_data.yaml"]), |
3494 | ("/etc/update-motd.d", glob.glob("update-motd.d/*")), |
3495 | ("/usr/lib/ubuntu-advantage", glob.glob("lib/[!_]*")), |
3496 | @@ -49,16 +49,8 @@ def _get_data_files(): |
3497 | ["release-upgrades.d/ubuntu-advantage-upgrades.cfg"], |
3498 | ), |
3499 | (defaults.CONFIG_DEFAULTS["data_dir"], []), |
3500 | + ("/lib/systemd/system", glob.glob("systemd/*")), |
3501 | ] |
3502 | - rel_major, _rel_minor = util.get_platform_info()["release"].split(".", 1) |
3503 | - if rel_major == "14": |
3504 | - data_files.append( |
3505 | - ("/etc/apt/apt.conf.d", ["apt.conf.d/51ubuntu-advantage-esm"]) |
3506 | - ) |
3507 | - data_files.append(("/etc/init", glob.glob("upstart/*"))) |
3508 | - else: |
3509 | - data_files.append(("/lib/systemd/system", glob.glob("systemd/*"))) |
3510 | - return data_files |
3511 | |
3512 | |
3513 | setuptools.setup( |
3514 | diff --git a/sru/release-27.7/test_world_readable_logs.sh b/sru/release-27.7/test_world_readable_logs.sh |
3515 | new file mode 100644 |
3516 | index 0000000..ed687a7 |
3517 | --- /dev/null |
3518 | +++ b/sru/release-27.7/test_world_readable_logs.sh |
3519 | @@ -0,0 +1,66 @@ |
3520 | +series=$1 |
3521 | +deb=$2 |
3522 | + |
3523 | +set -eE |
3524 | + |
3525 | +GREEN="\e[32m" |
3526 | +RED="\e[31m" |
3527 | +BLUE="\e[36m" |
3528 | +END_COLOR="\e[0m" |
3529 | + |
3530 | +function cleanup { |
3531 | + lxc delete test --force |
3532 | +} |
3533 | + |
3534 | +function on_err { |
3535 | + echo -e "${RED}Test Failed${END_COLOR}" |
3536 | + cleanup |
3537 | + exit 1 |
3538 | +} |
3539 | + |
3540 | +trap on_err ERR |
3541 | + |
3542 | +function print_and_run_cmd { |
3543 | + echo -e "${BLUE}Running:${END_COLOR}" "$@" |
3544 | + echo -e "${BLUE}Output:${END_COLOR}" |
3545 | + lxc exec test -- sh -c "$@" |
3546 | + echo |
3547 | +} |
3548 | + |
3549 | +function explanatory_message { |
3550 | + echo -e "${BLUE}$@${END_COLOR}" |
3551 | +} |
3552 | + |
3553 | +explanatory_message "Starting $series container and updating ubuntu-advantage-tools" |
3554 | +lxc launch ubuntu-daily:$series test >/dev/null 2>&1 |
3555 | +sleep 10 |
3556 | + |
3557 | +explanatory_message "Check that log is not world readable" |
3558 | +print_and_run_cmd "ua version" |
3559 | +print_and_run_cmd "head /var/log/ubuntu-advantage.log" |
3560 | +print_and_run_cmd "find /var/log/ -name ubuntu-advantage.log -perm 0600 | grep -qz ." |
3561 | + |
3562 | +lxc exec test -- apt-get update >/dev/null |
3563 | +explanatory_message "installing new version of ubuntu-advantage-tools from local copy" |
3564 | +lxc file push $deb test/tmp/ua.deb > /dev/null |
3565 | +print_and_run_cmd "dpkg -i /tmp/ua.deb" |
3566 | +print_and_run_cmd "ua version" |
3567 | + |
3568 | +explanatory_message "Check that log files permissions are still the same" |
3569 | +print_and_run_cmd "find /var/log/ -name ubuntu-advantage.log -perm 0600 | grep -qz ." |
3570 | + |
3571 | +explanatory_message "Check that logrotate command will create world readable files" |
3572 | +print_and_run_cmd "logrotate --force /etc/logrotate.d/ubuntu-advantage-tools" |
3573 | +print_and_run_cmd "find /var/log/ -name ubuntu-advantage.log -perm 0644 | grep -qz ." |
3574 | +print_and_run_cmd "find /var/log/ -name ubuntu-advantage.log.1 -perm 0600 | grep -qz ." |
3575 | + |
3576 | +explanatory_message "Check that running logrotate again will stil make world readable files" |
3577 | +# Just to add new entry to the log |
3578 | +print_and_run_cmd "ua version" |
3579 | +print_and_run_cmd "logrotate --force /etc/logrotate.d/ubuntu-advantage-tools" |
3580 | +print_and_run_cmd "find /var/log/ -name ubuntu-advantage.log -perm 0644 | grep -qz ." |
3581 | +print_and_run_cmd "find /var/log/ -name ubuntu-advantage.log.1 -perm 0644 | grep -qz ." |
3582 | +print_and_run_cmd "find /var/log/ -name ubuntu-advantage.log.2.gz -perm 0600 | grep -qz ." |
3583 | + |
3584 | +echo -e "${GREEN}Test Passed${END_COLOR}" |
3585 | +cleanup |
3586 | diff --git a/tools/create-lp-release-branches.sh b/tools/create-lp-release-branches.sh |
3587 | index 604df74..454af96 100755 |
3588 | --- a/tools/create-lp-release-branches.sh |
3589 | +++ b/tools/create-lp-release-branches.sh |
3590 | @@ -32,7 +32,7 @@ else |
3591 | set -e |
3592 | fi |
3593 | |
3594 | -for release in xenial bionic focal hirsute impish |
3595 | +for release in xenial bionic focal impish |
3596 | do |
3597 | echo |
3598 | echo $release |
3599 | @@ -48,7 +48,6 @@ do |
3600 | xenial) version=${UA_VERSION}~16.04.1;; |
3601 | bionic) version=${UA_VERSION}~18.04.1;; |
3602 | focal) version=${UA_VERSION}~20.04.1;; |
3603 | - hirsute) version=${UA_VERSION}~21.04.1;; |
3604 | impish) version=${UA_VERSION}~21.10.1;; |
3605 | esac |
3606 | dch_cmd=(dch -v ${version} -D ${release} -b "Backport new upstream release: (LP: #${SRU_BUG}) to $release") |
3607 | diff --git a/tools/refresh-aws-pro-ids b/tools/refresh-aws-pro-ids |
3608 | index 5256a6c..7a89f5a 100755 |
3609 | --- a/tools/refresh-aws-pro-ids |
3610 | +++ b/tools/refresh-aws-pro-ids |
3611 | @@ -3,6 +3,7 @@ |
3612 | import glob |
3613 | import os |
3614 | import re |
3615 | + |
3616 | import yaml |
3617 | |
3618 | from uaclient import util |
3619 | @@ -19,7 +20,7 @@ git push upstream your-branch |
3620 | Create a new pull request @ https://github.com/canonical/ubuntu-advantage-client/pulls |
3621 | """ |
3622 | |
3623 | -EOL_RELEASES = ("trusty", ) # Releases we no longer test |
3624 | +EOL_RELEASES = ("trusty",) # Releases we no longer test |
3625 | |
3626 | |
3627 | def main(): |
3628 | @@ -33,35 +34,45 @@ def main(): |
3629 | aws_ids = {} |
3630 | for aws_listing in glob.glob("listing-aws-pro-*"): |
3631 | m = re.match( |
3632 | - r"^listing-aws-pro-(?P<release>\w+).yaml$", aws_listing |
3633 | + r"^listing-aws-pro-(fips-)?(?P<release>\w+).yaml$", aws_listing |
3634 | ) |
3635 | if not m: |
3636 | print("Skipping unexpected listing file name: ", aws_listing) |
3637 | continue |
3638 | elif m.group("release") in EOL_RELEASES: |
3639 | print( |
3640 | - "Skipping release %s. No longer CI on EOL releases" % |
3641 | - m.group("release") |
3642 | + "Skipping release %s. No longer CI on EOL releases" |
3643 | + % m.group("release") |
3644 | ) |
3645 | continue |
3646 | listing = yaml.safe_load(open(aws_listing, "r")) |
3647 | - for md in listing['metadata']: |
3648 | + for md in listing["metadata"]: |
3649 | if md["key"] == "series": |
3650 | release = md["value"] |
3651 | + if "fips" in listing["productID"]: |
3652 | + release = release + "-fips" |
3653 | break |
3654 | - for externalID in listing['externalIDs']: |
3655 | - if externalID['origin'] == 'AWS': |
3656 | + for externalID in listing["externalIDs"]: |
3657 | + if externalID["origin"] == "AWS": |
3658 | # TODO(handle multiple IDs) |
3659 | - [marketplace_id] = externalID['IDs'] |
3660 | + [marketplace_id] = externalID["IDs"] |
3661 | break |
3662 | marketplace_id = marketplace_id.replace(MARKETPLACE_PREFIX, "") |
3663 | out, _err = util.subp( |
3664 | - ["aws", "ec2", "describe-images", "--owners", "aws-marketplace", |
3665 | - "--filters", "Name=product-code,Values={}".format(marketplace_id), |
3666 | - "--query", "sort_by(Images, &CreationDate)[-1].ImageId"] |
3667 | + [ |
3668 | + "aws", |
3669 | + "ec2", |
3670 | + "describe-images", |
3671 | + "--owners", |
3672 | + "aws-marketplace", |
3673 | + "--filters", |
3674 | + "Name=product-code,Values={}".format(marketplace_id), |
3675 | + "--query", |
3676 | + "sort_by(Images, &CreationDate)[-1].ImageId", |
3677 | + ] |
3678 | ) |
3679 | ami_id = out.strip() |
3680 | - aws_ids[release] = ami_id.replace("\"", "") |
3681 | + aws_ids[release] = ami_id.replace('"', "") |
3682 | |
3683 | os.chdir("../..") |
3684 | with open("features/aws-ids.yaml", "w") as stream: |
3685 | diff --git a/tools/run-integration-tests.py b/tools/run-integration-tests.py |
3686 | index 10b4a55..da55b1c 100644 |
3687 | --- a/tools/run-integration-tests.py |
3688 | +++ b/tools/run-integration-tests.py |
3689 | @@ -12,7 +12,6 @@ SERIES_TO_VERSION = { |
3690 | "xenial": "16.04", |
3691 | "bionic": "18.04", |
3692 | "focal": "20.04", |
3693 | - "hirsute": "21.04", |
3694 | "impish": "21.10", |
3695 | "jammy": "22.04", |
3696 | } |
3697 | @@ -28,11 +27,11 @@ PLATFORM_SERIES_TESTS = { |
3698 | "azurepro": ["xenial", "bionic", "focal"], |
3699 | "awsgeneric": ["xenial", "bionic", "focal"], |
3700 | "awspro": ["xenial", "bionic", "focal"], |
3701 | - "gcpgeneric": ["xenial", "bionic", "focal", "hirsute"], |
3702 | + "gcpgeneric": ["xenial", "bionic", "focal", "impish", "jammy"], |
3703 | "gcppro": ["xenial", "bionic", "focal"], |
3704 | "vm": ["xenial", "bionic", "focal"], |
3705 | - "lxd": ["xenial", "bionic", "focal", "hirsute", "impish", "jammy"], |
3706 | - "upgrade": ["xenial", "bionic", "focal", "hirsute", "impish"], |
3707 | + "lxd": ["xenial", "bionic", "focal", "impish", "jammy"], |
3708 | + "upgrade": ["xenial", "bionic", "focal", "impish"], |
3709 | } |
3710 | |
3711 | |
3712 | diff --git a/tox.ini b/tox.ini |
3713 | index 9c98f03..45962e0 100644 |
3714 | --- a/tox.ini |
3715 | +++ b/tox.ini |
3716 | @@ -1,20 +1,21 @@ |
3717 | [tox] |
3718 | -envlist = py3, flake8, py3-{xenial,bionic}, flake8-{trusty,xenial,bionic}, mypy, black, isort |
3719 | - |
3720 | -[testenv:flake8-trusty] |
3721 | -pip_version = 9.0.2 |
3722 | +envlist = py3, flake8, py3-{xenial,bionic}, flake8-{xenial,bionic}, mypy, black, isort |
3723 | |
3724 | [testenv:flake8-bionic] |
3725 | pip_version = 9.0.2 |
3726 | +setuptools_version = 59.8.0 |
3727 | |
3728 | [testenv:flake8-xenial] |
3729 | pip_version = 9.0.2 |
3730 | +setuptools_version = 59.8.0 |
3731 | |
3732 | [testenv:py3-xenial] |
3733 | pip_version = 9.0.2 |
3734 | +setuptools_version = 59.8.0 |
3735 | |
3736 | [testenv:py3-bionic] |
3737 | pip_version = 9.0.2 |
3738 | +setuptools_version = 59.8.0 |
3739 | |
3740 | [testenv] |
3741 | deps = |
3742 | @@ -35,8 +36,10 @@ passenv = |
3743 | setenv = |
3744 | awsgeneric: UACLIENT_BEHAVE_MACHINE_TYPE = aws.generic |
3745 | awspro: UACLIENT_BEHAVE_MACHINE_TYPE = aws.pro |
3746 | + awspro-fips: UACLIENT_BEHAVE_MACHINE_TYPE = aws.pro.fips |
3747 | azuregeneric: UACLIENT_BEHAVE_MACHINE_TYPE = azure.generic |
3748 | azurepro: UACLIENT_BEHAVE_MACHINE_TYPE = azure.pro |
3749 | + azurepro-fips: UACLIENT_BEHAVE_MACHINE_TYPE = azure.pro.fips |
3750 | gcpgeneric: UACLIENT_BEHAVE_MACHINE_TYPE = gcp.generic |
3751 | gcppro: UACLIENT_BEHAVE_MACHINE_TYPE = gcp.pro |
3752 | vm: UACLIENT_BEHAVE_MACHINE_TYPE = lxd.vm |
3753 | @@ -52,16 +55,14 @@ commands = |
3754 | behave-lxd-16.04: behave -v {posargs} --tags="uses.config.machine_type.lxd.container" --tags="series.xenial,series.lts,series.all" --tags="~upgrade" |
3755 | behave-lxd-18.04: behave -v {posargs} --tags="uses.config.machine_type.lxd.container" --tags="series.bionic,series.lts,series.all" --tags="~upgrade" |
3756 | behave-lxd-20.04: behave -v {posargs} --tags="uses.config.machine_type.lxd.container" --tags="series.focal,series.lts,series.all" --tags="~upgrade" |
3757 | - behave-lxd-21.04: behave -v {posargs} --tags="uses.config.machine_type.lxd.container" --tags="series.hirsute,series.all" --tags="~upgrade" |
3758 | behave-lxd-21.10: behave -v {posargs} --tags="uses.config.machine_type.lxd.container" --tags="series.impish,series.all" --tags="~upgrade" |
3759 | - behave-lxd-22.04: behave -v {posargs} --tags="uses.config.machine_type.lxd.container" --tags="series.jammy,series.all" --tags="~upgrade" |
3760 | + behave-lxd-22.04: behave -v {posargs} --tags="uses.config.machine_type.lxd.container" --tags="series.jammy,series.lts,series.all" --tags="~upgrade" |
3761 | behave-vm-16.04: behave -v {posargs} --tags="uses.config.machine_type.lxd.vm" --tags="series.xenial,series.all,series.lts" --tags="~upgrade" |
3762 | behave-vm-18.04: behave -v {posargs} --tags="uses.config.machine_type.lxd.vm" --tags="series.bionic,series.all,series.lts" --tags="~upgrade" |
3763 | behave-vm-20.04: behave -v {posargs} --tags="uses.config.machine_type.lxd.vm" --tags="series.focal,series.all,series.lts" --tags="~upgrade" |
3764 | behave-upgrade-16.04: behave -v {posargs} --tags="upgrade" --tags="series.xenial,series.all" |
3765 | behave-upgrade-18.04: behave -v {posargs} --tags="upgrade" --tags="series.bionic,series.all" |
3766 | behave-upgrade-20.04: behave -v {posargs} --tags="upgrade" --tags="series.focal,series.all" |
3767 | - behave-upgrade-21.04: behave -v {posargs} --tags="upgrade" --tags="series.hirsute,series.all" |
3768 | behave-upgrade-21.10: behave -v {posargs} --tags="upgrade" --tags="series.impish,series.all" |
3769 | behave-awsgeneric-16.04: behave -v {posargs} --tags="uses.config.machine_type.aws.generic" --tags="series.xenial,series.lts,series.all" --tags="~upgrade" |
3770 | behave-awsgeneric-18.04: behave -v {posargs} --tags="uses.config.machine_type.aws.generic" --tags="series.bionic,series.lts,series.all" --tags="~upgrade" |
3771 | @@ -69,16 +70,21 @@ commands = |
3772 | behave-awspro-16.04: behave -v {posargs} --tags="uses.config.machine_type.aws.pro" --tags="series.xenial,series.lts,series.all" |
3773 | behave-awspro-18.04: behave -v {posargs} --tags="uses.config.machine_type.aws.pro" --tags="series.bionic,series.lts,series.all" |
3774 | behave-awspro-20.04: behave -v {posargs} --tags="uses.config.machine_type.aws.pro" --tags="series.focal,series.lts,series.all" |
3775 | + behave-awspro-fips-16.04: behave -v {posargs} --tags="uses.config.machine_type.aws.pro.fips" --tags="series.xenial,series.lts,series.all" |
3776 | + behave-awspro-fips-18.04: behave -v {posargs} --tags="uses.config.machine_type.aws.pro.fips" --tags="series.bionic,series.lts,series.all" |
3777 | behave-azuregeneric-16.04: behave -v {posargs} --tags="uses.config.machine_type.azure.generic" --tags="series.xenial,series.lts,series.all" --tags="~upgrade" |
3778 | behave-azuregeneric-18.04: behave -v {posargs} --tags="uses.config.machine_type.azure.generic" --tags="series.bionic,series.lts,series.all" --tags="~upgrade" |
3779 | behave-azuregeneric-20.04: behave -v {posargs} --tags="uses.config.machine_type.azure.generic" --tags="series.focal,series.lts,series.all" --tags="~upgrade" |
3780 | behave-azurepro-16.04: behave -v {posargs} --tags="uses.config.machine_type.azure.pro" --tags="series.xenial,series.lts,series.all" |
3781 | behave-azurepro-18.04: behave -v {posargs} --tags="uses.config.machine_type.azure.pro" --tags="series.bionic,series.lts,series.all" |
3782 | behave-azurepro-20.04: behave -v {posargs} --tags="uses.config.machine_type.azure.pro" --tags="series.focal,series.lts,series.all" |
3783 | + behave-azurepro-fips-16.04: behave -v {posargs} --tags="uses.config.machine_type.azure.pro.fips" --tags="series.xenial,series.lts,series.all" |
3784 | + behave-azurepro-fips-18.04: behave -v {posargs} --tags="uses.config.machine_type.azure.pro.fips" --tags="series.bionic,series.lts,series.all" |
3785 | behave-gcpgeneric-16.04: behave -v {posargs} --tags="uses.config.machine_type.gcp.generic" --tags="series.xenial,series.lts,series.all" --tags="~upgrade" |
3786 | behave-gcpgeneric-18.04: behave -v {posargs} --tags="uses.config.machine_type.gcp.generic" --tags="series.bionic,series.lts,series.all" --tags="~upgrade" |
3787 | behave-gcpgeneric-20.04: behave -v {posargs} --tags="uses.config.machine_type.gcp.generic" --tags="series.focal,series.lts,series.all" --tags="~upgrade" |
3788 | - behave-gcpgeneric-21.04: behave -v {posargs} --tags="uses.config.machine_type.gcp.generic" --tags="series.hirsute,series.all" --tags="~upgrade" |
3789 | + behave-gcpgeneric-21.10: behave -v {posargs} --tags="uses.config.machine_type.gcp.generic" --tags="series.impish,series.all" --tags="~upgrade" |
3790 | + behave-gcpgeneric-22.04: behave -v {posargs} --tags="uses.config.machine_type.gcp.generic" --tags="series.jammy,series.lts,series.all" --tags="~upgrade" |
3791 | behave-gcppro-16.04: behave -v {posargs} --tags="uses.config.machine_type.gcp.pro" --tags="series.xenial,series.lts,series.all" --tags="~upgrade" |
3792 | behave-gcppro-18.04: behave -v {posargs} --tags="uses.config.machine_type.gcp.pro" --tags="series.bionic,series.lts,series.all" --tags="~upgrade" |
3793 | behave-gcppro-20.04: behave -v {posargs} --tags="uses.config.machine_type.gcp.pro" --tags="series.focal,series.lts,series.all" --tags="~upgrade" |
3794 | diff --git a/uaclient/actions.py b/uaclient/actions.py |
3795 | index ec8706f..792c5a7 100644 |
3796 | --- a/uaclient/actions.py |
3797 | +++ b/uaclient/actions.py |
3798 | @@ -1,9 +1,20 @@ |
3799 | import logging |
3800 | +import sys |
3801 | +from typing import Optional # noqa: F401 |
3802 | |
3803 | -from uaclient import clouds, config, contract, exceptions, status, util |
3804 | +from uaclient import ( |
3805 | + clouds, |
3806 | + config, |
3807 | + contract, |
3808 | + entitlements, |
3809 | + event_logger, |
3810 | + exceptions, |
3811 | + messages, |
3812 | +) |
3813 | from uaclient.clouds import identity |
3814 | |
3815 | LOG = logging.getLogger("ua.actions") |
3816 | +event = event_logger.get_event_logger() |
3817 | |
3818 | |
3819 | def attach_with_token( |
3820 | @@ -22,18 +33,20 @@ def attach_with_token( |
3821 | contract.request_updated_contract( |
3822 | cfg, token, allow_enable=allow_enable |
3823 | ) |
3824 | - except util.UrlError as exc: |
3825 | - with util.disable_log_to_console(): |
3826 | - LOG.exception(exc) |
3827 | + except exceptions.UrlError as exc: |
3828 | cfg.status() # Persist updated status in the event of partial attach |
3829 | update_apt_and_motd_messages(cfg) |
3830 | raise exc |
3831 | except exceptions.UserFacingError as exc: |
3832 | - LOG.warning(exc.msg) |
3833 | + event.info(exc.msg, file_type=sys.stderr) |
3834 | cfg.status() # Persist updated status in the event of partial attach |
3835 | update_apt_and_motd_messages(cfg) |
3836 | raise exc |
3837 | |
3838 | + current_iid = identity.get_instance_id() |
3839 | + if current_iid: |
3840 | + cfg.write_cache("instance-id", current_iid) |
3841 | + |
3842 | update_apt_and_motd_messages(cfg) |
3843 | |
3844 | |
3845 | @@ -53,16 +66,53 @@ def auto_attach( |
3846 | tokenResponse = contract_client.request_auto_attach_contract_token( |
3847 | instance=cloud |
3848 | ) |
3849 | - except contract.ContractAPIError as e: |
3850 | + except exceptions.ContractAPIError as e: |
3851 | if e.code and 400 <= e.code < 500: |
3852 | raise exceptions.NonAutoAttachImageError( |
3853 | - status.MESSAGE_UNSUPPORTED_AUTO_ATTACH |
3854 | + messages.UNSUPPORTED_AUTO_ATTACH |
3855 | ) |
3856 | raise e |
3857 | - current_iid = identity.get_instance_id() |
3858 | - if current_iid: |
3859 | - cfg.write_cache("instance-id", current_iid) |
3860 | |
3861 | token = tokenResponse["contractToken"] |
3862 | |
3863 | attach_with_token(cfg, token=token, allow_enable=True) |
3864 | + |
3865 | + |
3866 | +def enable_entitlement_by_name( |
3867 | + cfg: config.UAConfig, |
3868 | + name: str, |
3869 | + *, |
3870 | + assume_yes: bool = False, |
3871 | + allow_beta: bool = False |
3872 | +): |
3873 | + """ |
3874 | + Constructs an entitlement based on the name provided. Passes kwargs onto |
3875 | + the entitlement constructor. |
3876 | + :raise EntitlementNotFoundError: If no entitlement with the given name is |
3877 | + found, then raises this error. |
3878 | + """ |
3879 | + ent_cls = entitlements.entitlement_factory(name) |
3880 | + entitlement = ent_cls( |
3881 | + cfg, assume_yes=assume_yes, allow_beta=allow_beta, called_name=name |
3882 | + ) |
3883 | + return entitlement.enable() |
3884 | + |
3885 | + |
3886 | +def status( |
3887 | + cfg: config.UAConfig, |
3888 | + *, |
3889 | + simulate_with_token: Optional[str] = None, |
3890 | + show_beta: bool = False |
3891 | +): |
3892 | + """ |
3893 | + Construct the current UA status dictionary. |
3894 | + """ |
3895 | + if simulate_with_token: |
3896 | + status, ret = cfg.simulate_status( |
3897 | + token=simulate_with_token, show_beta=show_beta |
3898 | + ) |
3899 | + else: |
3900 | + status = cfg.status(show_beta=show_beta) |
3901 | + ret = 0 |
3902 | + |
3903 | + return status, ret |
3904 | diff --git a/uaclient/apt.py b/uaclient/apt.py |
3905 | index f6e86a7..e84d3cf 100644 |
3906 | --- a/uaclient/apt.py |
3907 | +++ b/uaclient/apt.py |
3908 | @@ -6,7 +6,7 @@ import subprocess |
3909 | import tempfile |
3910 | from typing import Dict, List, Optional |
3911 | |
3912 | -from uaclient import exceptions, gpg, status, util |
3913 | +from uaclient import event_logger, exceptions, gpg, messages, util |
3914 | |
3915 | APT_HELPER_TIMEOUT = 60.0 # 60 second timeout used for apt-helper call |
3916 | APT_AUTH_COMMENT = " # ubuntu-advantage-tools" |
3917 | @@ -27,6 +27,8 @@ APT_PROXY_CONF_FILE = "/etc/apt/apt.conf.d/90ubuntu-advantage-aptproxy" |
3918 | # Hope for an optimal first try. |
3919 | APT_RETRIES = [1.0, 5.0, 10.0] |
3920 | |
3921 | +event = event_logger.get_event_logger() |
3922 | + |
3923 | |
3924 | def assert_valid_apt_credentials(repo_url, username, password): |
3925 | """Validate apt credentials for a PPA. |
3926 | @@ -55,7 +57,7 @@ def assert_valid_apt_credentials(repo_url, username, password): |
3927 | timeout=APT_HELPER_TIMEOUT, |
3928 | retry_sleeps=APT_RETRIES, |
3929 | ) |
3930 | - except util.ProcessExecutionError as e: |
3931 | + except exceptions.ProcessExecutionError as e: |
3932 | if e.exit_code == 100: |
3933 | stderr = str(e.stderr).lower() |
3934 | if re.search(r"401\s+unauthorized|httperror401", stderr): |
3935 | @@ -80,7 +82,9 @@ def assert_valid_apt_credentials(repo_url, username, password): |
3936 | ) |
3937 | |
3938 | |
3939 | -def _parse_apt_update_for_invalid_apt_config(apt_error: str) -> str: |
3940 | +def _parse_apt_update_for_invalid_apt_config( |
3941 | + apt_error: str |
3942 | +) -> Optional[messages.NamedMessage]: |
3943 | """Parse apt update errors for invalid apt config in user machine. |
3944 | |
3945 | This functions parses apt update errors regarding the presence of |
3946 | @@ -96,9 +100,9 @@ def _parse_apt_update_for_invalid_apt_config(apt_error: str) -> str: |
3947 | message. |
3948 | |
3949 | :param apt_error: The apt error string |
3950 | - :return: a string containing the parsed error message. |
3951 | + :return: a NamedMessage containing the error message |
3952 | """ |
3953 | - error_msg = "" |
3954 | + error_msg = None |
3955 | failed_repos = set() |
3956 | |
3957 | for line in apt_error.strip().split("\n"): |
3958 | @@ -115,17 +119,18 @@ def _parse_apt_update_for_invalid_apt_config(apt_error: str) -> str: |
3959 | failed_repos.add(repo_url_match) |
3960 | |
3961 | if failed_repos: |
3962 | - error_msg += "\n" |
3963 | - error_msg += status.MESSAGE_APT_UPDATE_INVALID_URL_CONFIG.format( |
3964 | - "s" if len(failed_repos) > 1 else "", |
3965 | - "\n".join(sorted(failed_repos)), |
3966 | + error_msg = messages.APT_UPDATE_INVALID_URL_CONFIG.format( |
3967 | + plural="s" if len(failed_repos) > 1 else "", |
3968 | + failed_repos="\n".join(sorted(failed_repos)), |
3969 | ) |
3970 | |
3971 | return error_msg |
3972 | |
3973 | |
3974 | def run_apt_command( |
3975 | - cmd: List[str], error_msg: str, env: Optional[Dict[str, str]] = {} |
3976 | + cmd: List[str], |
3977 | + error_msg: Optional[str] = None, |
3978 | + env: Optional[Dict[str, str]] = {}, |
3979 | ) -> str: |
3980 | """Run an apt command, retrying upon failure APT_RETRIES times. |
3981 | |
3982 | @@ -141,18 +146,66 @@ def run_apt_command( |
3983 | out, _err = util.subp( |
3984 | cmd, capture=True, retry_sleeps=APT_RETRIES, env=env |
3985 | ) |
3986 | - except util.ProcessExecutionError as e: |
3987 | + except exceptions.ProcessExecutionError as e: |
3988 | if "Could not get lock /var/lib/dpkg/lock" in str(e.stderr): |
3989 | - error_msg += " Another process is running APT." |
3990 | + raise exceptions.APTProcessConflictError() |
3991 | else: |
3992 | """ |
3993 | Treat errors where one of the APT repositories |
3994 | is invalid or unreachable. In that situation, we alert |
3995 | which repository is causing the error |
3996 | """ |
3997 | - error_msg += _parse_apt_update_for_invalid_apt_config(e.stderr) |
3998 | + repo_error_msg = _parse_apt_update_for_invalid_apt_config(e.stderr) |
3999 | + if repo_error_msg: |
4000 | + raise exceptions.APTInvalidRepoError( |
4001 | + error_msg=repo_error_msg.msg |
4002 | + ) |
4003 | + |
4004 | + msg = error_msg if error_msg else str(e) |
4005 | + raise exceptions.UserFacingError(msg) |
4006 | + return out |
4007 | + |
4008 | + |
4009 | +def run_apt_update_command(env: Optional[Dict[str, str]] = {}) -> str: |
4010 | + try: |
4011 | + out = run_apt_command(cmd=["apt-get", "update"], env=env) |
4012 | + except exceptions.APTProcessConflictError: |
4013 | + raise exceptions.APTUpdateProcessConflictError() |
4014 | + except exceptions.APTInvalidRepoError as e: |
4015 | + raise exceptions.APTUpdateInvalidRepoError(repo_msg=e.msg) |
4016 | + except exceptions.UserFacingError as e: |
4017 | + raise exceptions.UserFacingError( |
4018 | + msg=messages.APT_UPDATE_FAILED.msg + "\n" + e.msg, |
4019 | + msg_code=messages.APT_UPDATE_FAILED.name, |
4020 | + ) |
4021 | + |
4022 | + return out |
4023 | + |
4024 | + |
4025 | +def run_apt_install_command( |
4026 | + packages: List[str], |
4027 | + apt_options: Optional[List[str]] = None, |
4028 | + error_msg: Optional[str] = None, |
4029 | + env: Optional[Dict[str, str]] = {}, |
4030 | +) -> str: |
4031 | + if apt_options is None: |
4032 | + apt_options = [] |
4033 | + |
4034 | + try: |
4035 | + out = run_apt_command( |
4036 | + cmd=["apt-get", "install", "--assume-yes"] |
4037 | + + apt_options |
4038 | + + packages, |
4039 | + error_msg=error_msg, |
4040 | + env=env, |
4041 | + ) |
4042 | + except exceptions.APTProcessConflictError: |
4043 | + raise exceptions.APTInstallProcessConflictError(header_msg=error_msg) |
4044 | + except exceptions.APTInvalidRepoError as e: |
4045 | + raise exceptions.APTInstallInvalidRepoError( |
4046 | + repo_msg=e.msg, header_msg=error_msg |
4047 | + ) |
4048 | |
4049 | - raise exceptions.UserFacingError(error_msg) |
4050 | return out |
4051 | |
4052 | |
4053 | @@ -181,7 +234,7 @@ def add_auth_apt_repo( |
4054 | # Does this system have updates suite enabled? |
4055 | updates_enabled = False |
4056 | policy = run_apt_command( |
4057 | - ["apt-cache", "policy"], status.MESSAGE_APT_POLICY_FAILED |
4058 | + ["apt-cache", "policy"], messages.APT_POLICY_FAILED.msg |
4059 | ) |
4060 | for line in policy.splitlines(): |
4061 | # We only care about $suite-updates lines |
4062 | @@ -403,7 +456,7 @@ def setup_apt_proxy( |
4063 | :return: None |
4064 | """ |
4065 | if http_proxy or https_proxy: |
4066 | - print(status.MESSAGE_SETTING_SERVICE_PROXY.format(service="APT")) |
4067 | + event.info(messages.SETTING_SERVICE_PROXY.format(service="APT")) |
4068 | |
4069 | apt_proxy_config = "" |
4070 | if http_proxy: |
4071 | @@ -413,9 +466,7 @@ def setup_apt_proxy( |
4072 | proxy_url=https_proxy |
4073 | ) |
4074 | if apt_proxy_config != "": |
4075 | - apt_proxy_config = ( |
4076 | - status.MESSAGE_APT_PROXY_CONFIG_HEADER + apt_proxy_config |
4077 | - ) |
4078 | + apt_proxy_config = messages.APT_PROXY_CONFIG_HEADER + apt_proxy_config |
4079 | |
4080 | if apt_proxy_config == "": |
4081 | util.remove_file(APT_PROXY_CONF_FILE) |
4082 | diff --git a/uaclient/cli.py b/uaclient/cli.py |
4083 | index 340516c..6af7e74 100644 |
4084 | --- a/uaclient/cli.py |
4085 | +++ b/uaclient/cli.py |
4086 | @@ -15,8 +15,7 @@ import tempfile |
4087 | import textwrap |
4088 | import time |
4089 | from functools import wraps |
4090 | -from typing import Optional # noqa: F401 |
4091 | -from typing import List, Tuple |
4092 | +from typing import List, Optional, Tuple # noqa |
4093 | |
4094 | import yaml |
4095 | |
4096 | @@ -25,9 +24,11 @@ from uaclient import ( |
4097 | config, |
4098 | contract, |
4099 | entitlements, |
4100 | + event_logger, |
4101 | exceptions, |
4102 | jobs, |
4103 | lock, |
4104 | + messages, |
4105 | security, |
4106 | security_status, |
4107 | ) |
4108 | @@ -35,6 +36,7 @@ from uaclient import status as ua_status |
4109 | from uaclient import util, version |
4110 | from uaclient.clouds import AutoAttachCloudInstance # noqa: F401 |
4111 | from uaclient.clouds import identity |
4112 | +from uaclient.data_types import AttachActionsConfigFile, IncorrectTypeError |
4113 | from uaclient.defaults import ( |
4114 | CLOUD_BUILD_INFO, |
4115 | CONFIG_FIELD_ENVVAR_ALLOWLIST, |
4116 | @@ -82,6 +84,8 @@ UA_SERVICES = ( |
4117 | "ua-license-check.timer", |
4118 | ) |
4119 | |
4120 | +event = event_logger.get_event_logger() |
4121 | + |
4122 | |
4123 | class UAArgumentParser(argparse.ArgumentParser): |
4124 | def __init__( |
4125 | @@ -128,31 +132,31 @@ class UAArgumentParser(argparse.ArgumentParser): |
4126 | |
4127 | resources = contract.get_available_resources(config.UAConfig()) |
4128 | for resource in resources: |
4129 | - ent_cls = entitlements.entitlement_factory(resource["name"]) |
4130 | - if ent_cls: |
4131 | - # Because we don't know the presentation name if unattached |
4132 | - presentation_name = resource.get( |
4133 | - "presentedAs", resource["name"] |
4134 | - ) |
4135 | - if ent_cls.help_doc_url: |
4136 | - url = " ({})".format(ent_cls.help_doc_url) |
4137 | - else: |
4138 | - url = "" |
4139 | - service_info = textwrap.fill( |
4140 | - service_info_tmpl.format( |
4141 | - name=presentation_name, |
4142 | - description=ent_cls.description, |
4143 | - url=url, |
4144 | - ), |
4145 | - width=PRINT_WRAP_WIDTH, |
4146 | - subsequent_indent=" ", |
4147 | - break_long_words=False, |
4148 | - break_on_hyphens=False, |
4149 | - ) |
4150 | - if ent_cls.is_beta: |
4151 | - beta_services_desc.append(service_info) |
4152 | - else: |
4153 | - non_beta_services_desc.append(service_info) |
4154 | + try: |
4155 | + ent_cls = entitlements.entitlement_factory(resource["name"]) |
4156 | + except exceptions.EntitlementNotFoundError: |
4157 | + continue |
4158 | + # Because we don't know the presentation name if unattached |
4159 | + presentation_name = resource.get("presentedAs", resource["name"]) |
4160 | + if ent_cls.help_doc_url: |
4161 | + url = " ({})".format(ent_cls.help_doc_url) |
4162 | + else: |
4163 | + url = "" |
4164 | + service_info = textwrap.fill( |
4165 | + service_info_tmpl.format( |
4166 | + name=presentation_name, |
4167 | + description=ent_cls.description, |
4168 | + url=url, |
4169 | + ), |
4170 | + width=PRINT_WRAP_WIDTH, |
4171 | + subsequent_indent=" ", |
4172 | + break_long_words=False, |
4173 | + break_on_hyphens=False, |
4174 | + ) |
4175 | + if ent_cls.is_beta: |
4176 | + beta_services_desc.append(service_info) |
4177 | + else: |
4178 | + non_beta_services_desc.append(service_info) |
4179 | |
4180 | return (non_beta_services_desc, beta_services_desc) |
4181 | |
4182 | @@ -179,7 +183,25 @@ def assert_root(f): |
4183 | def new_f(*args, **kwargs): |
4184 | if os.getuid() != 0: |
4185 | raise exceptions.NonRootUserError() |
4186 | - return f(*args, **kwargs) |
4187 | + else: |
4188 | + return f(*args, **kwargs) |
4189 | + |
4190 | + return new_f |
4191 | + |
4192 | + |
4193 | +def verify_json_format_args(f): |
4194 | + """Decorator to verify if correct params are used for json format""" |
4195 | + |
4196 | + @wraps(f) |
4197 | + def new_f(cmd_args, *args, **kwargs): |
4198 | + if not cmd_args: |
4199 | + return f(cmd_args, *args, **kwargs) |
4200 | + |
4201 | + if cmd_args.format == "json" and not cmd_args.assume_yes: |
4202 | + msg = messages.JSON_FORMAT_REQUIRE_ASSUME_YES |
4203 | + raise exceptions.UserFacingError(msg=msg.msg, msg_code=msg.name) |
4204 | + else: |
4205 | + return f(cmd_args, *args, **kwargs) |
4206 | |
4207 | return new_f |
4208 | |
4209 | @@ -352,6 +374,21 @@ def attach_parser(parser): |
4210 | dest="auto_enable", |
4211 | help="do not enable any recommended services automatically", |
4212 | ) |
4213 | + parser.add_argument( |
4214 | + "--attach-config", |
4215 | + type=argparse.FileType("r"), |
4216 | + help=( |
4217 | + "use the provided attach config file instead of passing the token" |
4218 | + " on the cli" |
4219 | + ), |
4220 | + ) |
4221 | + parser.add_argument( |
4222 | + "--format", |
4223 | + action="store", |
4224 | + choices=["cli", "json"], |
4225 | + default="cli", |
4226 | + help=("output enable in the specified format (default: cli)"), |
4227 | + ) |
4228 | return parser |
4229 | |
4230 | |
4231 | @@ -389,15 +426,6 @@ def security_status_parser(parser): |
4232 | choices=("json", "yaml"), |
4233 | required=True, |
4234 | ) |
4235 | - parser.add_argument( |
4236 | - "--beta", |
4237 | - help=( |
4238 | - "Acknowledge that this output is not final and may change in the" |
4239 | - " next version" |
4240 | - ), |
4241 | - action="store_true", |
4242 | - required=True, |
4243 | - ) |
4244 | return parser |
4245 | |
4246 | |
4247 | @@ -465,6 +493,13 @@ def detach_parser(parser): |
4248 | action="store_true", |
4249 | help="do not prompt for confirmation before performing the detach", |
4250 | ) |
4251 | + parser.add_argument( |
4252 | + "--format", |
4253 | + action="store", |
4254 | + choices=["cli", "json"], |
4255 | + default="cli", |
4256 | + help=("output enable in the specified format (default: cli)"), |
4257 | + ) |
4258 | return parser |
4259 | |
4260 | |
4261 | @@ -534,6 +569,13 @@ def enable_parser(parser): |
4262 | parser.add_argument( |
4263 | "--beta", action="store_true", help="allow beta service to be enabled" |
4264 | ) |
4265 | + parser.add_argument( |
4266 | + "--format", |
4267 | + action="store", |
4268 | + choices=["cli", "json"], |
4269 | + default="cli", |
4270 | + help=("output enable in the specified format (default: cli)"), |
4271 | + ) |
4272 | return parser |
4273 | |
4274 | |
4275 | @@ -561,6 +603,13 @@ def disable_parser(parser): |
4276 | action="store_true", |
4277 | help="do not prompt for confirmation before performing the disable", |
4278 | ) |
4279 | + parser.add_argument( |
4280 | + "--format", |
4281 | + action="store", |
4282 | + choices=["cli", "json"], |
4283 | + default="cli", |
4284 | + help=("output disable in the specified format (default: cli)"), |
4285 | + ) |
4286 | return parser |
4287 | |
4288 | |
4289 | @@ -643,7 +692,7 @@ def status_parser(parser): |
4290 | return parser |
4291 | |
4292 | |
4293 | -def _perform_disable(entitlement_name, cfg, *, assume_yes): |
4294 | +def _perform_disable(entitlement, cfg, *, assume_yes, update_status=True): |
4295 | """Perform the disable action on a named entitlement. |
4296 | |
4297 | :param entitlement_name: the name of the entitlement to enable |
4298 | @@ -653,10 +702,27 @@ def _perform_disable(entitlement_name, cfg, *, assume_yes): |
4299 | |
4300 | @return: True on success, False otherwise |
4301 | """ |
4302 | - ent_cls = entitlements.entitlement_factory(entitlement_name) |
4303 | - entitlement = ent_cls(cfg, assume_yes=assume_yes) |
4304 | - ret = entitlement.disable() |
4305 | - cfg.status() # Update the status cache |
4306 | + ret, reason = entitlement.disable() |
4307 | + |
4308 | + if not ret: |
4309 | + event.service_failed(entitlement.name) |
4310 | + |
4311 | + if reason is not None and isinstance( |
4312 | + reason, ua_status.CanDisableFailure |
4313 | + ): |
4314 | + if reason.message is not None: |
4315 | + event.info(reason.message.msg) |
4316 | + event.error( |
4317 | + error_msg=reason.message.msg, |
4318 | + error_code=reason.message.name, |
4319 | + service=entitlement.name, |
4320 | + ) |
4321 | + else: |
4322 | + event.service_processed(entitlement.name) |
4323 | + |
4324 | + if update_status: |
4325 | + cfg.status() # Update the status cache |
4326 | + |
4327 | return ret |
4328 | |
4329 | |
4330 | @@ -709,7 +775,7 @@ def action_config_show(args, *, cfg, **kwargs): |
4331 | raise exceptions.UserFacingError( |
4332 | textwrap.fill( |
4333 | msg, |
4334 | - width=ua_status.PRINT_WRAP_WIDTH, |
4335 | + width=PRINT_WRAP_WIDTH, |
4336 | subsequent_indent=" " * indent_position, |
4337 | ) |
4338 | ) |
4339 | @@ -844,8 +910,9 @@ def action_config_unset(args, *, cfg, **kwargs): |
4340 | return 0 |
4341 | |
4342 | |
4343 | +@verify_json_format_args |
4344 | @assert_root |
4345 | -@assert_attached(ua_status.MESSAGE_ENABLE_FAILURE_UNATTACHED_TMPL) |
4346 | +@assert_attached(messages.ENABLE_FAILURE_UNATTACHED) |
4347 | @assert_lock_file("ua disable") |
4348 | def action_disable(args, *, cfg, **kwargs): |
4349 | """Perform the disable action on a list of entitlements. |
4350 | @@ -856,11 +923,13 @@ def action_disable(args, *, cfg, **kwargs): |
4351 | entitlements_found, entitlements_not_found = get_valid_entitlement_names( |
4352 | names |
4353 | ) |
4354 | - tmpl = ua_status.MESSAGE_INVALID_SERVICE_OP_FAILURE_TMPL |
4355 | ret = True |
4356 | |
4357 | - for entitlement in entitlements_found: |
4358 | - ret &= _perform_disable(entitlement, cfg, assume_yes=args.assume_yes) |
4359 | + for ent_name in entitlements_found: |
4360 | + ent_cls = entitlements.entitlement_factory(ent_name) |
4361 | + ent = ent_cls(cfg, assume_yes=args.assume_yes) |
4362 | + |
4363 | + ret &= _perform_disable(ent, cfg, assume_yes=args.assume_yes) |
4364 | |
4365 | if entitlements_not_found: |
4366 | valid_names = ( |
4367 | @@ -876,50 +945,68 @@ def action_disable(args, *, cfg, **kwargs): |
4368 | break_on_hyphens=False, |
4369 | ) |
4370 | ) |
4371 | - raise exceptions.UserFacingError( |
4372 | - tmpl.format( |
4373 | - operation="disable", |
4374 | - name=", ".join(entitlements_not_found), |
4375 | - service_msg=service_msg, |
4376 | - ) |
4377 | + raise exceptions.InvalidServiceToDisableError( |
4378 | + operation="disable", |
4379 | + name=", ".join(entitlements_not_found), |
4380 | + service_msg=service_msg, |
4381 | ) |
4382 | |
4383 | + event.process_events() |
4384 | return 0 if ret else 1 |
4385 | |
4386 | |
4387 | +def _create_enable_entitlements_not_found_message( |
4388 | + entitlements_not_found, *, allow_beta: bool |
4389 | +) -> messages.NamedMessage: |
4390 | + """ |
4391 | + Constructs the MESSAGE_INVALID_SERVICE_OP_FAILURE message |
4392 | + based on the attempted services and valid services. |
4393 | + """ |
4394 | + valid_services_names = entitlements.valid_services(allow_beta=allow_beta) |
4395 | + valid_names = ", ".join(valid_services_names) |
4396 | + service_msg = "\n".join( |
4397 | + textwrap.wrap( |
4398 | + "Try " + valid_names + ".", |
4399 | + width=80, |
4400 | + break_long_words=False, |
4401 | + break_on_hyphens=False, |
4402 | + ) |
4403 | + ) |
4404 | + |
4405 | + return messages.INVALID_SERVICE_OP_FAILURE.format( |
4406 | + operation="enable", |
4407 | + name=", ".join(entitlements_not_found), |
4408 | + service_msg=service_msg, |
4409 | + ) |
4410 | + |
4411 | + |
4412 | +@verify_json_format_args |
4413 | @assert_root |
4414 | -@assert_attached(ua_status.MESSAGE_ENABLE_FAILURE_UNATTACHED_TMPL) |
4415 | +@assert_attached(messages.ENABLE_FAILURE_UNATTACHED) |
4416 | @assert_lock_file("ua enable") |
4417 | def action_enable(args, *, cfg, **kwargs): |
4418 | """Perform the enable action on a named entitlement. |
4419 | |
4420 | @return: 0 on success, 1 otherwise |
4421 | """ |
4422 | - print(ua_status.MESSAGE_REFRESH_CONTRACT_ENABLE) |
4423 | + event.info(messages.REFRESH_CONTRACT_ENABLE) |
4424 | try: |
4425 | contract.request_updated_contract(cfg) |
4426 | - except (util.UrlError, exceptions.UserFacingError): |
4427 | + except (exceptions.UrlError, exceptions.UserFacingError): |
4428 | # Inability to refresh is not a critical issue during enable |
4429 | - logging.debug( |
4430 | - ua_status.MESSAGE_REFRESH_CONTRACT_FAILURE, exc_info=True |
4431 | - ) |
4432 | + logging.debug(messages.REFRESH_CONTRACT_FAILURE, exc_info=True) |
4433 | + event.warning(warning_msg=messages.REFRESH_CONTRACT_FAILURE) |
4434 | |
4435 | names = getattr(args, "service", []) |
4436 | entitlements_found, entitlements_not_found = get_valid_entitlement_names( |
4437 | names |
4438 | ) |
4439 | - valid_services_names = entitlements.valid_services(allow_beta=args.beta) |
4440 | ret = True |
4441 | for ent_name in entitlements_found: |
4442 | try: |
4443 | - ent_cls = entitlements.entitlement_factory(ent_name) |
4444 | - entitlement = ent_cls( |
4445 | - cfg, |
4446 | - assume_yes=args.assume_yes, |
4447 | - allow_beta=args.beta, |
4448 | - called_name=ent_name, |
4449 | + ent_ret, reason = actions.enable_entitlement_by_name( |
4450 | + cfg, ent_name, assume_yes=args.assume_yes, allow_beta=args.beta |
4451 | ) |
4452 | - ent_ret, reason = entitlement.enable() |
4453 | cfg.status() # Update the status cache |
4454 | |
4455 | if ( |
4456 | @@ -928,39 +1015,41 @@ def action_enable(args, *, cfg, **kwargs): |
4457 | and isinstance(reason, ua_status.CanEnableFailure) |
4458 | ): |
4459 | if reason.message is not None: |
4460 | - print(reason.message) |
4461 | + event.info(reason.message.msg) |
4462 | + event.error( |
4463 | + error_msg=reason.message.msg, |
4464 | + error_code=reason.message.name, |
4465 | + service=ent_name, |
4466 | + ) |
4467 | if reason.reason == ua_status.CanEnableFailureReason.IS_BETA: |
4468 | # if we failed because ent is in beta and there was no |
4469 | # allow_beta flag/config, pretend it doesn't exist |
4470 | entitlements_not_found.append(ent_name) |
4471 | + elif ent_ret: |
4472 | + event.service_processed(service=ent_name) |
4473 | + elif not ent_ret and reason is None: |
4474 | + event.service_failed(service=ent_name) |
4475 | |
4476 | ret &= ent_ret |
4477 | except exceptions.UserFacingError as e: |
4478 | - print(e) |
4479 | + event.info(e.msg) |
4480 | + event.error( |
4481 | + error_msg=e.msg, error_code=e.msg_code, service=ent_name |
4482 | + ) |
4483 | ret = False |
4484 | |
4485 | if entitlements_not_found: |
4486 | - valid_names = ", ".join(valid_services_names) |
4487 | - service_msg = "\n".join( |
4488 | - textwrap.wrap( |
4489 | - "Try " + valid_names + ".", |
4490 | - width=80, |
4491 | - break_long_words=False, |
4492 | - break_on_hyphens=False, |
4493 | - ) |
4494 | - ) |
4495 | - tmpl = ua_status.MESSAGE_INVALID_SERVICE_OP_FAILURE_TMPL |
4496 | - raise exceptions.UserFacingError( |
4497 | - tmpl.format( |
4498 | - operation="enable", |
4499 | - name=", ".join(entitlements_not_found), |
4500 | - service_msg=service_msg, |
4501 | - ) |
4502 | + msg = _create_enable_entitlements_not_found_message( |
4503 | + entitlements_not_found, allow_beta=args.beta |
4504 | ) |
4505 | + event.services_failed(entitlements_not_found) |
4506 | + raise exceptions.UserFacingError(msg=msg.msg, msg_code=msg.name) |
4507 | |
4508 | + event.process_events() |
4509 | return 0 if ret else 1 |
4510 | |
4511 | |
4512 | +@verify_json_format_args |
4513 | @assert_root |
4514 | @assert_attached() |
4515 | @assert_lock_file("ua detach") |
4516 | @@ -985,11 +1074,15 @@ def _detach(cfg: config.UAConfig, assume_yes: bool) -> int: |
4517 | to_disable = [] |
4518 | for ent_cls in entitlements.ENTITLEMENT_CLASSES: |
4519 | ent = ent_cls(cfg=cfg, assume_yes=assume_yes) |
4520 | - if ent.can_disable(silent=True): |
4521 | + # For detach, we should not consider that a service |
4522 | + # cannot be disabled because of dependent services, |
4523 | + # since we are going to disable all of them anyway |
4524 | + ret, _ = ent.can_disable(ignore_dependent_services=True) |
4525 | + if ret: |
4526 | to_disable.append(ent) |
4527 | |
4528 | """ |
4529 | - We will nake sure that services without dependencies are disabled first |
4530 | + We will make sure that services without dependencies are disabled first |
4531 | PS: This will only work because we have only three services with reverse |
4532 | dependencies: |
4533 | * ros: ros-updates |
4534 | @@ -1007,40 +1100,47 @@ def _detach(cfg: config.UAConfig, assume_yes: bool) -> int: |
4535 | |
4536 | if to_disable: |
4537 | suffix = "s" if len(to_disable) > 1 else "" |
4538 | - print("Detach will disable the following service{}:".format(suffix)) |
4539 | + event.info( |
4540 | + "Detach will disable the following service{}:".format(suffix) |
4541 | + ) |
4542 | for ent in to_disable: |
4543 | - print(" {}".format(ent.name)) |
4544 | + event.info(" {}".format(ent.name)) |
4545 | if not util.prompt_for_confirmation(assume_yes=assume_yes): |
4546 | return 1 |
4547 | for ent in to_disable: |
4548 | - ent.disable(silent=False) |
4549 | - contract_client = contract.UAContractClient(cfg) |
4550 | - machine_token = cfg.machine_token["machineToken"] |
4551 | - contract_id = cfg.machine_token["machineTokenInfo"]["contractInfo"]["id"] |
4552 | - contract_client.detach_machine_from_contract(machine_token, contract_id) |
4553 | + _perform_disable(ent, cfg, assume_yes=assume_yes, update_status=False) |
4554 | + |
4555 | cfg.delete_cache() |
4556 | jobs.enable_license_check_if_applicable(cfg) |
4557 | update_apt_and_motd_messages(cfg) |
4558 | - print(ua_status.MESSAGE_DETACH_SUCCESS) |
4559 | + event.info(messages.DETACH_SUCCESS) |
4560 | + event.process_events() |
4561 | return 0 |
4562 | |
4563 | |
4564 | def _post_cli_attach(cfg: config.UAConfig) -> None: |
4565 | - contract_name = cfg.machine_token["machineTokenInfo"]["contractInfo"][ |
4566 | - "name" |
4567 | - ] |
4568 | + contract_name = None |
4569 | + |
4570 | + if cfg.machine_token: |
4571 | + contract_name = ( |
4572 | + cfg.machine_token.get("machineTokenInfo", {}) |
4573 | + .get("contractInfo", {}) |
4574 | + .get("name") |
4575 | + ) |
4576 | |
4577 | if contract_name: |
4578 | - print( |
4579 | - ua_status.MESSAGE_ATTACH_SUCCESS_TMPL.format( |
4580 | - contract_name=contract_name |
4581 | - ) |
4582 | + event.info( |
4583 | + messages.ATTACH_SUCCESS_TMPL.format(contract_name=contract_name) |
4584 | ) |
4585 | else: |
4586 | - print(ua_status.MESSAGE_ATTACH_SUCCESS_NO_CONTRACT_NAME) |
4587 | + event.info(messages.ATTACH_SUCCESS_NO_CONTRACT_NAME) |
4588 | |
4589 | jobs.disable_license_check_if_applicable(cfg) |
4590 | - action_status(args=None, cfg=cfg) |
4591 | + |
4592 | + status, _ret = actions.status(cfg) |
4593 | + output = ua_status.format_tabular(status) |
4594 | + event.info(util.handle_unicode_characters(output)) |
4595 | + event.process_events() |
4596 | |
4597 | |
4598 | @assert_root |
4599 | @@ -1064,27 +1164,25 @@ def action_auto_attach(args, *, cfg): |
4600 | raise exceptions.AlreadyAttachedError(cfg) |
4601 | if isinstance(e, exceptions.CloudFactoryNoCloudError): |
4602 | raise exceptions.UserFacingError( |
4603 | - ua_status.MESSAGE_UNABLE_TO_DETERMINE_CLOUD_TYPE |
4604 | + messages.UNABLE_TO_DETERMINE_CLOUD_TYPE |
4605 | ) |
4606 | if isinstance(e, exceptions.CloudFactoryNonViableCloudError): |
4607 | - raise exceptions.UserFacingError( |
4608 | - ua_status.MESSAGE_UNSUPPORTED_AUTO_ATTACH |
4609 | - ) |
4610 | + raise exceptions.UserFacingError(messages.UNSUPPORTED_AUTO_ATTACH) |
4611 | if isinstance(e, exceptions.CloudFactoryUnsupportedCloudError): |
4612 | raise exceptions.NonAutoAttachImageError( |
4613 | - ua_status.MESSAGE_UNSUPPORTED_AUTO_ATTACH_CLOUD_TYPE.format( |
4614 | + messages.UNSUPPORTED_AUTO_ATTACH_CLOUD_TYPE.format( |
4615 | cloud_type=e.cloud_type |
4616 | ) |
4617 | ) |
4618 | # we shouldn't get here, but this is a reasonable default just in case |
4619 | raise exceptions.UserFacingError( |
4620 | - ua_status.MESSAGE_UNABLE_TO_DETERMINE_CLOUD_TYPE |
4621 | + messages.UNABLE_TO_DETERMINE_CLOUD_TYPE |
4622 | ) |
4623 | |
4624 | if not instance: |
4625 | # we shouldn't get here, but this is a reasonable default just in case |
4626 | raise exceptions.UserFacingError( |
4627 | - ua_status.MESSAGE_UNABLE_TO_DETERMINE_CLOUD_TYPE |
4628 | + messages.UNABLE_TO_DETERMINE_CLOUD_TYPE |
4629 | ) |
4630 | |
4631 | current_iid = identity.get_instance_id() |
4632 | @@ -1095,13 +1193,13 @@ def action_auto_attach(args, *, cfg): |
4633 | print("Re-attaching Ubuntu Advantage subscription on new instance") |
4634 | if _detach(cfg, assume_yes=True) != 0: |
4635 | raise exceptions.UserFacingError( |
4636 | - ua_status.MESSAGE_DETACH_AUTOMATION_FAILURE |
4637 | + messages.DETACH_AUTOMATION_FAILURE |
4638 | ) |
4639 | |
4640 | try: |
4641 | actions.auto_attach(cfg, instance) |
4642 | - except util.UrlError: |
4643 | - print(ua_status.MESSAGE_ATTACH_FAILURE) |
4644 | + except exceptions.UrlError: |
4645 | + event.info(messages.ATTACH_FAILURE) |
4646 | return 1 |
4647 | except exceptions.UserFacingError: |
4648 | return 1 |
4649 | @@ -1114,22 +1212,83 @@ def action_auto_attach(args, *, cfg): |
4650 | @assert_root |
4651 | @assert_lock_file("ua attach") |
4652 | def action_attach(args, *, cfg): |
4653 | - if not args.token: |
4654 | + if not args.token and not args.attach_config: |
4655 | raise exceptions.UserFacingError( |
4656 | - ua_status.MESSAGE_ATTACH_REQUIRES_TOKEN |
4657 | + msg=messages.ATTACH_REQUIRES_TOKEN.msg, |
4658 | + msg_code=messages.ATTACH_REQUIRES_TOKEN.name, |
4659 | ) |
4660 | - try: |
4661 | - actions.attach_with_token( |
4662 | - cfg, token=args.token, allow_enable=args.auto_enable |
4663 | + if args.token and args.attach_config: |
4664 | + raise exceptions.UserFacingError( |
4665 | + msg=messages.ATTACH_TOKEN_ARG_XOR_CONFIG.msg, |
4666 | + msg_code=messages.ATTACH_TOKEN_ARG_XOR_CONFIG.name, |
4667 | ) |
4668 | - except util.UrlError: |
4669 | - print(ua_status.MESSAGE_ATTACH_FAILURE) |
4670 | + |
4671 | + if args.token: |
4672 | + token = args.token |
4673 | + enable_services_override = None |
4674 | + else: |
4675 | + try: |
4676 | + attach_config = AttachActionsConfigFile.from_dict( |
4677 | + yaml.safe_load(args.attach_config) |
4678 | + ) |
4679 | + except IncorrectTypeError as e: |
4680 | + raise exceptions.AttachInvalidConfigFileError( |
4681 | + config_name=args.attach_config.name, error=e.msg |
4682 | + ) |
4683 | + |
4684 | + token = attach_config.token |
4685 | + enable_services_override = attach_config.enable_services |
4686 | + |
4687 | + allow_enable = args.auto_enable and enable_services_override is None |
4688 | + |
4689 | + try: |
4690 | + actions.attach_with_token(cfg, token=token, allow_enable=allow_enable) |
4691 | + except exceptions.UrlError: |
4692 | + msg = messages.ATTACH_FAILURE |
4693 | + event.info(msg.msg) |
4694 | + event.error(error_msg=msg.msg, error_code=msg.name) |
4695 | + event.process_events() |
4696 | return 1 |
4697 | - except exceptions.UserFacingError: |
4698 | + except exceptions.UserFacingError as exc: |
4699 | + event.info(exc.msg) |
4700 | + event.error(error_msg=exc.msg, error_code=exc.msg_code) |
4701 | + event.process_events() |
4702 | return 1 |
4703 | else: |
4704 | + ret = 0 |
4705 | + if enable_services_override is not None and args.auto_enable: |
4706 | + found, not_found = get_valid_entitlement_names( |
4707 | + enable_services_override |
4708 | + ) |
4709 | + for name in found: |
4710 | + ent_ret, reason = actions.enable_entitlement_by_name( |
4711 | + cfg, name, assume_yes=True, allow_beta=True |
4712 | + ) |
4713 | + if not ent_ret: |
4714 | + ret = 1 |
4715 | + if ( |
4716 | + reason is not None |
4717 | + and isinstance(reason, ua_status.CanEnableFailure) |
4718 | + and reason.message is not None |
4719 | + ): |
4720 | + event.info(reason.message.msg) |
4721 | + event.error( |
4722 | + error_msg=reason.message.msg, |
4723 | + error_code=reason.message.name, |
4724 | + service=name, |
4725 | + ) |
4726 | + else: |
4727 | + event.service_processed(name) |
4728 | + |
4729 | + if not_found: |
4730 | + msg = _create_enable_entitlements_not_found_message( |
4731 | + not_found, allow_beta=True |
4732 | + ) |
4733 | + event.info(msg.msg, file_type=sys.stderr) |
4734 | + event.error(error_msg=msg.msg, error_code=msg.name) |
4735 | + ret = 1 |
4736 | _post_cli_attach(cfg) |
4737 | - return 0 |
4738 | + return ret |
4739 | |
4740 | |
4741 | def _write_command_output_to_file( |
4742 | @@ -1138,7 +1297,7 @@ def _write_command_output_to_file( |
4743 | """Helper which runs a command and writes output or error to filename.""" |
4744 | try: |
4745 | out, _ = util.subp(cmd.split(), rcs=return_codes) |
4746 | - except util.ProcessExecutionError as e: |
4747 | + except exceptions.ProcessExecutionError as e: |
4748 | util.write_file("{}-error".format(filename), str(e)) |
4749 | else: |
4750 | util.write_file(filename, out) |
4751 | @@ -1326,26 +1485,27 @@ def action_status(args, *, cfg): |
4752 | cfg = config.UAConfig() |
4753 | show_beta = args.all if args else False |
4754 | token = args.simulate_with_token if args else None |
4755 | - if token: |
4756 | - status = cfg.simulate_status(token=token, show_beta=show_beta) |
4757 | - else: |
4758 | - status = cfg.status(show_beta=show_beta) |
4759 | active_value = ua_status.UserFacingConfigStatus.ACTIVE.value |
4760 | + |
4761 | + status, ret = actions.status( |
4762 | + cfg, simulate_with_token=token, show_beta=show_beta |
4763 | + ) |
4764 | config_active = bool(status["execution_status"] == active_value) |
4765 | + |
4766 | if args and args.wait and config_active: |
4767 | while status["execution_status"] == active_value: |
4768 | - print(".", end="") |
4769 | + event.info(".", end="") |
4770 | time.sleep(1) |
4771 | - status = cfg.status(show_beta=show_beta) |
4772 | - print("") |
4773 | - if args and args.format == "json": |
4774 | - print(ua_status.format_json_status(status)) |
4775 | - elif args and args.format == "yaml": |
4776 | - print(ua_status.format_yaml_status(status)) |
4777 | - else: |
4778 | - output = ua_status.format_tabular(status) |
4779 | - print(util.handle_unicode_characters(output)) |
4780 | - return 0 |
4781 | + status, ret = actions.status( |
4782 | + cfg, simulate_with_token=token, show_beta=show_beta |
4783 | + ) |
4784 | + event.info("") |
4785 | + |
4786 | + event.set_output_content(status) |
4787 | + output = ua_status.format_tabular(status) |
4788 | + event.info(util.handle_unicode_characters(output)) |
4789 | + event.process_events() |
4790 | + return ret |
4791 | |
4792 | |
4793 | def get_version(_args=None, _cfg=None): |
4794 | @@ -1365,23 +1525,19 @@ def _action_refresh_config(args, cfg: config.UAConfig): |
4795 | except RuntimeError as exc: |
4796 | with util.disable_log_to_console(): |
4797 | logging.exception(exc) |
4798 | - raise exceptions.UserFacingError( |
4799 | - ua_status.MESSAGE_REFRESH_CONFIG_FAILURE |
4800 | - ) |
4801 | - print(ua_status.MESSAGE_REFRESH_CONFIG_SUCCESS) |
4802 | + raise exceptions.UserFacingError(messages.REFRESH_CONFIG_FAILURE) |
4803 | + print(messages.REFRESH_CONFIG_SUCCESS) |
4804 | |
4805 | |
4806 | @assert_attached() |
4807 | def _action_refresh_contract(_args, cfg: config.UAConfig): |
4808 | try: |
4809 | contract.request_updated_contract(cfg) |
4810 | - except util.UrlError as exc: |
4811 | + except exceptions.UrlError as exc: |
4812 | with util.disable_log_to_console(): |
4813 | logging.exception(exc) |
4814 | - raise exceptions.UserFacingError( |
4815 | - ua_status.MESSAGE_REFRESH_CONTRACT_FAILURE |
4816 | - ) |
4817 | - print(ua_status.MESSAGE_REFRESH_CONTRACT_SUCCESS) |
4818 | + raise exceptions.UserFacingError(messages.REFRESH_CONTRACT_FAILURE) |
4819 | + print(messages.REFRESH_CONTRACT_SUCCESS) |
4820 | |
4821 | |
4822 | @assert_root |
4823 | @@ -1444,8 +1600,10 @@ def setup_logging(console_level, log_level, log_file=None, logger=None): |
4824 | if os.getuid() == 0: |
4825 | # Setup readable-by-root-only debug file logging if running as root |
4826 | log_file_path = pathlib.Path(log_file) |
4827 | - log_file_path.touch() |
4828 | - log_file_path.chmod(0o600) |
4829 | + |
4830 | + if not log_file_path.exists(): |
4831 | + log_file_path.touch() |
4832 | + log_file_path.chmod(0o644) |
4833 | |
4834 | file_handler = logging.FileHandler(log_file) |
4835 | file_handler.setLevel(log_level) |
4836 | @@ -1454,6 +1612,17 @@ def setup_logging(console_level, log_level, log_file=None, logger=None): |
4837 | logger.addHandler(file_handler) |
4838 | |
4839 | |
4840 | +def set_event_mode(cmd_args): |
4841 | + """Set the right event mode based on the args provided""" |
4842 | + if cmd_args.command in ("attach", "detach", "enable", "disable", "status"): |
4843 | + event.set_command(cmd_args.command) |
4844 | + if hasattr(cmd_args, "format"): |
4845 | + if cmd_args.format == "json": |
4846 | + event.set_event_mode(event_logger.EventLoggerMode.JSON) |
4847 | + if cmd_args.format == "yaml": |
4848 | + event.set_event_mode(event_logger.EventLoggerMode.YAML) |
4849 | + |
4850 | + |
4851 | def main_error_handler(func): |
4852 | def wrapper(*args, **kwargs): |
4853 | try: |
4854 | @@ -1464,40 +1633,53 @@ def main_error_handler(func): |
4855 | print("Interrupt received; exiting.", file=sys.stderr) |
4856 | lock.clear_lock_file_if_present() |
4857 | sys.exit(1) |
4858 | - except util.UrlError as exc: |
4859 | + except exceptions.UrlError as exc: |
4860 | if "CERTIFICATE_VERIFY_FAILED" in str(exc): |
4861 | - tmpl = ua_status.MESSAGE_SSL_VERIFICATION_ERROR_CA_CERTIFICATES |
4862 | + tmpl = messages.SSL_VERIFICATION_ERROR_CA_CERTIFICATES |
4863 | if util.is_installed("ca-certificates"): |
4864 | - tmpl = ( |
4865 | - ua_status.MESSAGE_SSL_VERIFICATION_ERROR_OPENSSL_CONFIG |
4866 | - ) |
4867 | - print(tmpl.format(url=exc.url), file=sys.stderr) |
4868 | + tmpl = messages.SSL_VERIFICATION_ERROR_OPENSSL_CONFIG |
4869 | + msg = tmpl.format(url=exc.url) |
4870 | + event.error(error_msg=msg.msg, error_code=msg.name) |
4871 | + event.info(info_msg=msg.msg, file_type=sys.stderr) |
4872 | else: |
4873 | with util.disable_log_to_console(): |
4874 | msg_args = {"url": exc.url, "error": exc} |
4875 | if exc.url: |
4876 | msg_tmpl = ( |
4877 | - ua_status.LOG_CONNECTIVITY_ERROR_WITH_URL_TMPL |
4878 | + messages.LOG_CONNECTIVITY_ERROR_WITH_URL_TMPL |
4879 | ) |
4880 | else: |
4881 | - msg_tmpl = ua_status.LOG_CONNECTIVITY_ERROR_TMPL |
4882 | + msg_tmpl = messages.LOG_CONNECTIVITY_ERROR_TMPL |
4883 | logging.exception(msg_tmpl.format(**msg_args)) |
4884 | - print(ua_status.MESSAGE_CONNECTIVITY_ERROR, file=sys.stderr) |
4885 | + |
4886 | + msg = messages.CONNECTIVITY_ERROR |
4887 | + event.error(error_msg=msg.msg, error_code=msg.name) |
4888 | + event.info(info_msg=msg.msg, file_type=sys.stderr) |
4889 | + |
4890 | lock.clear_lock_file_if_present() |
4891 | + event.process_events() |
4892 | sys.exit(1) |
4893 | except exceptions.UserFacingError as exc: |
4894 | with util.disable_log_to_console(): |
4895 | logging.error(exc.msg) |
4896 | - print("{}".format(exc.msg), file=sys.stderr) |
4897 | + event.error(error_msg=exc.msg, error_code=exc.msg_code) |
4898 | + event.info(info_msg="{}".format(exc.msg), file_type=sys.stderr) |
4899 | if not isinstance(exc, exceptions.LockHeldError): |
4900 | # Only clear the lock if it is ours. |
4901 | lock.clear_lock_file_if_present() |
4902 | + event.process_events() |
4903 | sys.exit(exc.exit_code) |
4904 | - except Exception: |
4905 | + except Exception as e: |
4906 | with util.disable_log_to_console(): |
4907 | logging.exception("Unhandled exception, please file a bug") |
4908 | lock.clear_lock_file_if_present() |
4909 | - print(ua_status.MESSAGE_UNEXPECTED_ERROR, file=sys.stderr) |
4910 | + event.info( |
4911 | + info_msg=messages.UNEXPECTED_ERROR.msg, file_type=sys.stderr |
4912 | + ) |
4913 | + event.error( |
4914 | + error_msg=getattr(e, "msg", str(e)), error_type="exception" |
4915 | + ) |
4916 | + event.process_events() |
4917 | sys.exit(1) |
4918 | |
4919 | return wrapper |
4920 | @@ -1514,6 +1696,7 @@ def main(sys_argv=None): |
4921 | print("Try 'ua --help' for more information.") |
4922 | sys.exit(1) |
4923 | args = parser.parse_args(args=cli_arguments) |
4924 | + set_event_mode(args) |
4925 | cfg = config.UAConfig() |
4926 | |
4927 | http_proxy = cfg.http_proxy |
4928 | diff --git a/uaclient/clouds/gcp.py b/uaclient/clouds/gcp.py |
4929 | index 55f518c..c520d47 100644 |
4930 | --- a/uaclient/clouds/gcp.py |
4931 | +++ b/uaclient/clouds/gcp.py |
4932 | @@ -20,6 +20,7 @@ GCP_LICENSES = { |
4933 | "xenial": "8045211386737108299", |
4934 | "bionic": "6022427724719891830", |
4935 | "focal": "599959289349842382", |
4936 | + "jammy": "2592866803419978320", |
4937 | } |
4938 | |
4939 | |
4940 | diff --git a/uaclient/clouds/identity.py b/uaclient/clouds/identity.py |
4941 | index cd8f7b4..7542d35 100644 |
4942 | --- a/uaclient/clouds/identity.py |
4943 | +++ b/uaclient/clouds/identity.py |
4944 | @@ -30,7 +30,7 @@ def get_instance_id() -> Optional[str]: |
4945 | # Present in cloud-init on >= Xenial |
4946 | out, _err = util.subp(["cloud-init", "query", "instance_id"]) |
4947 | return out.strip() |
4948 | - except util.ProcessExecutionError: |
4949 | + except exceptions.ProcessExecutionError: |
4950 | pass |
4951 | logging.warning("Unable to determine current instance-id") |
4952 | return None |
4953 | @@ -43,7 +43,7 @@ def get_cloud_type() -> Tuple[Optional[str], Optional[NoCloudTypeReason]]: |
4954 | try: |
4955 | out, _err = util.subp(["cloud-id"]) |
4956 | return (out.strip(), None) |
4957 | - except util.ProcessExecutionError: |
4958 | + except exceptions.ProcessExecutionError: |
4959 | return (None, NoCloudTypeReason.CLOUD_ID_ERROR) |
4960 | # If no cloud-id command, assume not on cloud |
4961 | return (None, NoCloudTypeReason.NO_CLOUD_DETECTED) |
4962 | diff --git a/uaclient/clouds/tests/test_aws.py b/uaclient/clouds/tests/test_aws.py |
4963 | index d319427..9063994 100644 |
4964 | --- a/uaclient/clouds/tests/test_aws.py |
4965 | +++ b/uaclient/clouds/tests/test_aws.py |
4966 | @@ -6,6 +6,7 @@ from urllib.error import HTTPError |
4967 | import mock |
4968 | import pytest |
4969 | |
4970 | +from uaclient import exceptions |
4971 | from uaclient.clouds.aws import ( |
4972 | AWS_TOKEN_PUT_HEADER, |
4973 | AWS_TOKEN_REQ_HEADER, |
4974 | @@ -16,7 +17,6 @@ from uaclient.clouds.aws import ( |
4975 | IMDS_V2_TOKEN_URL, |
4976 | UAAutoAttachAWSInstance, |
4977 | ) |
4978 | -from uaclient.exceptions import UserFacingError |
4979 | |
4980 | M_PATH = "uaclient.clouds.aws." |
4981 | |
4982 | @@ -274,7 +274,9 @@ class TestUAAutoAttachAWSInstance: |
4983 | "No valid AWS IMDS endpoint discovered at " |
4984 | "addresses: {}, {}".format(IMDS_IPV4_ADDRESS, IMDS_IPV6_ADDRESS) |
4985 | ) |
4986 | - with pytest.raises(UserFacingError, match=re.escape(expected_error)): |
4987 | + with pytest.raises( |
4988 | + exceptions.UserFacingError, match=re.escape(expected_error) |
4989 | + ): |
4990 | instance.identity_doc |
4991 | |
4992 | expected = [ |
4993 | diff --git a/uaclient/clouds/tests/test_identity.py b/uaclient/clouds/tests/test_identity.py |
4994 | index f223f80..a21efee 100644 |
4995 | --- a/uaclient/clouds/tests/test_identity.py |
4996 | +++ b/uaclient/clouds/tests/test_identity.py |
4997 | @@ -1,18 +1,13 @@ |
4998 | import mock |
4999 | import pytest |
5000 |
Looking at this as packaging for a normal new upstream release: this is fine. Packaging changes are small, the only delicate bit is the handling of the log file permissions, which is now partially handled by logrotate. If logrotate isn't installed the logs will stay non-user-readable, which is a good compromise. Lintian complains hard about E: missing- build-dependenc y-for-dh- addon, but the dh-systemd B-D is present as an "OR" dependency, which lintian doesn't resolve, so this is a false positive. We may want to override this, but it's not a blocker for uploading. The other Lintian warning are due to deliberate choices.
Looking at this upload from the FFe/SRU perspective: this also looks good to me. More specifically the changes are
- Bug fixes;
- New functionality, extending existing functionality
in a non-breaking way;
- Documentation changes.
A binary debdiff shows that ubuntu- advantage- tools_27. 7~22.04. 1_amd64. deb ships the following new files wrt 27.6~22.04.1:
Files in second .deb but not in first ------- ------- ------- ------- -- python3/ dist-packages/ uaclient/ data_types. py python3/ dist-packages/ uaclient/ event_logger. py python3/ dist-packages/ uaclient/ messages. py
-------
-rw-r--r-- root/root /usr/lib/
-rw-r--r-- root/root /usr/lib/
-rw-r--r-- root/root /usr/lib/
These are expected and part of the aforementioned new functionality.
I think this is ready for the "second pass" review from a SRU team member.