Merge ~chad.smith/ubuntu/+source/ubuntu-advantage-tools:upload-release-26 into ubuntu/+source/ubuntu-advantage-tools:ubuntu/devel
- Git
- lp:~chad.smith/ubuntu/+source/ubuntu-advantage-tools
- upload-release-26
- Merge into ubuntu/devel
Status: | Merged |
---|---|
Merged at revision: | 83975b05565e50fa8fc8efc315c7d09babbd5f0a |
Proposed branch: | ~chad.smith/ubuntu/+source/ubuntu-advantage-tools:upload-release-26 |
Merge into: | ubuntu/+source/ubuntu-advantage-tools:ubuntu/devel |
Diff against target: |
18644 lines (+13502/-1203) 107 files modified
.github/PULL_REQUEST_TEMPLATE.md (+33/-0) .gitignore (+24/-0) Jenkinsfile (+263/-0) Makefile (+7/-1) README.md (+277/-23) RELEASES.md (+63/-0) apt-hook/hook.cc (+61/-22) debian/changelog (+225/-0) debian/control (+4/-3) debian/po/POTFILES.in (+1/-0) debian/po/templates.pot (+36/-0) debian/postinst (+112/-10) debian/postrm (+4/-5) debian/prerm (+2/-2) debian/rules (+5/-7) debian/ubuntu-advantage-tools.templates (+1/-1) dev/null (+0/-7) features/attach_invalidtoken.feature (+12/-5) features/attach_validtoken.feature (+354/-9) features/attached_commands.feature (+382/-53) features/attached_enable.feature (+373/-67) features/aws-ids.yaml (+4/-0) features/azure-ids.yaml (+4/-0) features/cloud.py (+744/-0) features/environment.py (+649/-80) features/gcp-ids.yaml (+3/-0) features/staging_commands.feature (+395/-0) features/steps/steps.py (+332/-22) features/ubuntu_pro.feature (+354/-0) features/ubuntu_upgrade.feature (+71/-0) features/unattached_commands.feature (+91/-55) features/unattached_status.feature (+68/-14) features/util.py (+251/-85) help_data.yaml (+68/-0) integration-requirements.txt (+10/-0) lib/__init__.py (+0/-0) lib/reboot_cmds.py (+159/-0) lib/upgrade_lts_contract.py (+99/-0) release-upgrades.d/ubuntu-advantage-upgrades.cfg (+4/-0) setup.py (+25/-2) sru/release-25/trusty-hwe-livepatch.txt (+1787/-0) sru/release-26/xenial-enable-fips (+188/-0) systemd/ua-auto-attach.path (+9/-0) systemd/ua-auto-attach.service (+2/-2) systemd/ua-reboot-cmds.service (+13/-0) test-requirements.txt (+0/-4) tools/base_travis_integration_tests.sh (+23/-0) tools/constraints-bionic.txt (+1/-0) tools/constraints-mypy.txt (+3/-0) tools/constraints-xenial.txt (+1/-0) tools/make-release (+120/-0) tools/refresh-aws-pro-ids (+63/-0) tools/refresh-keyrings.sh (+15/-22) tools/run_aws_travis_integration_tests.sh (+22/-0) tools/run_azure_travis_integration_tests.sh (+28/-0) tools/run_lxd_travis_integration_tests.sh (+29/-0) tools/tox-lxd-runner (+89/-0) tools/ua-dev-cloud-config.yaml (+12/-0) tox.ini (+75/-8) uaclient/apt.py (+83/-17) uaclient/cli.py (+391/-58) uaclient/clouds/gcp.py (+49/-0) uaclient/clouds/identity.py (+5/-3) uaclient/clouds/tests/test_gcp.py (+104/-0) uaclient/config.py (+330/-8) uaclient/conftest.py (+5/-1) uaclient/contract.py (+122/-47) uaclient/defaults.py (+4/-1) uaclient/entitlements/__init__.py (+10/-0) uaclient/entitlements/base.py (+153/-4) uaclient/entitlements/cc.py (+23/-11) uaclient/entitlements/cis.py (+5/-3) uaclient/entitlements/esm.py (+4/-3) uaclient/entitlements/fips.py (+307/-29) uaclient/entitlements/livepatch.py (+59/-16) uaclient/entitlements/repo.py (+183/-65) uaclient/entitlements/tests/conftest.py (+8/-2) uaclient/entitlements/tests/test_base.py (+52/-0) uaclient/entitlements/tests/test_cc.py (+8/-3) uaclient/entitlements/tests/test_cis.py (+16/-8) uaclient/entitlements/tests/test_esm.py (+13/-12) uaclient/entitlements/tests/test_fips.py (+616/-131) uaclient/entitlements/tests/test_livepatch.py (+96/-6) uaclient/entitlements/tests/test_repo.py (+281/-41) uaclient/exceptions.py (+32/-0) uaclient/pip.py (+29/-0) uaclient/status.py (+108/-11) uaclient/tests/test_apt.py (+115/-24) uaclient/tests/test_cli.py (+306/-52) uaclient/tests/test_cli_attach.py (+15/-0) uaclient/tests/test_cli_auto_attach.py (+59/-1) uaclient/tests/test_cli_detach.py (+48/-16) uaclient/tests/test_cli_disable.py (+146/-14) uaclient/tests/test_cli_enable.py (+384/-9) uaclient/tests/test_cli_refresh.py (+14/-0) uaclient/tests/test_cli_status.py (+204/-12) uaclient/tests/test_config.py (+462/-19) uaclient/tests/test_contract.py (+78/-45) uaclient/tests/test_pip.py (+91/-0) uaclient/tests/test_reboot_cmds.py (+124/-0) uaclient/tests/test_status.py (+3/-0) uaclient/tests/test_upgrade_lts_contract.py (+118/-0) uaclient/tests/test_util.py (+83/-5) uaclient/tests/test_version.py (+11/-3) uaclient/util.py (+76/-7) uaclient/version.py (+16/-4) ubuntu-advantage.1 (+3/-3) |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Bryce Harrington (community) | Approve | ||
Canonical Server | Pending | ||
Review via email: mp+398470@code.launchpad.net |
Commit message
Description of the change
New upstream release of 26.1 into Hirsute.
We would like to preserve rich git commit history by adding an pkg/upload/26.1 tag
pkg/ubuntu/
Known lintian warnings in this version we plan on addressing for our 27.0 release before trying to upload to Hirsute during feature freeze[1]:
- lintian issues:
- https:/
PPA package pushed and building at https:/
local tests can be run w/ tox -e py3/mypy/flake8 and are also run on every PR against ubuntu-
Daily integration tests are also run on our Jenkins[2] (VPN needs to be active)
references:
[1] FFe bug for releasing 27.0 into hirsute in a couple weeks https:/
[2] Jenkins UA integration tests https:/
Chad Smith (chad.smith) wrote : | # |
Bryce Harrington (bryce) wrote : | # |
### Packaging Review ###
Changelog entries look great (lots and lots of changes!)
Per the RELEASES.md documentation, the version number for hirsute should rather be just '26.1'. The ~NN.04.M suffix is only used on stable series. I've updated this manually, hopefully this is ok.
Beyond that, I just spot-checked commits to ./debian/.
In running debuild -S and debuild, I notice the packaging introduces some git delta. It's all just tmp build chaff, nothing that's actually an issue, and this is not at all unusual for packages, but if you're looking to polish the packaging might be worth tidying up:
$ debuild -S
...
Changes not staged for commit:
(use "git add/rm <file>..." to update what will be committed)
(use "git restore <file>..." to discard changes in working directory)
deleted: .pytest_
deleted: .pytest_
deleted: .pytest_
$ debuild
...
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git restore <file>..." to discard changes in working directory)
modified: .pytest_
modified: .pytest_
Untracked files:
(use "git add <file>..." to include in what will be committed)
apt-hook/hook
apt-hook/
debian/files
debian/
debian/
Most likely just stuff to add to .gitignore. The .pytest_cache directory is in the .git repository, but maybe it shouldn't be?
### Autopkgtest ###
Passed without issue.
### Lintian ###
I'm ignoring the lintian errors since sounds like you plan to investigate and address in the future, but just for feedback these are the errors/warnings that showed for me:
E: ubuntu-
W: ubuntu-
W: ubuntu-
W: ubuntu-
W: ubuntu-
W: ubuntu-
W: ubuntu-
The man page core dumps happen to me for pretty much every package I do; I've never bothered to investigate and am guessing it's something quirky about my lxc environment.
### SRU text ###
I know this MP isn't an SRU, so am considering the SRU bug report just a draft, but I thought I'd give some feedback on it anyway.
"Version 27.0 will introduce the ability a new `ua fix <CVE_or_USN>` subcommand which will introspect the running system for a specific CVE or USN issue"
- I think there's a small grammar issue there. Maybe drop "ability"?
"If we block the update to ubuntu-
Preview Diff
1 | diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md |
2 | new file mode 100644 |
3 | index 0000000..1fdfc76 |
4 | --- /dev/null |
5 | +++ b/.github/PULL_REQUEST_TEMPLATE.md |
6 | @@ -0,0 +1,33 @@ |
7 | +## Proposed Commit Message |
8 | +<!-- Include a proposed commit message because all PRs can be merged in a variety of ways by the reviewer --> |
9 | + |
10 | +> summary: no more than 70 characters |
11 | +> |
12 | +> A description of what the change being made is and why it is being |
13 | +> made, if the summary line is insufficient. The blank line above is |
14 | +> required. This should be wrapped at 72 characters, but otherwise has |
15 | +> no particular length requirements. |
16 | +> |
17 | +> If you need to write multiple paragraphs, feel free. |
18 | +> |
19 | +> LP: #NNNNNNN (replace with the appropriate Launchpad bug reference if applicable) |
20 | +> Fixes: #NNNNNNN (replace with the appropriate github issue if applicable) |
21 | + |
22 | +## Test Steps |
23 | +<!-- Please include any steps necessary to verify (and reproduce if |
24 | +this is a bug fix) this change on a live deployed system, |
25 | +including any necessary configuration files, user-data, |
26 | +setup, and teardown. Scripts used may be attached directly to this PR. --> |
27 | + |
28 | +## Desired commit type:: |
29 | +<!-- put an `x` in one merge type to allow the reviewer to merge for you --> |
30 | + - [ ] Squash and merge: Using the "Proposed Commit Message" |
31 | + - [ ] Create a merge commit and use "Proposed Commit Message" |
32 | + - [ ] Rebase and merge, no merge commit, rely only on existing commit messages |
33 | + |
34 | +## Checklist: |
35 | +<!-- Go over all the following points, and put an `x` in all the boxes |
36 | +that apply. --> |
37 | + - [ ] I have updated or added any unit tests accordingly |
38 | + - [ ] I have updated or added any integration tests accordingly |
39 | + - [ ] I have updated or added any documentation accordingly |
40 | diff --git a/.gitignore b/.gitignore |
41 | new file mode 100644 |
42 | index 0000000..2b2da67 |
43 | --- /dev/null |
44 | +++ b/.gitignore |
45 | @@ -0,0 +1,24 @@ |
46 | +artifacts/* |
47 | +*debhelper* |
48 | +debian/ubuntu-advantage-tools/ |
49 | +debian/ubuntu-advantage-tools.substvars |
50 | +dev/entitlement-creds.json.* |
51 | +*.pyc |
52 | +*.pyo |
53 | +__pycache__ |
54 | +.tox |
55 | +.pybuild |
56 | +.coverage |
57 | +.cache |
58 | +*.egg-info/ |
59 | +.mypy_cache/ |
60 | + |
61 | +# Ignore artifacts generated by bddeb |
62 | +*-1~bddeb* |
63 | +ubuntu-advantage-tools_*.orig.tar.gz |
64 | +ubuntu-advantage-tools_all.deb |
65 | +ubuntu_advantage_tools.dsc |
66 | + |
67 | +# test/jenkins artifacts |
68 | +pytest_results.xml |
69 | +reports/ |
70 | diff --git a/.travis.yml b/.travis.yml |
71 | deleted file mode 100644 |
72 | index 9e571fa..0000000 |
73 | --- a/.travis.yml |
74 | +++ /dev/null |
75 | @@ -1,83 +0,0 @@ |
76 | -language: python |
77 | -dist: bionic |
78 | - |
79 | -install: |
80 | - # Required so `git describe` will definitely find a tag; see |
81 | - # https://github.com/travis-ci/travis-ci/issues/7422 |
82 | - - git fetch --unshallow |
83 | - - make testdeps |
84 | -script: |
85 | - - make test |
86 | - |
87 | -matrix: |
88 | - fast_finish: true |
89 | - include: |
90 | - - python: 3.7 |
91 | - env: TOXENV=behave |
92 | - script: |
93 | - # bionic has lxd from deb installed, remove it first to avoid |
94 | - # confusion over versions |
95 | - - sudo apt-get remove --yes --purge lxd lxd-client |
96 | - - sudo rm -Rf /var/lib/lxd |
97 | - - sudo snap install lxd |
98 | - - sudo lxd init --auto |
99 | - - sudo usermod -a -G lxd $USER |
100 | - - sg lxd -c 'make test' |
101 | - - env: |
102 | - PACKAGE_BUILD_SERIES=trusty |
103 | - install: |
104 | - - make travis-deb-install |
105 | - script: |
106 | - - make travis-deb-script |
107 | - - env: |
108 | - PACKAGE_BUILD_SERIES=xenial |
109 | - install: |
110 | - - make travis-deb-install |
111 | - script: |
112 | - - make travis-deb-script |
113 | - - env: |
114 | - PACKAGE_BUILD_SERIES=bionic |
115 | - install: |
116 | - - make travis-deb-install |
117 | - script: |
118 | - - make travis-deb-script |
119 | - - env: |
120 | - PACKAGE_BUILD_SERIES=eoan |
121 | - install: |
122 | - - make travis-deb-install |
123 | - script: |
124 | - - make travis-deb-script |
125 | - - env: |
126 | - PACKAGE_BUILD_SERIES=focal |
127 | - install: |
128 | - - make travis-deb-install |
129 | - script: |
130 | - - make travis-deb-script |
131 | - - python: 3.4 |
132 | - env: TOXENV=py3-trusty,flake8-trusty |
133 | - dist: trusty |
134 | - - python: 3.5 |
135 | - env: TOXENV=py3-xenial,flake8-xenial |
136 | - dist: xenial |
137 | - - python: 3.6 |
138 | - env: TOXENV=py3-bionic,flake8-bionic |
139 | - - python: 3.7 |
140 | - env: TOXENV=py3-eoan,flake8-eoan |
141 | - - python: 3.8 |
142 | - env: TOXENV=py3,flake8 |
143 | - - python: 3.7 |
144 | - env: TOXENV=mypy |
145 | - - python: 3.7 |
146 | - env: TOXENV=black |
147 | - allow_failures: |
148 | - - python: 3.7 |
149 | - env: TOXENV=behave |
150 | - script: |
151 | - # bionic has lxd from deb installed, remove it first to avoid |
152 | - # confusion over versions |
153 | - - sudo apt-get remove --yes --purge lxd lxd-client |
154 | - - sudo rm -Rf /var/lib/lxd |
155 | - - sudo snap install lxd |
156 | - - sudo lxd init --auto |
157 | - - sudo usermod -a -G lxd $USER |
158 | - - sg lxd -c 'make test' |
159 | diff --git a/Jenkinsfile b/Jenkinsfile |
160 | new file mode 100644 |
161 | index 0000000..ebee6f9 |
162 | --- /dev/null |
163 | +++ b/Jenkinsfile |
164 | @@ -0,0 +1,263 @@ |
165 | +pipeline { |
166 | + agent any |
167 | + |
168 | + environment { |
169 | + TMPDIR = "/tmp/$BUILD_TAG/" |
170 | + UACLIENT_BEHAVE_JENKINS_BUILD_TAG = "${BUILD_TAG}" |
171 | + UACLIENT_BEHAVE_JENKINS_CHANGE_ID = "${CHANGE_ID}" |
172 | + UACLIENT_BEHAVE_BUILD_PR=1 |
173 | + UACLIENT_BEHAVE_CONTRACT_TOKEN = credentials('ua-contract-token') |
174 | + UACLIENT_BEHAVE_AWS_ACCESS_KEY_ID = credentials('ua-aws-access-key-id') |
175 | + UACLIENT_BEHAVE_AWS_SECRET_ACCESS_KEY = credentials( |
176 | + 'ua-aws-secret-access-key' |
177 | + ) |
178 | + UACLIENT_BEHAVE_AZ_CLIENT_ID = credentials('ua-azure-client-id') |
179 | + UACLIENT_BEHAVE_AZ_CLIENT_SECRET = credentials( |
180 | + 'ua-azure-client-secret' |
181 | + ) |
182 | + UACLIENT_BEHAVE_AZ_TENANT_ID = credentials('ua-azure-tenant') |
183 | + UACLIENT_BEHAVE_AZ_SUBSCRIPTION_ID = credentials( |
184 | + 'ua-azure-subscription-id' |
185 | + ) |
186 | + UACLIENT_BEHAVE_CONTRACT_TOKEN_STAGING = credentials( |
187 | + 'ua-contract-token-staging' |
188 | + ) |
189 | + JOB_SUFFIX = sh(returnStdout: true, script: "basename ${JOB_NAME}| cut -d'-' -f2").trim() |
190 | + } |
191 | + |
192 | + stages { |
193 | + stage ('Setup Dependencies') { |
194 | + steps { |
195 | + deleteDir() |
196 | + checkout scm |
197 | + sh ''' |
198 | + python3 -m venv $TMPDIR |
199 | + . $TMPDIR/bin/activate |
200 | + pip install tox # for tox supporting --parallel--safe-build |
201 | + ''' |
202 | + } |
203 | + } |
204 | + stage ('Lint and Style') { |
205 | + parallel { |
206 | + stage("flake8") { |
207 | + steps { |
208 | + sh ''' |
209 | + set +x |
210 | + . $TMPDIR/bin/activate |
211 | + tox --parallel--safe-build -e flake8 |
212 | + ''' |
213 | + } |
214 | + } |
215 | + stage("style") { |
216 | + steps { |
217 | + sh ''' |
218 | + set +x |
219 | + . $TMPDIR/bin/activate |
220 | + tox --parallel--safe-build -e black |
221 | + ''' |
222 | + } |
223 | + } |
224 | + stage("mypy") { |
225 | + steps { |
226 | + sh ''' |
227 | + set +x |
228 | + . $TMPDIR/bin/activate |
229 | + tox --parallel--safe-build -e mypy |
230 | + ''' |
231 | + } |
232 | + } |
233 | + } |
234 | + } |
235 | + stage ('Unit Tests') { |
236 | + steps { |
237 | + sh ''' |
238 | + set +x |
239 | + . $TMPDIR/bin/activate |
240 | + tox --parallel--safe-build -e py3 |
241 | + ''' |
242 | + } |
243 | + } |
244 | + stage ('Package builds') { |
245 | + parallel { |
246 | + stage ('Package build: 14.04') { |
247 | + environment { |
248 | + BUILD_SERIES = "trusty" |
249 | + SERIES_VERSION = "14.04" |
250 | + PKG_VERSION = sh(returnStdout: true, script: "dpkg-parsechangelog --show-field Version").trim() |
251 | + NEW_PKG_VERSION = "${PKG_VERSION}~${SERIES_VERSION}~${JOB_SUFFIX}" |
252 | + ARTIFACT_DIR = "${TMPDIR}${BUILD_SERIES}" |
253 | + } |
254 | + steps { |
255 | + sh ''' |
256 | + set -x |
257 | + mkdir ${ARTIFACT_DIR} |
258 | + cp debian/changelog ${WORKSPACE}/debian/changelog-${SERIES_VERSION} |
259 | + sed -i "s/${PKG_VERSION}/${NEW_PKG_VERSION}/" ${WORKSPACE}/debian/changelog-${SERIES_VERSION} |
260 | + dpkg-source -l${WORKSPACE}/debian/changelog-${SERIES_VERSION} -b . |
261 | + sbuild --nolog --verbose --dist=${BUILD_SERIES} --no-run-lintian --append-to-version=~${SERIES_VERSION} ../ubuntu-advantage-tools*${NEW_PKG_VERSION}*dsc |
262 | + cp ./ubuntu-advantage-tools*${SERIES_VERSION}*.deb ${ARTIFACT_DIR}/ubuntu-advantage-tools-${BUILD_SERIES}.deb |
263 | + cp ./ubuntu-advantage-pro*${SERIES_VERSION}*.deb ${ARTIFACT_DIR}/ubuntu-advantage-pro-${BUILD_SERIES}.deb |
264 | + ''' |
265 | + } |
266 | + } |
267 | + stage ('Package build: 16.04') { |
268 | + environment { |
269 | + BUILD_SERIES = "xenial" |
270 | + SERIES_VERSION = "16.04" |
271 | + PKG_VERSION = sh(returnStdout: true, script: "dpkg-parsechangelog --show-field Version").trim() |
272 | + NEW_PKG_VERSION = "${PKG_VERSION}~${SERIES_VERSION}~${JOB_SUFFIX}" |
273 | + ARTIFACT_DIR = "${TMPDIR}${BUILD_SERIES}" |
274 | + } |
275 | + steps { |
276 | + sh ''' |
277 | + set -x |
278 | + mkdir ${ARTIFACT_DIR} |
279 | + cp debian/changelog ${WORKSPACE}/debian/changelog-${SERIES_VERSION} |
280 | + sed -i "s/${PKG_VERSION}/${NEW_PKG_VERSION}/" ${WORKSPACE}/debian/changelog-${SERIES_VERSION} |
281 | + dpkg-source -l${WORKSPACE}/debian/changelog-${SERIES_VERSION} -b . |
282 | + sbuild --nolog --verbose --dist=${BUILD_SERIES} --no-run-lintian --append-to-version=~${SERIES_VERSION} ../ubuntu-advantage-tools*${NEW_PKG_VERSION}*dsc |
283 | + cp ./ubuntu-advantage-tools*${SERIES_VERSION}*.deb ${ARTIFACT_DIR}/ubuntu-advantage-tools-${BUILD_SERIES}.deb |
284 | + cp ./ubuntu-advantage-pro*${SERIES_VERSION}*.deb ${ARTIFACT_DIR}/ubuntu-advantage-pro-${BUILD_SERIES}.deb |
285 | + ''' |
286 | + } |
287 | + } |
288 | + stage ('Package build: 18.04') { |
289 | + environment { |
290 | + BUILD_SERIES = "bionic" |
291 | + SERIES_VERSION = "18.04" |
292 | + PKG_VERSION = sh(returnStdout: true, script: "dpkg-parsechangelog --show-field Version").trim() |
293 | + NEW_PKG_VERSION = "${PKG_VERSION}~${SERIES_VERSION}~${JOB_SUFFIX}" |
294 | + ARTIFACT_DIR = "${TMPDIR}${BUILD_SERIES}" |
295 | + } |
296 | + steps { |
297 | + sh ''' |
298 | + set -x |
299 | + mkdir ${ARTIFACT_DIR} |
300 | + cp debian/changelog ${WORKSPACE}/debian/changelog-${SERIES_VERSION} |
301 | + sed -i "s/${PKG_VERSION}/${NEW_PKG_VERSION}/" ${WORKSPACE}/debian/changelog-${SERIES_VERSION} |
302 | + dpkg-source -l${WORKSPACE}/debian/changelog-${SERIES_VERSION} -b . |
303 | + sbuild --nolog --verbose --dist=${BUILD_SERIES} --no-run-lintian --append-to-version=~${SERIES_VERSION} ../ubuntu-advantage-tools*${NEW_PKG_VERSION}*dsc |
304 | + cp ./ubuntu-advantage-tools*${SERIES_VERSION}*.deb ${ARTIFACT_DIR}/ubuntu-advantage-tools-${BUILD_SERIES}.deb |
305 | + cp ./ubuntu-advantage-pro*${SERIES_VERSION}*.deb ${ARTIFACT_DIR}/ubuntu-advantage-pro-${BUILD_SERIES}.deb |
306 | + ''' |
307 | + } |
308 | + } |
309 | + stage ('Package build: 20.04') { |
310 | + environment { |
311 | + BUILD_SERIES = "focal" |
312 | + SERIES_VERSION = "20.04" |
313 | + PKG_VERSION = sh(returnStdout: true, script: "dpkg-parsechangelog --show-field Version").trim() |
314 | + NEW_PKG_VERSION = "${PKG_VERSION}~${SERIES_VERSION}~${JOB_SUFFIX}" |
315 | + ARTIFACT_DIR = "${TMPDIR}${BUILD_SERIES}" |
316 | + } |
317 | + steps { |
318 | + sh ''' |
319 | + set -x |
320 | + mkdir ${ARTIFACT_DIR} |
321 | + cp debian/changelog ${WORKSPACE}/debian/changelog-${SERIES_VERSION} |
322 | + sed -i "s/${PKG_VERSION}/${NEW_PKG_VERSION}/" ${WORKSPACE}/debian/changelog-${SERIES_VERSION} |
323 | + dpkg-source -l${WORKSPACE}/debian/changelog-${SERIES_VERSION} -b . |
324 | + sbuild --nolog --verbose --dist=${BUILD_SERIES} --no-run-lintian --append-to-version=~${SERIES_VERSION} ../ubuntu-advantage-tools*${NEW_PKG_VERSION}*dsc |
325 | + cp ./ubuntu-advantage-tools*${SERIES_VERSION}*.deb ${ARTIFACT_DIR}/ubuntu-advantage-tools-${BUILD_SERIES}.deb |
326 | + cp ./ubuntu-advantage-pro*${SERIES_VERSION}*.deb ${ARTIFACT_DIR}/ubuntu-advantage-pro-${BUILD_SERIES}.deb |
327 | + ''' |
328 | + } |
329 | + } |
330 | + } |
331 | + } |
332 | + stage ('Integration Tests') { |
333 | + parallel { |
334 | + stage("lxc 14.04") { |
335 | + environment { |
336 | + UACLIENT_BEHAVE_DEBS_PATH = "${TMPDIR}trusty/" |
337 | + UACLIENT_BEHAVE_ARTIFACT_DIR = "${TMPDIR}artifacts/behave-lxd-14.04" |
338 | + } |
339 | + steps { |
340 | + sh ''' |
341 | + set +x |
342 | + . $TMPDIR/bin/activate |
343 | + tox --parallel--safe-build -e behave-lxd-14.04 |
344 | + ''' |
345 | + } |
346 | + } |
347 | + stage("lxc 16.04") { |
348 | + environment { |
349 | + UACLIENT_BEHAVE_DEBS_PATH = "${TMPDIR}xenial/" |
350 | + UACLIENT_BEHAVE_ARTIFACT_DIR = "${TMPDIR}artifacts/behave-lxd-16.04" |
351 | + } |
352 | + steps { |
353 | + sh ''' |
354 | + set +x |
355 | + . $TMPDIR/bin/activate |
356 | + tox --parallel--safe-build -e behave-lxd-16.04 |
357 | + ''' |
358 | + } |
359 | + } |
360 | + stage("lxc 18.04") { |
361 | + environment { |
362 | + UACLIENT_BEHAVE_DEBS_PATH = "${TMPDIR}bionic/" |
363 | + UACLIENT_BEHAVE_ARTIFACT_DIR = "${TMPDIR}artifacts/behave-lxd-18.04" |
364 | + } |
365 | + steps { |
366 | + sh ''' |
367 | + set +x |
368 | + . $TMPDIR/bin/activate |
369 | + tox --parallel--safe-build -e behave-lxd-18.04 |
370 | + ''' |
371 | + } |
372 | + } |
373 | + stage("lxc vm 20.04") { |
374 | + environment { |
375 | + UACLIENT_BEHAVE_DEBS_PATH = "${TMPDIR}focal/" |
376 | + UACLIENT_BEHAVE_ARTIFACT_DIR = "${TMPDIR}artifacts/behave-vm-20.04" |
377 | + } |
378 | + steps { |
379 | + sh ''' |
380 | + set +x |
381 | + . $TMPDIR/bin/activate |
382 | + tox --parallel--safe-build -e behave-vm-20.04 |
383 | + ''' |
384 | + } |
385 | + } |
386 | + stage("awspro 18.04") { |
387 | + environment { |
388 | + UACLIENT_BEHAVE_DEBS_PATH = "${TMPDIR}bionic/" |
389 | + UACLIENT_BEHAVE_ARTIFACT_DIR = "${TMPDIR}artifacts/behave-awspro-18.04" |
390 | + } |
391 | + steps { |
392 | + sh ''' |
393 | + set +x |
394 | + . $TMPDIR/bin/activate |
395 | + tox --parallel--safe-build -e behave-awspro-18.04 |
396 | + ''' |
397 | + } |
398 | + } |
399 | + } |
400 | + } |
401 | + } |
402 | + post { |
403 | + always { |
404 | + script { |
405 | + try { |
406 | + sh ''' |
407 | + set +x |
408 | + DATE=`date -d 'now+1day' +%m/%d/%Y` |
409 | + git clone https://github.com/canonical/server-test-scripts.git |
410 | + python3 server-test-scripts/ubuntu-advantage-client/lxd_cleanup.py --prefix ubuntu-behave-test-$CHANGE_ID --before-date $DATE || true |
411 | + ''' |
412 | + |
413 | + junit "pytest_results.xml" |
414 | + junit "reports/*.xml" |
415 | + } catch (Exception e) { |
416 | + echo e.toString() |
417 | + currentBuild.result = 'UNSTABLE' |
418 | + } |
419 | + try { |
420 | + archiveArtifacts "/tmp/${BUILD_TAG}/artifacts/**/*" |
421 | + } catch (Exception e) { |
422 | + echo "No integration test artifacts found. Presume success." |
423 | + } |
424 | + } |
425 | + } |
426 | + } |
427 | +} |
428 | diff --git a/Makefile b/Makefile |
429 | index d52d1e0..e8ce957 100644 |
430 | --- a/Makefile |
431 | +++ b/Makefile |
432 | @@ -27,8 +27,12 @@ test: |
433 | @tox |
434 | |
435 | testdeps: |
436 | - pip install -U six |
437 | +ifneq (,$(findstring trusty,$(TOXENV))) |
438 | + @echo Pinning virtualenv to 20.0.31 on trusty because 32 breaks py3.4 |
439 | + pip install virtualenv==20.0.31 |
440 | +endif |
441 | pip install tox |
442 | + pip install tox-pip-version |
443 | |
444 | travis-deb-install: |
445 | git fetch --unshallow |
446 | @@ -48,6 +52,8 @@ travis-deb-script: |
447 | # Use this to get a new shell where we're in the sbuild group |
448 | sudo -E su ${USER} -c 'mk-sbuild ${PACKAGE_BUILD_SERIES}' |
449 | sudo -E su ${USER} -c 'sbuild --nolog --verbose --dist=${PACKAGE_BUILD_SERIES} ../ubuntu-advantage-tools*.dsc' |
450 | + cp ./ubuntu-advantage-tools*.deb ubuntu-advantage-tools-${PACKAGE_BUILD_SERIES}.deb |
451 | + cp ./ubuntu-advantage-pro*.deb ubuntu-advantage-tools-pro-${PACKAGE_BUILD_SERIES}.deb |
452 | |
453 | |
454 | .PHONY: build clean test testdeps demo |
455 | diff --git a/README.md b/README.md |
456 | index 10e88d2..c45c58b 100644 |
457 | --- a/README.md |
458 | +++ b/README.md |
459 | @@ -1,22 +1,122 @@ |
460 | # Ubuntu Advantage Client |
461 | |
462 | -[![Build Status](https://travis-ci.org/CanonicalLtd/ubuntu-advantage-client.svg?branch=master)](https://travis-ci.org/CanonicalLtd/ubuntu-advantage-client) |
463 | +[![Build Status](https://travis-ci.com/canonical/ubuntu-advantage-client.svg?branch=master)](https://travis-ci.com/github/canonical/ubuntu-advantage-client) |
464 | |
465 | The Ubuntu Advantage client provides users with a simple mechanism to |
466 | view, enable, and disable offerings from Canonical on their system. The |
467 | following entitlements are supported: |
468 | |
469 | - [Common Criteria EAL2 certification artifacts provisioning](https://ubuntu.com/cc-eal) |
470 | -- [Canonical CIS Benchmark Audit Tool](https://ubuntu.com/cis) |
471 | +- [Canonical CIS Benchmark Audit Tool](https://ubuntu.com/cis-audit) |
472 | - [Ubuntu Extended Security Maintenance](https://ubuntu.com/esm) |
473 | - [FIPS 140-2 Certified Modules](https://ubuntu.com/fips) |
474 | -- [FIPS 140-2 Non-Certified Module Updates](https://ubuntu.com/fips-updates) |
475 | +- [FIPS 140-2 Non-Certified Module Updates](https://ubuntu.com/fips) |
476 | - [Livepatch Service](https://www.ubuntu.com/livepatch) |
477 | |
478 | ## Obtaining the Client |
479 | |
480 | -The client comes pre-installed on all Ubuntu systems. Users can run the |
481 | -`ua` command to learn more or view the manpage. |
482 | +The client comes pre-installed on all Ubuntu systems in the debian packages |
483 | +`ubuntu-advantage-tools` package. Ubuntu Pro images on AWS and Azure Ubuntu Pro |
484 | +images will also contain `ubuntu-advantage-pro` which automates machine attach |
485 | +on custom AWS and Azure images. |
486 | + |
487 | +Users can manually run the `ua` command to learn more or view the manpage. |
488 | + |
489 | +## Terminology |
490 | + The following vocabulary is used to describe different aspects of the work |
491 | +Ubuntu Advantage Client performs: |
492 | + |
493 | +| Term | Meaning | |
494 | +| -------- | -------- | |
495 | +| UA Client | The python command line client represented in this ubuntu-advantage-client repository. It is installed on each Ubuntu machine and is the entry-point to enable any Ubuntu Advantage commercial service on an Ubuntu machine. | |
496 | +| Contract Server | The backend service exposing a REST API to which UA Client authenticates in order to obtain contract and commercial service information and manage which support services are active on a machine.| |
497 | +| Entitlement/Service | An Ubuntu Advantage commercial support service such as FIPS, ESM, Livepatch, CIS-Audit to which a contract may be entitled | |
498 | +| Affordance | Service-specific list of applicable architectures and Ubuntu series on which a service can run | |
499 | +| Directives | Service-specific configuration values which are applied to a service when enabling that service | |
500 | +| Obligations | Service-specific policies that must be instrumented for support of a service. Example: `enableByDefault: true` means that any attached machine **MUST** enable a service on attach | |
501 | + |
502 | + |
503 | +## Architecture |
504 | +Ubuntu Advantage client, hereafter "UA client", is python3-based command line |
505 | +utility. It provides a CLI to attach, detach, enable, |
506 | +disable and check status of support related services. |
507 | + |
508 | +The package `ubuntu-advantage-tools` also provides a C++ APT hook which helps |
509 | +advertise ESM service and available packages in MOTD and during various apt |
510 | +commands. |
511 | + |
512 | +The `ubuntu-advantage-pro` package delivers auto-attach auto-enable |
513 | +functionality via init scripts and systemd services for various cloud |
514 | +platforms. |
515 | + |
516 | +By default, Ubuntu machines are deployed in an unattached state. A machine can |
517 | +get manually or automatically attached to a specific contract by interacting |
518 | +with the Contract Server REST API. Any change in state of services or machine |
519 | +attach results in additional interactions with the Contract Server API to |
520 | +validate such operations. The contract server API is described by the |
521 | +[ua-contracts openapi spec](https://github.com/CanonicalLtd/ua-contracts/blob/develop/docs/contracts.yaml). |
522 | + |
523 | +### Attaching a machine |
524 | +Each Ubuntu SSO account holder has access to one or more contracts. To attach |
525 | +a machine to an Ubuntu Advantage contract: |
526 | + |
527 | +* An Ubuntu SSO account holder must obtain a contract token from |
528 | +https://ubuntu.com/advantage. |
529 | +* Run `sudo ua attach <contractToken>` on the machine |
530 | + - Ubuntu Pro images for AWS and Azure perform an auto-attach without tokens |
531 | +* UA Client reads config from /etc/ubuntu-advantage/uaclient.conf to obtain |
532 | + the contract_url (default: https://contracts.canonical.com) |
533 | +* UA Client POSTs to the Contract Server API @ |
534 | + <contract_url>/api/v1/context/machines/token providing the \<contractToken\> |
535 | +* The Contract Server responds with a JSON blob containing an unique machine |
536 | + token, service credentials, affordances, directives and obligations to allow |
537 | + enabling and disabling Ubuntu Advantage services |
538 | +* UA client writes the machine token API response to the root-readonly |
539 | + /var/lib/ubuntu-advantage/machine-token.json |
540 | +* UA client auto-enables any services defined with |
541 | + `obligations:{enableByDefault: true}` |
542 | + |
543 | +### Enabling a service |
544 | +Each service controlled by UA client will have a python module in |
545 | +uaclient/entitlements/\*.py which handles setup and teardown of services when |
546 | +enabled or disabled. |
547 | + |
548 | +If a contract entitles a machine to a service, `root` user can enable the |
549 | +service with `ua enable <service>`. If a service can be disabled |
550 | +`ua disabled <service>` will be permitted. |
551 | + |
552 | +The goal of the UA client is to remain simple and flexible and let the |
553 | +contracts backend drive dynamic changes in contract offerings and constraints. |
554 | +In pursuit of that goal, the UA client obtains most of it's service constraints |
555 | +from a machine token that it obtains from the Contract Server API. |
556 | + |
557 | +The UA Client is simple in that it relies on the machine token on the attached |
558 | +machine to describe whether a service is applicable for an environment and what |
559 | +configuration is required to properly enable that service. |
560 | + |
561 | +Any interactions with the Contract server API are defined as UAContractClient |
562 | +class methods in [uaclient/contract.py](uaclient/contract.py). |
563 | + |
564 | +## Directory layout |
565 | +The following describes the intent of UA client related directories: |
566 | + |
567 | + |
568 | +| File/Directory | Intent | |
569 | +| -------- | -------- | |
570 | +| ./tools | Helpful scripts used to publish, release or test various aspects of UA client | |
571 | +| ./features/ | Behave BDD integration tests for UA Client |
572 | +| ./uaclient/ | collection of python modules which will be packaged into ubuntu-advantage-tools package to deliver the UA Client CLI | |
573 | +| uaclient.entitlements | Service-specific \*Entitlement class definitions which perform enable, disable, status, and entitlement operations etc. All classes derive from base.py:UAEntitlement and many derive from repo.py:RepoEntitlement | |
574 | +| ./uaclient/cli.py | The entry-point for the command-line client |
575 | +| ./uaclient/clouds/ | Cloud-platform detection logic used in Ubuntu Pro to determine if a given should be auto-attached to a contract | |
576 | +| uaclient.contract | Module for interacting with the Contract Server API | |
577 | +| ./demo | Various stale developer scripts for setting up one-off demo environments. (Not needed often) |
578 | +| ./apt-hook/ | the C++ apt-hook delivering MOTD and apt command notifications about UA support services | |
579 | +| ./apt-conf.d/ | apt config files delivered to /etc/apt/apt-conf.d to automatically allow unattended upgrades of ESM security-related components | |
580 | +| /etc/ubuntu-advantage/uaclient.conf | Configuration file for the UA client.| |
581 | +| /var/lib/ubuntu-advantage/private | `root` read-only directory containing Contract API responses, machine-tokens and service credentials | |
582 | +| /var/log/ubuntu-advantage.log | `root` read-only log of ubuntu-advantage operations | |
583 | + |
584 | |
585 | ## Testing |
586 | |
587 | @@ -42,19 +142,49 @@ directory and consist of two parts: `.feature` files that define the |
588 | tests we want to run, and `.py` files which implement the underlying |
589 | logic for those tests. |
590 | |
591 | +By default, integration tests will do the folowing on a given cloud platform: |
592 | + * Launch an instance running latest daily image of the target Ubuntu release |
593 | + * Add the Ubuntu advantage client daily build PPA: [ppa:canonical-server/ua-client-daily](https://code.launchpad.net/~canonical-server/+archive/ubuntu/ua-client-daily) |
594 | + * Install the appropriate ubuntu-advantage-tools and ubuntu-advantage-pro deb |
595 | + * Stop the instance and snapshot it creating an updated bootable image for |
596 | + test runs |
597 | + * Launch a fresh instance based on the boot-image created and exercise tests |
598 | + |
599 | +The testing can be overridden to run using a local copy of the ubuntu-advantage-client source code instead of the daily PPA by providing the following environment variable to the behave test runner. |
600 | +```UACLIENT_BEHAVE_BUILD_PR=1``` |
601 | + |
602 | To run the tests, you can use `tox`: |
603 | |
604 | ```shell |
605 | -tox -e behave |
606 | +tox -e behave-20.04 |
607 | ``` |
608 | |
609 | or, if you just want to run a specific file, or a test within a file: |
610 | |
611 | ```shell |
612 | -tox -e behave features/unattached_commands.feature |
613 | -tox -e behave features/unattached_commands.feature:55 |
614 | +tox -e behave-20.04 features/unattached_commands.feature |
615 | +tox -e behave-20.04 features/unattached_commands.feature:55 |
616 | ``` |
617 | |
618 | +As can be seen, this will run behave tests only for release 20.04 (Focal Fossa). We are currently |
619 | +supporting 4 distinct releases: |
620 | + |
621 | +* 20.04 (Focal Fossa) |
622 | +* 18.04 (Bionic Beaver) |
623 | +* 16.04 (Xenial Xerus) |
624 | +* 14.04 (Trusty Tahr) |
625 | + |
626 | +Therefore, to change which release to run the behave tests against, just change the release version |
627 | +on the behave command. |
628 | + |
629 | +Furthermore, when developing/debugging a new scenario: |
630 | + |
631 | + 1. Add a `@wip` tag decorator on the scenario |
632 | + 2. To only run @wip scenarios run: `tox -e behave-20.04 -- -w` |
633 | + 4. If you want to use a debugger: |
634 | + a. Add ipdb to integration-requirements.txt |
635 | + b. Add ipdb.set_trace() in the code block you wish to debug |
636 | + |
637 | (If you're getting started with behave, we recommend at least reading |
638 | through [the behave |
639 | tutorial](https://behave.readthedocs.io/en/latest/tutorial.html) to get |
640 | @@ -104,25 +234,138 @@ you need to add `-D reuse_container=container_name`: |
641 | tox -e behave -D reuse_container=container_name |
642 | ``` |
643 | |
644 | +#### Integration testing on EC2 |
645 | +The following tox environments allow for testing focal on EC2: |
646 | + |
647 | +``` |
648 | + # To test ubuntu-pro-images on EC2 |
649 | + tox -e behave-awspro-20.04 |
650 | + # To test Canonical cloud images (non-ubuntu-pro) on EC2 |
651 | + tox -e behave-awsgeneric-20.04 |
652 | +``` |
653 | + |
654 | +To run the test for a different release, just update the release version string. For example, |
655 | +to run AWS pro xenial tests, you can run: |
656 | + |
657 | +``` |
658 | +tox -e behave-awspro-16.04 |
659 | +``` |
660 | + |
661 | +In order to run EC2 tests the following environment variables are required: |
662 | + - UACLIENT_BEHAVE_AWS_ACCESS_KEY_ID |
663 | + - UACLIENT_BEHAVE_AWS_SECRET_ACCESS_KEY |
664 | + |
665 | + |
666 | +To specifically run non-ubuntu pro tests using canonical cloud-images an |
667 | +additional token obtained from https://ubuntu.com/advantage needs to be set: |
668 | + - UACLIENT_BEHAVE_CONTRACT_TOKEN=<your_token> |
669 | + |
670 | +By default, the public AMIs for Ubuntu Pro testing used for each Ubuntu |
671 | +release are defined in features/aws-ids.yaml. These ami-ids are determined by |
672 | +running `./tools/refresh-aws-pro-ids`. |
673 | + |
674 | +Integration tests will read features/aws-ids.yaml to determine which default |
675 | +AMI id to use for each supported Ubuntu release. |
676 | + |
677 | +To update `features/aws-ids.yaml`, run `./tools/refresh-aws-pro-ids` and put up |
678 | +a pull request against this repo to updated that content from the ua-contracts |
679 | +marketplace definitions. |
680 | + |
681 | +* To manually run EC2 integration tests using packages from `ppa:canonical-server/ua-client-daily` provide the following environment vars: |
682 | + |
683 | +```sh |
684 | +UACLIENT_BEHAVE_AWS_ACCESS_KEY_ID=<blah> UACLIENT_BEHAVE_AWS_SECRET_KEY=<blah2> tox -e behave-awspro-20.04 |
685 | +``` |
686 | + |
687 | +* To manually run EC2 integration tests with a specific AMI Id provide the |
688 | +following environment variable to launch your specfic AMI instead of building |
689 | +a daily ubuntu-advantage-tools image. |
690 | +```sh |
691 | +UACLIENT_BEHAVE_REUSE_IMAGE=your-custom-ami tox -e behave-awspro-20.04 |
692 | +``` |
693 | + |
694 | +#### Integration testing on Azure |
695 | +The following tox environments allow for testing focal on Azure: |
696 | + |
697 | +``` |
698 | + # To test ubuntu-pro-images on EC2 |
699 | + tox -e behave-azurepro-20.04 |
700 | + # To test Canonical cloud images (non-ubuntu-pro) on EC2 |
701 | + tox -e behave-azuregeneric-20.04 |
702 | +``` |
703 | + |
704 | +To run the test for a different release, just update the release version string. For example, |
705 | +to run AWS pro xenial tests, you can run: |
706 | + |
707 | +``` |
708 | +tox -e behave-azurepro-16.04 |
709 | +``` |
710 | + |
711 | +In order to run EC2 tests the following environment variables are required: |
712 | + - UACLIENT_BEHAVE_AZ_CLIENT_ID |
713 | + - UACLIENT_BEHAVE_AZ_CLIENT_SECRET |
714 | + - UACLIENT_BEHAVE_AZ_SUBSCRIPTION_ID |
715 | + - UACLIENT_BEHAVE_AZ_TENANT_ID |
716 | + |
717 | + |
718 | +To specifically run non-ubuntu pro tests using canonical cloud-images an |
719 | +additional token obtained from https://ubuntu.com/advantage needs to be set: |
720 | + - UACLIENT_BEHAVE_CONTRACT_TOKEN=<your_token> |
721 | + |
722 | +* To manually run Azure integration tests using packages from `ppa:canonical-server/ua-client-daily` provide the following environment vars: |
723 | + |
724 | +```sh |
725 | +UACLIENT_BEHAVE_AZ_CLIENT_ID=<blah> UACLIENT_BEHAVE_AZ_CLIENT_SECRET=<blah2> UACLIENT_BEHAVE_AZ_SUBSCRIPTION_ID=<blah3> UACLIENT_BEHAVE_AZ_TENANT_ID=<blah4> tox -e behave-azurepro-20.04 |
726 | +``` |
727 | + |
728 | +* To manually run Azure integration tests with a specific Image Id provide the |
729 | +following environment variable to launch your specfic Image Id instead of building |
730 | +a daily ubuntu-advantage-tools image. |
731 | +```sh |
732 | +UACLIENT_BEHAVE_REUSE_IMAGE=your-custom-image-id tox -e behave-awspro-20.04 |
733 | +``` |
734 | + |
735 | ## Building |
736 | |
737 | -The packaging for the UA client package (ubuntu-advantage-tools) is |
738 | -in-tree, so you can build the package the way you would normally build |
739 | -a Debian package: |
740 | +Creating ubuntu-advantage-tools and ubuntu-advantage-pro is created from the |
741 | +debian/control file in this repository. You can build the |
742 | +package the way you would normally build a Debian package: |
743 | + |
744 | |
745 | ```shell |
746 | -dpkg-buildpackage |
747 | +dpkg-buildpackage -us -uc |
748 | ``` |
749 | |
750 | -or, if you want to build for a target release other than the release |
751 | -you're on, [configure sbuild](https://wiki.ubuntu.com/SimpleSbuild) and |
752 | +**Note** It will build the package with dependencies for the Ubuntu release on |
753 | +which you are building, so it's best to build in a container of kvm for the |
754 | +release you are targeting. |
755 | + |
756 | +OR, if you want to build for a target release other than the release |
757 | +you're on: |
758 | + |
759 | +### using sbuild |
760 | +[configure sbuild](https://wiki.ubuntu.com/SimpleSbuild) and |
761 | use that for the build: |
762 | |
763 | + |
764 | ```shell |
765 | debuild -S |
766 | sbuild --dist=<target> ../ubuntu-advantage-tools_*.dsc |
767 | ``` |
768 | |
769 | +### Setting up an lxc development container |
770 | +```shell |
771 | +lxc launch ubuntu-daily:trusty dev-t -c user.user-data="$(cat tools/ua-dev-cloud-config.yaml)" |
772 | +lxc exec dev-t bash |
773 | +``` |
774 | + |
775 | +### Setting up a kvm development environment with multipass |
776 | +**Note:** There is a sample procedure documented in tools/multipass.md as well. |
777 | +```shell |
778 | +multipass launch daily:focal -n dev-f --cloud-init tools/ua-dev-cloud-config.yaml |
779 | +multipass connect dev-f |
780 | +``` |
781 | + |
782 | ## Code Formatting |
783 | |
784 | The `ubuntu-advantage-client` code base is formatted using |
785 | @@ -151,15 +394,26 @@ the project, you should install them via `dev-requirements.txt`.) |
786 | On Launchpad, there is a [daily build recipe](https://code.launchpad.net/~canonical-server/+recipe/ua-client-daily), |
787 | 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). |
788 | |
789 | -## Demo |
790 | +## Remastering custom golden images based on Ubuntu PRO |
791 | |
792 | -Users can demo the client with a local backend. This can be done with |
793 | -the following: |
794 | +Vendors who wish to provide custom images based on Ubuntu PRO images can |
795 | +follow the procedure below: |
796 | |
797 | -```shell |
798 | -# Set up ua-contracts in a docker container in a bionic lxc on port 3000 |
799 | -make demo |
800 | -# Set up two clients pointing at the local contract server |
801 | -./demo/run-uaclient --series disco |
802 | -./demo/run-uaclient --series xenial -b multipass |
803 | +* Launch the Ubuntu PRO golden image |
804 | +* Customize your golden image as you see fit |
805 | +* If `ua status` shows attached, remove the UA artifacts to allow clean |
806 | + auto-attach on subsequent cloned VM launches |
807 | +```bash |
808 | +sudo ua detach |
809 | +sudo rm -rf /var/log/ubuntu-advantage.log # to remove credentials and tokens from logs |
810 | ``` |
811 | +* Remove `cloud-init` first boot artifacts so the cloned VM boot is seen as a first boot |
812 | +```bash |
813 | +sudo cloud-init clean --logs |
814 | +sudo shutdown -h now |
815 | +``` |
816 | +* Use your cloud platform to clone or snapshot this VM as a golden image |
817 | + |
818 | + |
819 | +## Releasing ubuntu-adantage-tools |
820 | +see [RELEASES.md](RELEASES.md) |
821 | diff --git a/RELEASES.md b/RELEASES.md |
822 | new file mode 100644 |
823 | index 0000000..e31dc37 |
824 | --- /dev/null |
825 | +++ b/RELEASES.md |
826 | @@ -0,0 +1,63 @@ |
827 | +# Ubuntu Advantage Client Releases |
828 | + |
829 | +## Release versioning schemes: |
830 | + |
831 | +Below are the versioning schemes used for publishing debs: |
832 | + |
833 | +| Build target | Version Format | |
834 | +| -------- | -------- | |
835 | +| Devel series upstream release | XX.YY | |
836 | +| Devel series bugfix release | XX.YY.Z~ubuntu1| |
837 | +| Stable series release | XX.YY~ubuntu1~18.04.1| |
838 | +| [Daily Build Recipe](https://code.launchpad.net/~canonical-server/+recipe/ua-client-daily) | XX.YY+<revtime>-g<commitish>~ubuntu1~18.04.1 | |
839 | +| Ubuntu PRO series release | binary copies of Daily PPA | |
840 | + |
841 | +## Supported upgrade use-cases based on version formats |
842 | + |
843 | +| Upgrade path | Version diffs | |
844 | +| LTS to LTS | 20.3~ubuntu1~14.04.1 -> 20.3~ubuntu1~16.04.1 | |
845 | +| LTS to Daily PPA | 20.3~ubuntu1~14.04.1 -> 20.3+202004011202~ubuntu1~14.04.1 | |
846 | +| Ubuntu PRO to latest <series>-updates | 20.3+202004011202~ubuntu1~14.04.1 -> 20.4~ubuntu1~14.04.1 | |
847 | +| Ubuntu PRO to Daily PPA | 20.3+202004011202~ubuntu1~14.04.1 -> 20.4+202004021202~ubuntu1~14.04.1 | |
848 | + |
849 | + |
850 | +## Devel Release Process |
851 | + |
852 | +Below is the procedure used to release ubuntu-advantage-client to an Ubuntu series: |
853 | + |
854 | + 1. git-ubuntu clone ubuntu-advantage-tools; cd ubuntu-advantage-tools |
855 | + 2. git remote add upstream git@github.com:canonical/ubuntu-advantage-client.git |
856 | + 3. git fetch upstream |
857 | + 4. git checkout upstream/release-24 |
858 | + 5. git tag -a 24.3 |
859 | + 6. git rebase --onto pkg/ubuntu/devel 24.2 24.3 |
860 | + 7. git checkout -b pkg-upload-24.3 |
861 | + 8. debuild -S |
862 | + 9. dput ppa:chad.smith/ua-client-uploads ./ubuntu-advantage-tools_24.3_source.changes |
863 | + 10. create a release tarfile/changes file using uss-tableflip's build-package script |
864 | +``` |
865 | + ./tools/make-release --series <SERIES> --ppa <PPA_URL_FOR_TEST_UPLOADS> |
866 | + # follow printed procedure for dput to test PPA, and tag the released commitish |
867 | +``` |
868 | + 11. Create a merge proposal such as [24.2 PR](https://code.launchpad.net/~chad.smith/ubuntu/+source/ubuntu-advantage-tools/+git/ubuntu-advantage-tools/+merge/385073), [24.3 PR](https://code.launchpad.net/~chad.smith/ubuntu/+source/ubuntu-advantage-tools/+git/ubuntu-advantage-tools/+merge/389745) |
869 | + 11. For SRUs: Create an "upload a new version bug" in https://bugs.launchpad.net/ubuntu/+source/ubuntu-advantage-tools/+bugs |
870 | + 12. Describe the need, provide testing PPA and describe test instructions |
871 | + 13. Ping appropriate maintainer about upload and verification |
872 | + 14. Validate tests, accept upload and ship it |
873 | + |
874 | +Previous release bugs: |
875 | +| ------- | |
876 | +| [20.3 Focal](https://bugs.launchpad.net/ubuntu/+source/ubuntu-advantage-tools/+bug/1869980) | |
877 | + |
878 | + |
879 | +## Ubuntu PRO Release Process |
880 | + |
881 | +Manually perform a binary package copy from Daily PPA to Premium PPA and notify image creators |
882 | + |
883 | + 1. [Open Daily PPA copy-package operation](https://code.launchpad.net/~canonical-server/+archive/ubuntu/ua-client-daily/+copy-packages) |
884 | + 2. Check Trusty, Xenial, Bionic package |
885 | + 3. Select Destination PPA: UA Client Premium [~canonical-server/ubuntu/ua-client-premium] |
886 | + 4. Select Destination series: The same series |
887 | + 5. Copy options: "Copy existing binaries |
888 | + 6. Click Copy packages |
889 | + 7. Notify Pro Image creatros about expected Premium PPA version (patviafore/rcj) |
890 | diff --git a/apt-hook/hook.cc b/apt-hook/hook.cc |
891 | index 56032f4..ed009de 100644 |
892 | --- a/apt-hook/hook.cc |
893 | +++ b/apt-hook/hook.cc |
894 | @@ -33,8 +33,10 @@ |
895 | #include <locale.h> |
896 | |
897 | struct result { |
898 | - int enabled_esms; |
899 | - int disabled_esms; |
900 | + int enabled_esms_i; |
901 | + int disabled_esms_i; |
902 | + int enabled_esms_a; |
903 | + int disabled_esms_a; |
904 | }; |
905 | |
906 | // Return parent pid of specified pid, using /proc (pid might be self) |
907 | @@ -122,10 +124,22 @@ static void check_esm_upgrade(pkgCache::PkgIterator pkg, pkgPolicy *policy, resu |
908 | // TODO: Just look at the origin, not pinning. |
909 | if (pf.File().Archive() != 0 && pf.File().Origin() == std::string("UbuntuESM")) |
910 | { |
911 | + // Xenial and later should not be advertising unauthenticated ESM Infra apt repos |
912 | if (policy->GetPriority(pf.File()) == -32768) |
913 | - res.disabled_esms++; |
914 | + res.disabled_esms_i++; |
915 | else |
916 | - res.enabled_esms++; |
917 | + res.enabled_esms_i++; |
918 | + |
919 | + return; |
920 | + } |
921 | + |
922 | + if (pf.File().Archive() != 0 && pf.File().Origin() == std::string("UbuntuESMApps")) |
923 | + { |
924 | + // Xenial and later should not be advertising unauthenticated ESM Apps apt repos |
925 | + if (policy->GetPriority(pf.File()) == -32768) |
926 | + res.disabled_esms_a++; |
927 | + else |
928 | + res.enabled_esms_a++; |
929 | |
930 | return; |
931 | } |
932 | @@ -187,15 +201,16 @@ int main(int argc, char *argv[]) |
933 | // assert(ppid == getppid_of("self")); |
934 | // } |
935 | assert(cmdline_eligible(make_cmdline("apt\0update\0"))); |
936 | - assert(cmdline_eligible(make_cmdline("apt-get\0update\0"))); |
937 | - assert(!cmdline_eligible(make_cmdline("apt-get\0install\0"))); |
938 | - assert(!cmdline_eligible(make_cmdline("apt\0install\0"))); |
939 | assert(!cmdline_eligible(make_cmdline("apt\0install\0"))); |
940 | assert(cmdline_eligible(make_cmdline("aptitude\0upgrade\0"))); |
941 | assert(cmdline_eligible(make_cmdline("aptitude\0update\0"))); |
942 | command_used = ""; |
943 | |
944 | - result res = {0, 0}; |
945 | + result res = {0, 0, 0, 0}; |
946 | + |
947 | + // useful for testing |
948 | + if (has_arg(argv, "test")) |
949 | + command_used = "update"; |
950 | |
951 | if (has_arg(argv, "test") || cmdline_eligible(getcmdline(getppid_of(getppid_of("self"))))) |
952 | get_update_count(res); |
953 | @@ -205,27 +220,51 @@ int main(int argc, char *argv[]) |
954 | return 1; |
955 | } |
956 | |
957 | - if (res.enabled_esms > 0 && (command_used == "update")) |
958 | + if (command_used == "update") |
959 | { |
960 | - ioprintf(std::cout, |
961 | - ngettext("%d of the updates is from UA Infrastructure ESM.", |
962 | - "%d of the updates are from UA Infrastructure ESM.", |
963 | - res.enabled_esms), |
964 | - res.enabled_esms); |
965 | - ioprintf(std::cout, "\n"); |
966 | + if (res.enabled_esms_i > 0) |
967 | + { |
968 | + ioprintf(std::cout, |
969 | + ngettext("%d of the updates is from UA Infra: ESM.", |
970 | + "%d of the updates are from UA Infra: ESM.", |
971 | + res.enabled_esms_i), |
972 | + res.enabled_esms_i); |
973 | + ioprintf(std::cout, "\n"); |
974 | + } |
975 | + if (res.enabled_esms_a > 0) |
976 | + { |
977 | + ioprintf(std::cout, |
978 | + ngettext("%d of the updates is from UA Apps: ESM.", |
979 | + "%d of the updates are from UA Apps: ESM.", |
980 | + res.enabled_esms_a), |
981 | + res.enabled_esms_a); |
982 | + ioprintf(std::cout, "\n"); |
983 | + } |
984 | } |
985 | |
986 | - if (res.disabled_esms > 0) |
987 | + if (res.disabled_esms_i > 0 || res.disabled_esms_a > 0) |
988 | { |
989 | if (command_used != "update") |
990 | std::cout << std::endl; |
991 | - ioprintf(std::cout, |
992 | - ngettext("%d additional update is available with UA Infrastructure ESM.", |
993 | - "%d additional updates are available with UA Infrastructure ESM.", |
994 | - res.disabled_esms), |
995 | - res.disabled_esms); |
996 | + if (res.disabled_esms_i > 0) |
997 | + { |
998 | + ioprintf(std::cout, |
999 | + ngettext("%d additional update is available with UA Infra: ESM.", |
1000 | + "%d additional updates are available with UA Infra: ESM.", |
1001 | + res.disabled_esms_i), |
1002 | + res.disabled_esms_i); |
1003 | + ioprintf(std::cout, "\n"); |
1004 | + } |
1005 | + if (res.disabled_esms_a > 0) |
1006 | + { |
1007 | + ioprintf(std::cout, |
1008 | + ngettext("%d additional update is available with UA Apps: ESM.", |
1009 | + "%d additional updates are available with UA Apps ESM.", |
1010 | + res.disabled_esms_a), |
1011 | + res.disabled_esms_a); |
1012 | + ioprintf(std::cout, "\n"); |
1013 | + } |
1014 | |
1015 | - ioprintf(std::cout, "\n"); |
1016 | ioprintf(std::cout, gettext("To see these additional updates run: apt list --upgradable")); |
1017 | ioprintf(std::cout, "\n"); |
1018 | ioprintf(std::cout, gettext("See https://ubuntu.com/advantage or run: sudo ua status")); |
1019 | diff --git a/debian/changelog b/debian/changelog |
1020 | index 001d980..1180c0f 100644 |
1021 | --- a/debian/changelog |
1022 | +++ b/debian/changelog |
1023 | @@ -1,3 +1,228 @@ |
1024 | +ubuntu-advantage-tools (26.1~21.04.1) hirsute; urgency=medium |
1025 | + |
1026 | + * New upstream release 26.1 |
1027 | + - contract: block detach call to contract if machine-id change |
1028 | + - docs: add readme docs about mastering clean golden images |
1029 | + - fips: add reboot notices for fips operations (GH: #1368) |
1030 | + - livepatch: add retry when running canonical-livepatch status |
1031 | + (GH: #1360) |
1032 | + - util: use lru_cache to avoid re-reading os-release and machine-id |
1033 | + (GH: #1329) |
1034 | + - tests: |
1035 | + + add disable_auto_attach config to all test PRO vms |
1036 | + + add more log artifacts during failed integration test |
1037 | + + check cloudinit status after launching image |
1038 | + + mock leaking livepatch.application_status for fips test |
1039 | + + retry package installs on apt exit 100 |
1040 | + - jenkins: parameterize build stages to avoid parallel job collision |
1041 | + |
1042 | + -- Lucas Moura <lucas.moura@canonical.com> Fri, 19 Feb 2021 10:30:22 -0300 |
1043 | + |
1044 | +ubuntu-advantage-tools (26.0.1~21.04.1) hirsute; urgency=medium |
1045 | + |
1046 | + * auto-attach: fix comparing numeric iid |
1047 | + |
1048 | + -- Lucas Moura <lucas.moura@canonical.com> Fri, 05 Feb 2021 14:10:09 -0300 |
1049 | + |
1050 | +ubuntu-advantage-tools (26.0~21.04.1) hirsute; urgency=medium |
1051 | + |
1052 | + * New upstream release 26.0: |
1053 | + - auto-attach: systemd unit to run before ua-reboot-cmds.service |
1054 | + - config: remove_notice should remove notices.json when empty |
1055 | + - fips: |
1056 | + + add notice if running a deactivated FIPS kernel (GH: #1348) |
1057 | + + block enabling FIPS on clouds using Xenial |
1058 | + + block enabling fips on GCP instances |
1059 | + + check /proc/sys/crypto/fips_enable to see if fips is enabled |
1060 | + + override fips metapackage when on bionic cloud |
1061 | + + update metapackage override logic on fips |
1062 | + - notices: clear lock file and notice when encountering any exception |
1063 | + (GH: #1326) |
1064 | + - reboot_cmds: retry on lock held errors due to pro auto-attach |
1065 | + - services: allow uaclient to disable services during enable |
1066 | + - status: include beta services in json formatted output with --all |
1067 | + (GH: #1341) |
1068 | + - tests: |
1069 | + + add FIPS tests to AWS and Azure bionic images |
1070 | + + add GCP pro test for focal machine |
1071 | + + add after_step collection of artifacts on failure |
1072 | + + remove proc file check after disabling fips |
1073 | + + pro: block auto-attach with cloud-config bootcmd |
1074 | + + add validation of systemd unit ua-reboot-cmds.service |
1075 | + + test enabling fips-updates when fips is enabled |
1076 | + - jenkins: |
1077 | + - add deb build stage to assert package builds |
1078 | + - use series-specific sbuild --build-dir avoid races |
1079 | + - use --append-to-version for each sbuild run to avoid races |
1080 | + - presume success when no integration artifacts created |
1081 | + |
1082 | + -- Lucas Moura <lucas.moura@canonical.com> Thu, 04 Feb 2021 16:34:56 -0300 |
1083 | + |
1084 | +ubuntu-advantage-tools (26.0~21.04.1~beta) hirsute; urgency=medium |
1085 | + |
1086 | + * d/rules: |
1087 | + - add --with systemd to allow reboot init script |
1088 | + - do not remove lib/systemd/system folder |
1089 | + * d/postinst: |
1090 | + - create marker file when reboot script need to run: |
1091 | + - enable livepatch across trusty to xenial upgrade |
1092 | + - update fips on existing fips pro machines |
1093 | + * New upstream release 26.0~beta: |
1094 | + - gcp: add Google Cloud Platform support (GH #1269) |
1095 | + - fips: |
1096 | + + remove is_beta from fips sevices |
1097 | + + fips pro: add upgrade support to require reboot to unmark held fips pkgs |
1098 | + + update origin UbuntuFIPSUpdates |
1099 | + - status: |
1100 | + + add notice to tabular output |
1101 | + + held locks emit notice about Operation in progress |
1102 | + - cli: help sort output so trusty ordering matches xenial++ |
1103 | + - cis: rename service from cis-audit |
1104 | + - config: provide config notices and add_notice and remove_notice methods |
1105 | + - contract: add resource-machine-access route and datapath |
1106 | + - init: add init script to run commands on reboot |
1107 | + - keys: add ubuntu-advantage-cis keyring |
1108 | + - livepatch: make livepatch react to enableByDefault delta |
1109 | + - log: log when we install pkgs because of contract delta |
1110 | + - make: drop six testdeps target |
1111 | + - pro: do not install pro debs on non-pro instances |
1112 | + - services: Update beta info for services (GH #1220) |
1113 | + - tools: add tox-lxd-runner, that execute the test command in a shell |
1114 | + - tools: refresh-keyrings handles cis keys. drop series-specific keys |
1115 | + - tests: |
1116 | + + add GCE support for integration tests |
1117 | + + add cis integration tests for unattached and pro |
1118 | + + add pytest constraint for mypy tests |
1119 | + + add unittests for reboot_cmds script |
1120 | + + fix esm package messages for new update notifier version |
1121 | + + pin importlib-metadata for mypy tests |
1122 | + + repo tests for request_resource_machine_access |
1123 | + + unit tests for config cache clearing and machine-access data |
1124 | + - jenkins: |
1125 | + + add basic Jenkinsfile for CI runs per PR |
1126 | + + add jenkins parseable test results |
1127 | + + add lxc cleanup stage on Jenkinsfile |
1128 | + |
1129 | + -- Lucas Moura <lucas.moura@canonical.com> Thu, 14 Jan 2021 10:08:20 -0300 |
1130 | + |
1131 | +ubuntu-advantage-tools (25.0~20.10.1) groovy; urgency=medium |
1132 | + |
1133 | + * Release version 25.0 |
1134 | + |
1135 | + -- Chad Smith <chad.smith@canonical.com> Fri, 04 Dec 2020 13:32:16 -0700 |
1136 | + |
1137 | +ubuntu-advantage-tools (25.0~20.10.1beta3) groovy; urgency=medium |
1138 | + |
1139 | + * New upstream release 25.0~beta3: |
1140 | + - upgrade-lts-conract: noop during do-release-upgrade on unattached |
1141 | + (GH: #1255) |
1142 | + - ua-auto-attach: order systemd unit before cloud-config.service |
1143 | + - Update FIPSUpdates pin origin |
1144 | + - fips: unmark held fips packages for ubuntu pro fips image support |
1145 | + (GH: #1109) |
1146 | + - repo: handle changes to additionalPackages contract deltas |
1147 | + - repo: move package installation to install_packages method |
1148 | + - pro: trigger auto-attach as soon as instance-data.json is available |
1149 | + (GH: #1234) |
1150 | + - Conditionally install packages when enabling FIPS |
1151 | + - fips: allow disable (GH: #1168) |
1152 | + - cli: add trailing newline to argparse errors (GH: #1236) |
1153 | + - Install fips metapacking when enabling service |
1154 | + - integration test improvements: |
1155 | + + upgrade-test: fix upgrade path restart failures on trusty (GH: #1257) |
1156 | + + Fix integration test setup scripts (GH: #1253) |
1157 | + + strict checking for command success on behave |
1158 | + + Update tests to use new pycloudlib LXD abstraction |
1159 | + + Add upgrade scenario tests when FIPS is enabled |
1160 | + + Improve FIPS tests for checking packages |
1161 | + + Update esm-infra xenial lxd test |
1162 | + + Fix vm tests as esm-apps is beta service |
1163 | + + Fix azure generic integration testing |
1164 | + + Update esm-apps check on staging_commands tests |
1165 | + + Install pycloudlib for azure jobs only |
1166 | + + Fix shell condition in run_azure_travis_integration_tests.sh |
1167 | + + Update azure jobs on travis |
1168 | + + Update travis url in README |
1169 | + + Update travis scripts to use ppa only on master |
1170 | + + Fix cron event type check on travis yaml |
1171 | + |
1172 | + -- Chad Smith <chad.smith@canonical.com> Wed, 02 Dec 2020 13:43:16 -0700 |
1173 | + |
1174 | +ubuntu-advantage-tools (25.0~20.10.1~beta2) groovy; urgency=medium |
1175 | + |
1176 | + * New upstream release 25.0~beta2: |
1177 | + - help: update esm-infra help text (GH: #1212) |
1178 | + - apt-hook: update apt cli messaging for UA Infra: ESM and UA Apps: ESM |
1179 | + product names |
1180 | + - help: update fips help docs (GH: #1213) |
1181 | + - help: revert CIS help doc URL (GH: #1211) |
1182 | + - help: add new fips help URLs to CLI help docs (GH: #1210) |
1183 | + - Show error when enabling service with invalid repo [Lucas Moura] |
1184 | + (GH: #954) |
1185 | + - Update beta info for services (#1220) [Lucas Moura] (GH: #1216) |
1186 | + - Do not enable fips when fips-updates is active [Lucas Moura] (GH: #1209) |
1187 | + - Add vm test commands in tox.ini (#1204) [Lucas Moura] |
1188 | + |
1189 | + -- Chad Smith <chad.smith@canonical.com> Mon, 26 Oct 2020 20:01:21 -0600 |
1190 | + |
1191 | +ubuntu-advantage-tools (25.0~20.10.1~beta1) groovy; urgency=medium |
1192 | + |
1193 | + * Beta bug fix release |
1194 | + - status: fix missing description_override key after upgrade from |
1195 | + trusty (GH: #1201) |
1196 | + - During contract delta processing use _check_application_status_on_cache |
1197 | + instead of live service status |
1198 | + |
1199 | + -- Chad Smith <chad.smith@canonical.com> Sat, 10 Oct 2020 21:47:21 -0600 |
1200 | + |
1201 | +ubuntu-advantage-tools (25.0~20.10.1~beta) groovy; urgency=medium |
1202 | + |
1203 | + * d/control: |
1204 | + - add po-debconf dependency and fix lintian not-using-po-debconf and |
1205 | + untranslatable-debconf-templates |
1206 | + - add ${misc:Depends} dep to ubuntu-advantage-pro to fix lintian |
1207 | + debhelper-but-no-misc-depends (GH: #1024) |
1208 | + * d/rules: |
1209 | + - drop --with systemd fix build-depends-on-obsolete-package |
1210 | + - set fix lintian warning extra:Depends even if empty |
1211 | + * d/postrm |
1212 | + - Add more gpg keys to be deleted in postrm for Xenial+ support |
1213 | + * d/postinst: |
1214 | + - do not unconfigure non-trusty esm. no series in apt filenames (GH: #1170) |
1215 | + - check if esm is already enabled (GH: #1095) |
1216 | + * New upstream release 25.0: |
1217 | + - Do not uninstall additionalPackages or livepatch when disabling services |
1218 | + - check for issubclass on clean_apt_files |
1219 | + - Add do-release-upgrade support for esm-infra and apps suites (GH: #1169) |
1220 | + - Apply contract deltas during do-release-upgrade operations |
1221 | + - cli: add ua help command |
1222 | + - cli: status add blocking --wait param and lock files for config change |
1223 | + - Fix livepatch behaviour on aws pro focal machine |
1224 | + - travis: drop inapplicable workspaces from specific awsgeneric release |
1225 | + jobs |
1226 | + - Add possible reboot text after enabling/disabling services |
1227 | + - apt-hook: package apt-hook and apt configuration files on all releases |
1228 | + (GH: #1150) |
1229 | + - Fix enable fail bug |
1230 | + - Add uaclient.conf override mechanism for auto-attach, beta services and |
1231 | + machine-token |
1232 | + - Support ESM Apps [Brian Murray] (GH: #930) |
1233 | + - Do not enable services if blocking services is active (GH: #1029) |
1234 | + - contract: handle 401 on invalid token, 403 on expired (GH: #1335) |
1235 | + - Hide beta services from default status output and enable/disable |
1236 | + operations (GH: #1079) (GH: #1091) |
1237 | + - fips: force apt noninteractive prompts during package installs |
1238 | + (GH: #1084) |
1239 | + - tests: add unit tests for aws-gov/aws-china cloud detection |
1240 | + - Add AWS China and GovCloud partitions [Robert Jennings] |
1241 | + - Disable beta services to be show/enabled without flag |
1242 | + - Add missing build_pr command to environment |
1243 | + - Use additionalPackages from service payload |
1244 | + - Add integration testing for Travis runs [patriciadomin] (GH: #856) |
1245 | + (GH: #857) (GH: #853) |
1246 | + |
1247 | + -- Chad Smith <chad.smith@canonical.com> Mon, 28 Sep 2020 21:11:54 -0600 |
1248 | + |
1249 | ubuntu-advantage-tools (24.4) groovy; urgency=medium |
1250 | |
1251 | * New bug-fix-only release 24.4: |
1252 | diff --git a/debian/control b/debian/control |
1253 | index 0fedb9c..9c3095e 100644 |
1254 | --- a/debian/control |
1255 | +++ b/debian/control |
1256 | @@ -5,16 +5,17 @@ Maintainer: Ubuntu Developers <ubuntu-devel-discuss@lists.ubuntu.com> |
1257 | Build-Depends: bash-completion, |
1258 | debhelper (>=9), |
1259 | dh-python, |
1260 | + dh-systemd, |
1261 | gettext, |
1262 | git, |
1263 | libapt-pkg-dev, |
1264 | + po-debconf, |
1265 | python3 (>= 3.4), |
1266 | python3-flake8, |
1267 | python3-mock, |
1268 | python3-pytest, |
1269 | python3-setuptools, |
1270 | - python3-yaml, |
1271 | - dh-systemd |
1272 | + python3-yaml |
1273 | Standards-Version: 4.3.0 |
1274 | Homepage: https://buy.ubuntu.com |
1275 | Vcs-Git: https://github.com/CanonicalLtd/ubuntu-advantage-script.git |
1276 | @@ -37,7 +38,7 @@ Description: management tools for Ubuntu Advantage |
1277 | |
1278 | Package: ubuntu-advantage-pro |
1279 | Architecture: any |
1280 | -Depends: ubuntu-advantage-tools (>=20.2) |
1281 | +Depends: ${misc:Depends}, ubuntu-advantage-tools (>=20.2) |
1282 | Replaces: ubuntu-advantage-tools (<<20.2) |
1283 | Breaks: ubuntu-advantage-tools (<<20.2) |
1284 | Description: utilities and services for Ubuntu Pro images |
1285 | diff --git a/debian/po/POTFILES.in b/debian/po/POTFILES.in |
1286 | new file mode 100644 |
1287 | index 0000000..986f7cc |
1288 | --- /dev/null |
1289 | +++ b/debian/po/POTFILES.in |
1290 | @@ -0,0 +1 @@ |
1291 | +[type: gettext/rfc822deb] ubuntu-advantage-tools.templates |
1292 | diff --git a/debian/po/templates.pot b/debian/po/templates.pot |
1293 | new file mode 100644 |
1294 | index 0000000..9dd5145 |
1295 | --- /dev/null |
1296 | +++ b/debian/po/templates.pot |
1297 | @@ -0,0 +1,36 @@ |
1298 | +# SOME DESCRIPTIVE TITLE. |
1299 | +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER |
1300 | +# This file is distributed under the same license as the ubuntu-advantage-tools package. |
1301 | +# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR. |
1302 | +# |
1303 | +#, fuzzy |
1304 | +msgid "" |
1305 | +msgstr "" |
1306 | +"Project-Id-Version: ubuntu-advantage-tools\n" |
1307 | +"Report-Msgid-Bugs-To: ubuntu-advantage-tools@packages.debian.org\n" |
1308 | +"POT-Creation-Date: 2020-10-02 15:07-0600\n" |
1309 | +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" |
1310 | +"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" |
1311 | +"Language-Team: LANGUAGE <LL@li.org>\n" |
1312 | +"Language: \n" |
1313 | +"MIME-Version: 1.0\n" |
1314 | +"Content-Type: text/plain; charset=CHARSET\n" |
1315 | +"Content-Transfer-Encoding: 8bit\n" |
1316 | + |
1317 | +#. Type: note |
1318 | +#. Description |
1319 | +#: ../ubuntu-advantage-tools.templates:1001 |
1320 | +msgid "Ubuntu Pro support now requires ubuntu-advantage-pro" |
1321 | +msgstr "" |
1322 | + |
1323 | +#. Type: note |
1324 | +#. Description |
1325 | +#: ../ubuntu-advantage-tools.templates:1001 |
1326 | +msgid "To install run the following:" |
1327 | +msgstr "" |
1328 | + |
1329 | +#. Type: note |
1330 | +#. Description |
1331 | +#: ../ubuntu-advantage-tools.templates:1001 |
1332 | +msgid "sudo apt-get install ubuntu-advantage-pro" |
1333 | +msgstr "" |
1334 | diff --git a/debian/postinst b/debian/postinst |
1335 | index 3b39c9d..5d942f9 100644 |
1336 | --- a/debian/postinst |
1337 | +++ b/debian/postinst |
1338 | @@ -11,12 +11,15 @@ UA_KEYRING_DIR="/usr/share/keyrings/" |
1339 | ESM_INFRA_KEY_TRUSTY="ubuntu-advantage-esm-infra-trusty.gpg" |
1340 | |
1341 | APT_SRC_DIR="/etc/apt/sources.list.d" |
1342 | +APT_PREFERENCES_DIR="/etc/apt/preferences.d" |
1343 | ESM_APT_SOURCE_FILE_PRECISE="$APT_SRC_DIR/ubuntu-esm-precise.list" |
1344 | ESM_APT_SOURCE_FILE_TRUSTY="$APT_SRC_DIR/ubuntu-esm-trusty.list" |
1345 | -ESM_INFRA_APT_SOURCE_FILE_TRUSTY="$APT_SRC_DIR/ubuntu-esm-infra-trusty.list" |
1346 | +ESM_INFRA_OLD_APT_SOURCE_FILE_TRUSTY="$APT_SRC_DIR/ubuntu-esm-infra-trusty.list" |
1347 | +ESM_INFRA_APT_SOURCE_FILE_TRUSTY="$APT_SRC_DIR/ubuntu-esm-infra.list" |
1348 | |
1349 | ESM_APT_PREF_FILE_TRUSTY="/etc/apt/preferences.d/ubuntu-esm-trusty" |
1350 | -ESM_INFRA_APT_PREF_FILE_TRUSTY="/etc/apt/preferences.d/ubuntu-esm-infra-trusty" |
1351 | +ESM_INFRA_OLD_APT_PREF_FILE_TRUSTY="/etc/apt/preferences.d/ubuntu-esm-infra-trusty" |
1352 | +ESM_INFRA_APT_PREF_FILE_TRUSTY="/etc/apt/preferences.d/ubuntu-esm-infra" |
1353 | |
1354 | MYARCH="$(dpkg --print-architecture)" |
1355 | ESM_SUPPORTED_ARCHS="i386 amd64" |
1356 | @@ -25,14 +28,80 @@ SYSTEMD_WANTS_AUTO_ATTACH_LINK="/etc/systemd/system/multi-user.target.wants/ua-a |
1357 | SYSTEMD_HELPER_ENABLED_AUTO_ATTACH_DSH="/var/lib/systemd/deb-systemd-helper-enabled/ua-auto-attach.service.dsh-also" |
1358 | SYSTEMD_HELPER_ENABLED_WANTS_LINK="/var/lib/systemd/deb-systemd-helper-enabled/multi-user.target.wants/ua-auto-attach.service" |
1359 | |
1360 | +REBOOT_CMD_MARKER_FILE="/var/lib/ubuntu-advantage/marker-reboot-cmds-required" |
1361 | + |
1362 | +# Rename apt config files for ua services removing ubuntu release names |
1363 | +redact_ubuntu_release_from_ua_apt_filenames() { |
1364 | + DIR=$1 |
1365 | + UA_SERVICES=$(python3 -c " |
1366 | +from uaclient.entitlements import ENTITLEMENT_CLASS_BY_NAME |
1367 | +print(*ENTITLEMENT_CLASS_BY_NAME.keys(), sep=' ') |
1368 | +") |
1369 | + |
1370 | + for file in "$DIR"/*; do |
1371 | + release_name="" |
1372 | + case "$file" in |
1373 | + *-trusty*) |
1374 | + release_name=trusty;; |
1375 | + *-xenial*) |
1376 | + release_name=xenial;; |
1377 | + *-bionic*) |
1378 | + release_name=bionic;; |
1379 | + *-focal*) |
1380 | + release_name=focal;; |
1381 | + *-groovy*) |
1382 | + release_name=groovy;; |
1383 | + *) release_name="";; |
1384 | + esac |
1385 | + if [ "$release_name" ]; then |
1386 | + # We have a ubuntu release name in the apt config. |
1387 | + # Remove $release_name from original $file. |
1388 | + new_file=${file%-${release_name}*}${file#*${release_name}} |
1389 | + for service in ${UA_SERVICES}; do |
1390 | + if [ "${file#*$service}" != "$file" ]; then |
1391 | + # Valid apt cfg file for an ubuntu-advantage service |
1392 | + mv "$file" "$new_file" |
1393 | + fi |
1394 | + done |
1395 | + fi |
1396 | + done |
1397 | +} |
1398 | + |
1399 | + |
1400 | +# Check cached service status from status.json and return 0 if enabled else 1 |
1401 | +check_service_is_enabled() { |
1402 | + service_name=$1 |
1403 | + _RET=$(python3 -c " |
1404 | +import os |
1405 | +import json |
1406 | +from uaclient.config import UAConfig |
1407 | +cfg = UAConfig() |
1408 | +status = cfg.read_cache('status-cache') |
1409 | +if status: |
1410 | + for service in status['services']: |
1411 | + if service['name'] == '${service_name}': |
1412 | + print(service['status']) |
1413 | +") |
1414 | + if [ "${_RET}" = "enabled" ]; then |
1415 | + return 0 |
1416 | + else |
1417 | + return 1 |
1418 | + fi |
1419 | +} |
1420 | + |
1421 | |
1422 | unconfigure_esm() { |
1423 | - rm -f $APT_TRUSTED_KEY_DIR/ubuntu-esm*gpg # Remove previous esm keys |
1424 | - rm -f $APT_TRUSTED_KEY_DIR/$ESM_INFRA_KEY_TRUSTY |
1425 | - rm -f $ESM_INFRA_APT_SOURCE_FILE_TRUSTY |
1426 | - rm -f $ESM_APT_PREF_FILE_TRUSTY $ESM_INFRA_APT_PREF_FILE_TRUSTY |
1427 | + if ! check_service_is_enabled esm-infra; then |
1428 | + rm -f $APT_TRUSTED_KEY_DIR/ubuntu-esm*gpg # Remove previous esm keys |
1429 | + rm -f $APT_TRUSTED_KEY_DIR/$ESM_INFRA_KEY_TRUSTY |
1430 | + rm -f $ESM_INFRA_APT_SOURCE_FILE_TRUSTY |
1431 | + rm -f $ESM_INFRA_OLD_APT_SOURCE_FILE_TRUSTY |
1432 | + rm -f $ESM_APT_PREF_FILE_TRUSTY $ESM_INFRA_OLD_APT_PREF_FILE_TRUSTY |
1433 | + rm -f $ESM_INFRA_APT_PREF_FILE_TRUSTY |
1434 | + fi |
1435 | } |
1436 | |
1437 | + |
1438 | configure_esm() { |
1439 | rm -f $APT_TRUSTED_KEY_DIR/ubuntu-esm*gpg # Remove previous esm keys |
1440 | if [ ! -f "$APT_TRUSTED_KEY_DIR/$ESM_INFRA_KEY_TRUSTY" ]; then |
1441 | @@ -64,6 +133,29 @@ EOF |
1442 | fi |
1443 | } |
1444 | |
1445 | + |
1446 | +# If held fips packages exist, we are on a FIPS PRO machine with FIPS enabled |
1447 | +mark_reboot_for_fips_pro() { |
1448 | + FIPS_HOLDS=$(apt-mark showholds | grep -E 'fips|libssl1|openssh-client|openssh-server|linux-fips|openssl|strongswan' || exit 0) |
1449 | + if [ "$FIPS_HOLDS" ]; then |
1450 | + mark_reboot_cmds_as_needed MESSAGE_FIPS_REBOOT_REQUIRED |
1451 | + fi |
1452 | +} |
1453 | + |
1454 | + |
1455 | +mark_reboot_cmds_as_needed() { |
1456 | + msg_name=$1 |
1457 | + if [ ! -f "$REBOOT_CMD_MARKER_FILE" ]; then |
1458 | + touch $REBOOT_CMD_MARKER_FILE |
1459 | + fi |
1460 | + python3 -c " |
1461 | +from uaclient.config import UAConfig |
1462 | +from uaclient.status import ${msg_name} |
1463 | +cfg = UAConfig() |
1464 | +cfg.add_notice(label='', description=${msg_name}) |
1465 | +" |
1466 | +} |
1467 | + |
1468 | case "$1" in |
1469 | configure) |
1470 | PREVIOUS_PKG_VER=$2 |
1471 | @@ -94,10 +186,15 @@ case "$1" in |
1472 | # ubuntu-advantage-pro package that should be installed |
1473 | . /usr/share/debconf/confmodule |
1474 | db_input high ubuntu-advantage-tools/suggest_pro_pkg || true |
1475 | - db_go |
1476 | + db_go || true |
1477 | fi |
1478 | fi |
1479 | |
1480 | + # UA service PPAs support all ubuntu releases, no need to |
1481 | + # specialize apt config filenames per ubuntu release. |
1482 | + redact_ubuntu_release_from_ua_apt_filenames $APT_SRC_DIR |
1483 | + redact_ubuntu_release_from_ua_apt_filenames $APT_PREFERENCES_DIR |
1484 | + |
1485 | # CACHE_DIR is no longer present or used since 19.1 |
1486 | rm -rf /var/cache/ubuntu-advantage-tools |
1487 | # machine-access cache files no longer present or used since 20.1 |
1488 | @@ -111,10 +208,8 @@ case "$1" in |
1489 | # 14.04 and unsupported arch |
1490 | unconfigure_esm |
1491 | fi |
1492 | - else |
1493 | - # not 14.04, regardless of arch |
1494 | - unconfigure_esm |
1495 | fi |
1496 | + |
1497 | if [ ! -f /var/log/ubuntu-advantage.log ]; then |
1498 | touch /var/log/ubuntu-advantage.log |
1499 | fi |
1500 | @@ -124,6 +219,13 @@ case "$1" in |
1501 | if [ -d "$private_dir" ]; then |
1502 | chmod 0700 "$private_dir" |
1503 | fi |
1504 | + |
1505 | + if [ "$VERSION_ID" = "16.04" ]; then |
1506 | + if echo "$PREVIOUS_PKG_VER" | grep -q "14.04"; then |
1507 | + mark_reboot_cmds_as_needed MESSAGE_LIVEPATCH_LTS_REBOOT_REQUIRED |
1508 | + fi |
1509 | + fi |
1510 | + mark_reboot_for_fips_pro |
1511 | ;; |
1512 | esac |
1513 | |
1514 | diff --git a/debian/postrm b/debian/postrm |
1515 | index 2112cf5..fb84664 100644 |
1516 | --- a/debian/postrm |
1517 | +++ b/debian/postrm |
1518 | @@ -16,11 +16,10 @@ remove_logs(){ |
1519 | rm -f /var/log/ubuntu-advantage.log* |
1520 | } |
1521 | |
1522 | -remove_esm(){ |
1523 | - # config files created in postinst, need explicit handling on purge |
1524 | +remove_gpg_files(){ |
1525 | rm -f /etc/apt/trusted.gpg.d/ubuntu-advantage-esm-infra-trusty.gpg |
1526 | - rm -f /etc/apt/sources.list.d/ubuntu-esm-infra-trusty.list |
1527 | - rm -f /etc/apt/preferences.d/ubuntu-esm-infra-trusty |
1528 | + rm -f /etc/apt/trusted.gpg.d/ubuntu-advantage-esm-apps.gpg |
1529 | + rm -f /etc/apt/trusted.gpg.d/ubuntu-advantage-fips.gpg |
1530 | } |
1531 | |
1532 | case "$1" in |
1533 | @@ -28,7 +27,7 @@ case "$1" in |
1534 | remove_apt_auth |
1535 | remove_cache_dir |
1536 | remove_logs |
1537 | - remove_esm |
1538 | + remove_gpg_files |
1539 | ;; |
1540 | esac |
1541 | |
1542 | diff --git a/debian/prerm b/debian/prerm |
1543 | index 4644c05..59b2b1b 100644 |
1544 | --- a/debian/prerm |
1545 | +++ b/debian/prerm |
1546 | @@ -5,9 +5,9 @@ set -e |
1547 | |
1548 | remove_apt_files() { |
1549 | python3 -c ' |
1550 | -from uaclient.apt import clean_apt_sources |
1551 | +from uaclient.apt import clean_apt_files |
1552 | |
1553 | -clean_apt_sources() |
1554 | +clean_apt_files() |
1555 | ' |
1556 | |
1557 | } |
1558 | diff --git a/debian/rules b/debian/rules |
1559 | index a535bbb..888dcde 100755 |
1560 | --- a/debian/rules |
1561 | +++ b/debian/rules |
1562 | @@ -39,26 +39,24 @@ endif |
1563 | endif |
1564 | |
1565 | override_dh_gencontrol: |
1566 | - [ -z '$(APT_PKG_DEPS)' ] || echo extra:Depends=$(APT_PKG_DEPS) >> debian/ubuntu-advantage-tools.substvars |
1567 | + echo extra:Depends=$(APT_PKG_DEPS) >> debian/ubuntu-advantage-tools.substvars |
1568 | dh_gencontrol |
1569 | |
1570 | override_dh_auto_install: |
1571 | dh_auto_install --destdir=debian/ubuntu-advantage-tools |
1572 | flist=$$(find $(CURDIR)/debian/ -type f -name version.py) && sed -i 's,@@PACKAGED_VERSION@@,$(DEB_VERSION),' $${flist:-did-not-find-version-py-for-replacement} |
1573 | -ifeq (${VERSION_ID},"14.04") |
1574 | make -C apt-hook DESTDIR=$(CURDIR)/debian/ubuntu-advantage-tools install |
1575 | -endif |
1576 | |
1577 | ifeq (${VERSION_ID},"14.04") |
1578 | - # Move ua-auto-attach.conf to ubuntu-advantage-pro |
1579 | + # Move ua-auto-attach.conf out to ubuntu-advantage-pro |
1580 | mkdir -p debian/ubuntu-advantage-pro/etc/init |
1581 | mv debian/ubuntu-advantage-tools/etc/init/ua-auto-attach.conf debian/ubuntu-advantage-pro/etc/init/ |
1582 | rmdir debian/ubuntu-advantage-tools/etc/init |
1583 | else |
1584 | - # Move ua-auto-attach.service to ubuntu-advantage-pro |
1585 | + # Move ua-auto-attach.service out to ubuntu-advantage-pro |
1586 | mkdir -p debian/ubuntu-advantage-pro/lib/systemd/system |
1587 | - mv debian/ubuntu-advantage-tools/lib/systemd/system/ua-auto-attach.service debian/ubuntu-advantage-pro/lib/systemd/system |
1588 | - cd debian/ubuntu-advantage-tools && rmdir -p lib/systemd/system |
1589 | + mv debian/ubuntu-advantage-tools/lib/systemd/system/ua-auto-attach.* debian/ubuntu-advantage-pro/lib/systemd/system |
1590 | + cd debian/ubuntu-advantage-tools |
1591 | endif |
1592 | |
1593 | override_dh_auto_clean: |
1594 | diff --git a/debian/ubuntu-advantage-tools.templates b/debian/ubuntu-advantage-tools.templates |
1595 | index 255d330..1b5c6f8 100644 |
1596 | --- a/debian/ubuntu-advantage-tools.templates |
1597 | +++ b/debian/ubuntu-advantage-tools.templates |
1598 | @@ -1,6 +1,6 @@ |
1599 | Template: ubuntu-advantage-tools/suggest_pro_pkg |
1600 | Type: note |
1601 | -Description: Ubuntu Pro support now requires ubuntu-advantage-pro |
1602 | +_Description: Ubuntu Pro support now requires ubuntu-advantage-pro |
1603 | To install run the following: |
1604 | . |
1605 | sudo apt-get install ubuntu-advantage-pro |
1606 | diff --git a/features/attach_invalidtoken.feature b/features/attach_invalidtoken.feature |
1607 | index 11a8ba8..4f3fc9a 100644 |
1608 | --- a/features/attach_invalidtoken.feature |
1609 | +++ b/features/attach_invalidtoken.feature |
1610 | @@ -1,15 +1,22 @@ |
1611 | Feature: Command behaviour when trying to attach a machine to an Ubuntu |
1612 | Advantage subscription using an invalid token |
1613 | |
1614 | - Scenario: Attach command in a trusty lxd container |
1615 | - Given a trusty lxd container with ubuntu-advantage-tools installed |
1616 | - When I run `ua attach INVALID_TOKEN` with sudo |
1617 | - Then I will see the following on stderr: |
1618 | + @series.all |
1619 | + Scenario Outline: Attach command in a machine |
1620 | + Given a `<release>` machine with ubuntu-advantage-tools installed |
1621 | + When I verify that running `ua attach INVALID_TOKEN` `with sudo` exits `1` |
1622 | + Then stderr matches regexp: |
1623 | """ |
1624 | Invalid token. See https://ubuntu.com/advantage |
1625 | """ |
1626 | - When I run `ua attach INVALID_TOKEN` as non-root |
1627 | + When I verify that running `ua attach INVALID_TOKEN` `as non-root` exits `1` |
1628 | Then I will see the following on stderr: |
1629 | """ |
1630 | This command must be run as root (try using sudo) |
1631 | """ |
1632 | + Examples: ubuntu release |
1633 | + | release | |
1634 | + | trusty | |
1635 | + | xenial | |
1636 | + | bionic | |
1637 | + | focal | |
1638 | diff --git a/features/attach_validtoken.feature b/features/attach_validtoken.feature |
1639 | index 2a7bfc9..a25234f 100644 |
1640 | --- a/features/attach_validtoken.feature |
1641 | +++ b/features/attach_validtoken.feature |
1642 | @@ -1,10 +1,38 @@ |
1643 | +@uses.config.contract_token |
1644 | Feature: Command behaviour when attaching a machine to an Ubuntu Advantage |
1645 | subscription using a valid token |
1646 | |
1647 | - @uses.config.contract_token |
1648 | - Scenario: Attach command in a trusty lxd container |
1649 | - Given a trusty lxd container with ubuntu-advantage-tools installed |
1650 | - When I attach contract_token with sudo |
1651 | + @series.all |
1652 | + @uses.config.machine_type.lxd.container |
1653 | + Scenario Outline: Attach command in a ubuntu lxd container |
1654 | + Given a `<release>` machine with ubuntu-advantage-tools installed |
1655 | + When I run `apt-get update` with sudo, retrying exit [100] |
1656 | + And I run `apt-get install -y <downrev_pkg>` with sudo, retrying exit [100] |
1657 | + When I verify that running ` --assume-yes --beta` `with sudo` exits `1` |
1658 | + And I run `/usr/lib/update-notifier/apt-check --human-readable` as non-root |
1659 | + Then if `<release>` in `trusty` and stdout matches regexp: |
1660 | + """ |
1661 | + UA Infrastructure Extended Security Maintenance \(ESM\) is not enabled. |
1662 | + |
1663 | + \d+ update(s)? can be installed immediately. |
1664 | + \d+ of these updates (is a|are) security update(s)?. |
1665 | + """ |
1666 | + Then if `<release>` in `trusty` and stdout matches regexp: |
1667 | + """ |
1668 | + Enable UA Infrastructure ESM to receive \d+ additional security update(s)?. |
1669 | + See https://ubuntu.com/advantage or run: sudo ua status |
1670 | + """ |
1671 | + Then if `<release>` in `xenial or bionic` and stdout matches regexp: |
1672 | + """ |
1673 | + \d+ package(s)? can be updated. |
1674 | + \d+ of these updates (is a|are) security update(s)?. |
1675 | + """ |
1676 | + Then if `<release>` in `focal` and stdout matches regexp: |
1677 | + """ |
1678 | + \d+ update(s)? can be installed immediately. |
1679 | + \d+ of these updates (is a|are) security update(s)?. |
1680 | + """ |
1681 | + When I attach `contract_token` with sudo |
1682 | Then stdout matches regexp: |
1683 | """ |
1684 | ESM Infra enabled |
1685 | @@ -16,15 +44,332 @@ Feature: Command behaviour when attaching a machine to an Ubuntu Advantage |
1686 | And stdout matches regexp: |
1687 | """ |
1688 | SERVICE ENTITLED STATUS DESCRIPTION |
1689 | - cc-eal +yes +n/a +Common Criteria EAL2 Provisioning Packages |
1690 | - cis-audit +no +— +Center for Internet Security Audit Tools |
1691 | - esm-apps +no +— +UA Apps: Extended Security Maintenance |
1692 | - esm-infra +yes +enabled +UA Infra: Extended Security Maintenance |
1693 | + esm-infra +yes +enabled +UA Infra: Extended Security Maintenance \(ESM\) |
1694 | fips +yes +n/a +NIST-certified FIPS modules |
1695 | fips-updates +yes +n/a +Uncertified security updates to FIPS modules |
1696 | livepatch +yes +n/a +Canonical Livepatch service |
1697 | """ |
1698 | - And I will see the following on stderr: |
1699 | + And stderr matches regexp: |
1700 | + """ |
1701 | + Enabling default service esm-infra |
1702 | + """ |
1703 | + When I run `/usr/lib/update-notifier/apt-check --human-readable` as non-root |
1704 | + Then if `<release>` in `trusty` and stdout matches regexp: |
1705 | + """ |
1706 | + UA (Infra:|Infrastructure) Extended Security Maintenance \(ESM\) is enabled. |
1707 | + |
1708 | + \d+ update(s)? can be installed immediately. |
1709 | + \d+ of these updates (is|are) (fixed|provided) through UA (Infra:|Infrastructure) ESM. |
1710 | + \d+ of these updates (is a|are) security update(s)?. |
1711 | + """ |
1712 | + Then if `<release>` in `focal` and stdout matches regexp: |
1713 | + """ |
1714 | + UA (Infra:|Infrastructure) Extended Security Maintenance \(ESM\) is enabled. |
1715 | + |
1716 | + \d+ update(s)? can be installed immediately. |
1717 | + \d+ of these updates (is|are) (fixed|provided) through UA (Infra:|Infrastructure) ESM. |
1718 | + \d+ of these updates (is a|are) security update(s)?. |
1719 | + To see these additional updates run: apt list --upgradable |
1720 | + """ |
1721 | + Then if `<release>` in `xenial or bionic` and stdout matches regexp: |
1722 | + """ |
1723 | + \d+ package(s)? can be updated. |
1724 | + \d+ of these updates (is a|are) security update(s)?. |
1725 | + """ |
1726 | + Examples: ubuntu release packages |
1727 | + | release | downrev_pkg | |
1728 | + | trusty | libgit2-0=0.19.0-2 | |
1729 | + | xenial | libkrad0=1.13.2+dfsg-5 | |
1730 | + | bionic | libkrad0=1.16-2build1 | |
1731 | + | focal | hello=2.10-2ubuntu2 | |
1732 | + |
1733 | + @series.all |
1734 | + @uses.config.machine_type.aws.generic |
1735 | + Scenario Outline: Attach command in a ubuntu lxd container |
1736 | + Given a `<release>` machine with ubuntu-advantage-tools installed |
1737 | + When I attach `contract_token` with sudo |
1738 | + Then stdout matches regexp: |
1739 | + """ |
1740 | + ESM Infra enabled |
1741 | + """ |
1742 | + And stdout matches regexp: |
1743 | + """ |
1744 | + This machine is now attached to |
1745 | + """ |
1746 | + And stdout matches regexp: |
1747 | + """ |
1748 | + SERVICE ENTITLED STATUS DESCRIPTION |
1749 | + esm-infra +yes +enabled +UA Infra: Extended Security Maintenance \(ESM\) |
1750 | + fips +yes +<fips_status> +NIST-certified FIPS modules |
1751 | + fips-updates +yes +<fips_status> +Uncertified security updates to FIPS modules |
1752 | + livepatch +yes +<lp_status> +<lp_desc> |
1753 | + """ |
1754 | + And stderr matches regexp: |
1755 | + """ |
1756 | + Enabling default service esm-infra |
1757 | + """ |
1758 | + |
1759 | + Examples: ubuntu release livepatch status |
1760 | + | release | fips_status |lp_status | lp_desc | |
1761 | + | trusty | n/a |n/a | Available with the HWE kernel | |
1762 | + | xenial | disabled |enabled | Canonical Livepatch service | |
1763 | + | bionic | disabled |enabled | Canonical Livepatch service | |
1764 | + | focal | n/a |enabled | Canonical Livepatch service | |
1765 | + |
1766 | + @series.all |
1767 | + @uses.config.machine_type.azure.generic |
1768 | + Scenario Outline: Attach command in a ubuntu lxd container |
1769 | + Given a `<release>` machine with ubuntu-advantage-tools installed |
1770 | + When I attach `contract_token` with sudo |
1771 | + Then stdout matches regexp: |
1772 | + """ |
1773 | + ESM Infra enabled |
1774 | + """ |
1775 | + And stdout matches regexp: |
1776 | + """ |
1777 | + This machine is now attached to |
1778 | + """ |
1779 | + And stdout matches regexp: |
1780 | + """ |
1781 | + SERVICE ENTITLED STATUS DESCRIPTION |
1782 | + esm-infra +yes +enabled +UA Infra: Extended Security Maintenance \(ESM\) |
1783 | + fips +yes +<fips_status> +NIST-certified FIPS modules |
1784 | + fips-updates +yes +<fips_status> +Uncertified security updates to FIPS modules |
1785 | + livepatch +yes +<lp_status> +Canonical Livepatch service |
1786 | + """ |
1787 | + And stderr matches regexp: |
1788 | + """ |
1789 | + Enabling default service esm-infra |
1790 | + """ |
1791 | + |
1792 | + Examples: ubuntu release livepatch status |
1793 | + | release | lp_status | fips_status | |
1794 | + | trusty | disabled | n/a | |
1795 | + | xenial | n/a | n/a | |
1796 | + | bionic | n/a | disabled | |
1797 | + | focal | n/a | n/a | |
1798 | + |
1799 | + @series.all |
1800 | + @uses.config.machine_type.gcp.generic |
1801 | + Scenario Outline: Attach command in a ubuntu lxd container |
1802 | + Given a `<release>` machine with ubuntu-advantage-tools installed |
1803 | + When I attach `contract_token` with sudo |
1804 | + Then stdout matches regexp: |
1805 | + """ |
1806 | + ESM Infra enabled |
1807 | + """ |
1808 | + And stdout matches regexp: |
1809 | + """ |
1810 | + This machine is now attached to |
1811 | + """ |
1812 | + And stdout matches regexp: |
1813 | + """ |
1814 | + SERVICE ENTITLED STATUS DESCRIPTION |
1815 | + esm-infra +yes +enabled +UA Infra: Extended Security Maintenance \(ESM\) |
1816 | + fips +yes +<fips_status> +NIST-certified FIPS modules |
1817 | + fips-updates +yes +<fips_status> +Uncertified security updates to FIPS modules |
1818 | + livepatch +yes +<lp_status> +Canonical Livepatch service |
1819 | + """ |
1820 | + And stderr matches regexp: |
1821 | """ |
1822 | Enabling default service esm-infra |
1823 | """ |
1824 | + |
1825 | + Examples: ubuntu release livepatch status |
1826 | + | release | lp_status | fips_status | |
1827 | + | trusty | disabled | n/a | |
1828 | + | xenial | n/a | n/a | |
1829 | + | bionic | n/a | n/a | |
1830 | + | focal | n/a | n/a | |
1831 | + |
1832 | + @series.bionic |
1833 | + @uses.config.machine_type.azure.generic |
1834 | + Scenario Outline: Attached enable of vm-based services in an ubuntu lxd vm |
1835 | + Given a `<release>` machine with ubuntu-advantage-tools installed |
1836 | + When I attach `contract_token_staging` with sudo |
1837 | + And I run `apt-get install openssh-client openssh-server strongswan -y` with sudo |
1838 | + And I run `apt-mark hold openssh-client openssh-server strongswan` with sudo |
1839 | + And I run `ua enable <fips-service> --assume-yes` with sudo |
1840 | + Then stdout matches regexp: |
1841 | + """ |
1842 | + Updating package lists |
1843 | + Installing <fips-name> packages |
1844 | + <fips-name> enabled |
1845 | + A reboot is required to complete install |
1846 | + """ |
1847 | + When I run `ua status --all` with sudo |
1848 | + Then stdout matches regexp: |
1849 | + """ |
1850 | + <fips-service> +yes enabled |
1851 | + """ |
1852 | + And I verify that running `apt update` `with sudo` exits `0` |
1853 | + And I verify that running `grep Traceback /var/log/ubuntu-advantage.log` `with sudo` exits `1` |
1854 | + And I verify that `openssh-server` is installed from apt source `<fips-apt-source>` |
1855 | + And I verify that `openssh-client` is installed from apt source `<fips-apt-source>` |
1856 | + And I verify that `strongswan` is installed from apt source `<fips-apt-source>` |
1857 | + And I verify that `openssh-server-hmac` is installed from apt source `<fips-apt-source>` |
1858 | + And I verify that `openssh-client-hmac` is installed from apt source `<fips-apt-source>` |
1859 | + And I verify that `strongswan-hmac` is installed from apt source `<fips-apt-source>` |
1860 | + When I run `apt-cache policy ubuntu-azure-fips` as non-root |
1861 | + Then stdout does not match regexp: |
1862 | + """ |
1863 | + .*Installed: \(none\) |
1864 | + """ |
1865 | + When I reboot the `<release>` machine |
1866 | + And I run `uname -r` as non-root |
1867 | + Then stdout matches regexp: |
1868 | + """ |
1869 | + azure-fips |
1870 | + """ |
1871 | + When I run `cat /proc/sys/crypto/fips_enabled` with sudo |
1872 | + Then I will see the following on stdout: |
1873 | + """ |
1874 | + 1 |
1875 | + """ |
1876 | + When I run `ua disable <fips-service> --assume-yes` with sudo |
1877 | + Then stdout matches regexp: |
1878 | + """ |
1879 | + Updating package lists |
1880 | + """ |
1881 | + When I run `apt-cache policy ubuntu-azure-fips` as non-root |
1882 | + Then stdout matches regexp: |
1883 | + """ |
1884 | + .*Installed: \(none\) |
1885 | + """ |
1886 | + When I reboot the `<release>` machine |
1887 | + Then I verify that `openssh-server` installed version matches regexp `fips` |
1888 | + And I verify that `openssh-client` installed version matches regexp `fips` |
1889 | + And I verify that `strongswan` installed version matches regexp `fips` |
1890 | + And I verify that `openssh-server-hmac` installed version matches regexp `fips` |
1891 | + And I verify that `openssh-client-hmac` installed version matches regexp `fips` |
1892 | + And I verify that `strongswan-hmac` installed version matches regexp `fips` |
1893 | + When I run `apt-mark unhold openssh-client openssh-server strongswan` with sudo |
1894 | + Then I will see the following on stdout: |
1895 | + """ |
1896 | + openssh-client was already not hold. |
1897 | + openssh-server was already not hold. |
1898 | + strongswan was already not hold. |
1899 | + """ |
1900 | + When I run `ua status --all` with sudo |
1901 | + Then stdout matches regexp: |
1902 | + """ |
1903 | + <fips-service> +yes disabled |
1904 | + """ |
1905 | + |
1906 | + Examples: ubuntu release |
1907 | + | release | fips-name | fips-service |fips-apt-source | |
1908 | + | bionic | FIPS | fips |https://esm.staging.ubuntu.com/fips/ubuntu bionic/main | |
1909 | + |
1910 | + @series.bionic |
1911 | + @uses.config.machine_type.aws.generic |
1912 | + Scenario Outline: Attached enable of vm-based services in an ubuntu lxd vm |
1913 | + Given a `<release>` machine with ubuntu-advantage-tools installed |
1914 | + When I attach `contract_token_staging` with sudo |
1915 | + And I run `ua disable livepatch` with sudo |
1916 | + And I run `apt-get install openssh-client openssh-server strongswan -y` with sudo |
1917 | + And I run `apt-mark hold openssh-client openssh-server strongswan` with sudo |
1918 | + And I run `ua enable <fips-service> --assume-yes` with sudo |
1919 | + Then stdout matches regexp: |
1920 | + """ |
1921 | + Updating package lists |
1922 | + Installing <fips-name> packages |
1923 | + <fips-name> enabled |
1924 | + A reboot is required to complete install |
1925 | + """ |
1926 | + When I run `ua status --all` with sudo |
1927 | + Then stdout matches regexp: |
1928 | + """ |
1929 | + <fips-service> +yes enabled |
1930 | + """ |
1931 | + And I verify that running `apt update` `with sudo` exits `0` |
1932 | + And I verify that running `grep Traceback /var/log/ubuntu-advantage.log` `with sudo` exits `1` |
1933 | + And I verify that `openssh-server` is installed from apt source `<fips-apt-source>` |
1934 | + And I verify that `openssh-client` is installed from apt source `<fips-apt-source>` |
1935 | + And I verify that `strongswan` is installed from apt source `<fips-apt-source>` |
1936 | + And I verify that `openssh-server-hmac` is installed from apt source `<fips-apt-source>` |
1937 | + And I verify that `openssh-client-hmac` is installed from apt source `<fips-apt-source>` |
1938 | + And I verify that `strongswan-hmac` is installed from apt source `<fips-apt-source>` |
1939 | + When I run `apt-cache policy ubuntu-aws-fips` as non-root |
1940 | + Then stdout does not match regexp: |
1941 | + """ |
1942 | + .*Installed: \(none\) |
1943 | + """ |
1944 | + When I reboot the `<release>` machine |
1945 | + And I run `uname -r` as non-root |
1946 | + Then stdout matches regexp: |
1947 | + """ |
1948 | + aws-fips |
1949 | + """ |
1950 | + When I run `cat /proc/sys/crypto/fips_enabled` with sudo |
1951 | + Then I will see the following on stdout: |
1952 | + """ |
1953 | + 1 |
1954 | + """ |
1955 | + When I run `ua disable <fips-service> --assume-yes` with sudo |
1956 | + Then stdout matches regexp: |
1957 | + """ |
1958 | + Updating package lists |
1959 | + """ |
1960 | + When I run `apt-cache policy ubuntu-aws-fips` as non-root |
1961 | + Then stdout matches regexp: |
1962 | + """ |
1963 | + .*Installed: \(none\) |
1964 | + """ |
1965 | + When I reboot the `<release>` machine |
1966 | + Then I verify that `openssh-server` installed version matches regexp `fips` |
1967 | + And I verify that `openssh-client` installed version matches regexp `fips` |
1968 | + And I verify that `strongswan` installed version matches regexp `fips` |
1969 | + And I verify that `openssh-server-hmac` installed version matches regexp `fips` |
1970 | + And I verify that `openssh-client-hmac` installed version matches regexp `fips` |
1971 | + And I verify that `strongswan-hmac` installed version matches regexp `fips` |
1972 | + When I run `apt-mark unhold openssh-client openssh-server strongswan` with sudo |
1973 | + Then I will see the following on stdout: |
1974 | + """ |
1975 | + openssh-client was already not hold. |
1976 | + openssh-server was already not hold. |
1977 | + strongswan was already not hold. |
1978 | + """ |
1979 | + When I run `ua status --all` with sudo |
1980 | + Then stdout matches regexp: |
1981 | + """ |
1982 | + <fips-service> +yes disabled |
1983 | + """ |
1984 | + |
1985 | + Examples: ubuntu release |
1986 | + | release | fips-name | fips-service |fips-apt-source | |
1987 | + | bionic | FIPS | fips |https://esm.staging.ubuntu.com/fips/ubuntu bionic/main | |
1988 | + |
1989 | + @series.xenial |
1990 | + @uses.config.machine_type.azure.generic |
1991 | + Scenario Outline: Attached enable of vm-based services in an ubuntu lxd vm |
1992 | + Given a `xenial` machine with ubuntu-advantage-tools installed |
1993 | + When I attach `contract_token_staging` with sudo |
1994 | + Then I verify that running `ua enable <fips_service> --assume-yes` `with sudo` exits `1` |
1995 | + And stdout matches regexp: |
1996 | + """ |
1997 | + Ubuntu Xenial does not provide an Azure optimized FIPS kernel |
1998 | + """ |
1999 | + |
2000 | + Examples: fips |
2001 | + | fips_service | |
2002 | + | fips | |
2003 | + | fips-updates | |
2004 | + |
2005 | + @series.bionic |
2006 | + @series.xenial |
2007 | + @uses.config.machine_type.gcp.generic |
2008 | + Scenario Outline: Attached enable of fips services in an ubuntu gcp vm |
2009 | + Given a `<release>` machine with ubuntu-advantage-tools installed |
2010 | + When I attach `contract_token_staging` with sudo |
2011 | + Then I verify that running `ua enable <fips_service> --assume-yes` `with sudo` exits `1` |
2012 | + And stdout matches regexp: |
2013 | + """ |
2014 | + Ubuntu <release_title> does not provide a GCP optimized FIPS kernel |
2015 | + """ |
2016 | + |
2017 | + Examples: fips |
2018 | + | release | release_title | fips_service | |
2019 | + | xenial | Xenial | fips | |
2020 | + | xenial | Xenial | fips-updates | |
2021 | + | bionic | Bionic | fips | |
2022 | + | bionic | Bionic | fips-updates | |
2023 | diff --git a/features/attached_commands.feature b/features/attached_commands.feature |
2024 | index 24dfbfe..4b48f76 100644 |
2025 | --- a/features/attached_commands.feature |
2026 | +++ b/features/attached_commands.feature |
2027 | @@ -1,13 +1,14 @@ |
2028 | @uses.config.contract_token |
2029 | Feature: Command behaviour when attached to an UA subscription |
2030 | |
2031 | - Scenario: Attached refresh in a trusty lxd container |
2032 | - Given a trusty lxd container with ubuntu-advantage-tools installed |
2033 | - When I attach contract_token with sudo |
2034 | - And I run `ua refresh` as non-root |
2035 | - Then I will see the following on stderr: |
2036 | + @series.all |
2037 | + Scenario Outline: Attached refresh in a ubuntu machine |
2038 | + Given a `<release>` machine with ubuntu-advantage-tools installed |
2039 | + When I attach `contract_token` with sudo |
2040 | + Then I verify that running `ua refresh` `as non-root` exits `1` |
2041 | + And stderr matches regexp: |
2042 | """ |
2043 | - This command must be run as root (try using sudo) |
2044 | + This command must be run as root \(try using sudo\) |
2045 | """ |
2046 | When I run `ua refresh` with sudo |
2047 | Then I will see the following on stdout: |
2048 | @@ -15,43 +16,55 @@ Feature: Command behaviour when attached to an UA subscription |
2049 | Successfully refreshed your subscription |
2050 | """ |
2051 | |
2052 | - Scenario: Attached disable of an already disabled service in a trusty lxd container |
2053 | - Given a trusty lxd container with ubuntu-advantage-tools installed |
2054 | - When I attach contract_token with sudo |
2055 | - And I run `ua disable livepatch` as non-root |
2056 | - Then I will see the following on stderr: |
2057 | + Examples: ubuntu release |
2058 | + | release | |
2059 | + | bionic | |
2060 | + | focal | |
2061 | + | trusty | |
2062 | + | xenial | |
2063 | + |
2064 | + @series.all |
2065 | + Scenario Outline: Attached disable of an already disabled service in a ubuntu machine |
2066 | + Given a `<release>` machine with ubuntu-advantage-tools installed |
2067 | + When I attach `contract_token` with sudo |
2068 | + Then I verify that running `ua disable livepatch` `as non-root` exits `1` |
2069 | + And stderr matches regexp: |
2070 | """ |
2071 | - This command must be run as root (try using sudo) |
2072 | + This command must be run as root \(try using sudo\) |
2073 | """ |
2074 | - When I run `ua disable livepatch` with sudo |
2075 | - Then I will see the following on stdout: |
2076 | + And I verify that running `ua disable livepatch` `with sudo` exits `1` |
2077 | + And I will see the following on stdout: |
2078 | """ |
2079 | Livepatch is not currently enabled |
2080 | See: sudo ua status |
2081 | """ |
2082 | |
2083 | - Scenario: Attached disable of an unknown service in a trusty lxd container |
2084 | - Given a trusty lxd container with ubuntu-advantage-tools installed |
2085 | - When I attach contract_token with sudo |
2086 | - And I run `ua disable foobar` as non-root |
2087 | - Then I will see the following on stderr: |
2088 | + Examples: ubuntu release |
2089 | + | release | |
2090 | + | bionic | |
2091 | + | focal | |
2092 | + | trusty | |
2093 | + | xenial | |
2094 | + |
2095 | + @series.all |
2096 | + Scenario Outline: Attached disable of a service in a ubuntu machine |
2097 | + Given a `<release>` machine with ubuntu-advantage-tools installed |
2098 | + When I attach `contract_token` with sudo |
2099 | + Then I verify that running `ua disable foobar` `as non-root` exits `1` |
2100 | + And stderr matches regexp: |
2101 | """ |
2102 | - This command must be run as root (try using sudo) |
2103 | + This command must be run as root \(try using sudo\) |
2104 | """ |
2105 | - When I run `ua disable foobar` with sudo |
2106 | - Then I will see the following on stderr: |
2107 | + And I verify that running `ua disable foobar` `with sudo` exits `1` |
2108 | + And stderr matches regexp: |
2109 | """ |
2110 | - Cannot disable 'foobar' |
2111 | - For a list of services see: sudo ua status |
2112 | + Cannot disable unknown service 'foobar'. |
2113 | + Try cc-eal, cis, esm-apps, esm-infra, fips, fips-updates, livepatch |
2114 | """ |
2115 | - |
2116 | - Scenario: Attached disable of an already enabled service in a trusty lxd container |
2117 | - Given a trusty lxd container with ubuntu-advantage-tools installed |
2118 | - When I attach contract_token with sudo |
2119 | - And I run `ua disable esm-infra` as non-root |
2120 | - Then I will see the following on stderr: |
2121 | + And I verify that running `ua disable esm-infra` `as non-root` exits `1` |
2122 | + And stderr matches regexp: |
2123 | """ |
2124 | - This command must be run as root (try using sudo) |
2125 | + This command must be run as root \(try using sudo\) |
2126 | """ |
2127 | When I run `ua disable esm-infra` with sudo |
2128 | Then I will see the following on stdout: |
2129 | @@ -61,26 +74,24 @@ Feature: Command behaviour when attached to an UA subscription |
2130 | When I run `ua status` with sudo |
2131 | Then stdout matches regexp: |
2132 | """ |
2133 | - esm-infra +yes +disabled +UA Infra: Extended Security Maintenance |
2134 | - """ |
2135 | - When I run `apt-cache policy` with sudo |
2136 | - Then stdout matches regexp: |
2137 | - """ |
2138 | - -32768 https://esm.ubuntu.com/ubuntu/ trusty-infra-updates/main amd64 Packages |
2139 | - """ |
2140 | - And stdout matches regexp: |
2141 | - """ |
2142 | - -32768 https://esm.ubuntu.com/ubuntu/ trusty-infra-security/main amd64 Packages |
2143 | + esm-infra +yes +disabled +UA Infra: Extended Security Maintenance \(ESM\) |
2144 | """ |
2145 | + And I verify that running `apt update` `with sudo` exits `0` |
2146 | |
2147 | + Examples: ubuntu release |
2148 | + | release | |
2149 | + | bionic | |
2150 | + | focal | |
2151 | + | xenial | |
2152 | |
2153 | - Scenario: Attached detach in a trusty lxd container |
2154 | - Given a trusty lxd container with ubuntu-advantage-tools installed |
2155 | - When I attach contract_token with sudo |
2156 | - And I run `ua detach` as non-root |
2157 | - Then I will see the following on stderr: |
2158 | + @series.all |
2159 | + Scenario Outline: Attached detach in a trusty machine |
2160 | + Given a `<release>` machine with ubuntu-advantage-tools installed |
2161 | + When I attach `contract_token` with sudo |
2162 | + Then I verify that running `ua detach` `as non-root` exits `1` |
2163 | + And stderr matches regexp: |
2164 | """ |
2165 | - This command must be run as root (try using sudo) |
2166 | + This command must be run as root \(try using sudo\) |
2167 | """ |
2168 | When I run `ua detach --assume-yes` with sudo |
2169 | Then I will see the following on stdout: |
2170 | @@ -90,18 +101,336 @@ Feature: Command behaviour when attached to an UA subscription |
2171 | Updating package lists |
2172 | This machine is now detached |
2173 | """ |
2174 | - When I run `ua status` as non-root |
2175 | + When I run `ua status --all` as non-root |
2176 | Then stdout matches regexp: |
2177 | """ |
2178 | SERVICE AVAILABLE DESCRIPTION |
2179 | - cc-eal +no +Common Criteria EAL2 Provisioning Packages |
2180 | - esm-apps +no +UA Apps: Extended Security Maintenance |
2181 | - esm-infra +yes +UA Infra: Extended Security Maintenance |
2182 | - fips +no +NIST-certified FIPS modules |
2183 | - fips-updates +no +Uncertified security updates to FIPS modules |
2184 | + cc-eal +<cc-eal> +Common Criteria EAL2 Provisioning Packages |
2185 | + cis +<cis> +Center for Internet Security Audit Tools |
2186 | + esm-apps +<esm-apps> +UA Apps: Extended Security Maintenance \(ESM\) |
2187 | + esm-infra +yes +UA Infra: Extended Security Maintenance \(ESM\) |
2188 | + fips +<fips> +NIST-certified FIPS modules |
2189 | + fips-updates +<fips> +Uncertified security updates to FIPS modules |
2190 | livepatch +yes +Canonical Livepatch service |
2191 | """ |
2192 | And stdout matches regexp: |
2193 | """ |
2194 | This machine is not attached to a UA subscription. |
2195 | """ |
2196 | + And I verify that running `apt update` `with sudo` exits `0` |
2197 | + |
2198 | + Examples: ubuntu release |
2199 | + | release | esm-apps | cc-eal | cis | fips | fips-update | |
2200 | + | bionic | yes | no | yes | yes | yes | |
2201 | + | focal | yes | no | no | no | no | |
2202 | + | trusty | no | no | no | no | no | |
2203 | + | xenial | yes | yes | yes | yes | yes | |
2204 | + |
2205 | + @series.all |
2206 | + Scenario Outline: Attached auto-attach in a ubuntu machine |
2207 | + Given a `<release>` machine with ubuntu-advantage-tools installed |
2208 | + When I attach `contract_token` with sudo |
2209 | + Then I verify that running `ua auto-attach` `as non-root` exits `1` |
2210 | + And stderr matches regexp: |
2211 | + """ |
2212 | + This command must be run as root \(try using sudo\) |
2213 | + """ |
2214 | + When I run `ua auto-attach` with sudo |
2215 | + Then stderr matches regexp: |
2216 | + """ |
2217 | + This machine is already attached |
2218 | + """ |
2219 | + |
2220 | + Examples: ubuntu release |
2221 | + | release | |
2222 | + | bionic | |
2223 | + | focal | |
2224 | + | trusty | |
2225 | + | xenial | |
2226 | + |
2227 | + @series.all |
2228 | + Scenario Outline: Attached show version in a ubuntu machine |
2229 | + Given a `<release>` machine with ubuntu-advantage-tools installed |
2230 | + When I attach `contract_token` with sudo |
2231 | + And I run `ua version` as non-root |
2232 | + Then I will see the uaclient version on stdout |
2233 | + When I run `ua version` with sudo |
2234 | + Then I will see the uaclient version on stdout |
2235 | + When I run `ua --version` as non-root |
2236 | + Then I will see the uaclient version on stdout |
2237 | + When I run `ua --version` with sudo |
2238 | + Then I will see the uaclient version on stdout |
2239 | + |
2240 | + Examples: ubuntu release |
2241 | + | release | |
2242 | + | bionic | |
2243 | + | focal | |
2244 | + | trusty | |
2245 | + | xenial | |
2246 | + |
2247 | + @series.all |
2248 | + Scenario Outline: Unattached status in a ubuntu machine with feature overrides |
2249 | + Given a `<release>` machine with ubuntu-advantage-tools installed |
2250 | + When I create the file `/tmp/machine-token-overlay.json` with the following: |
2251 | + """ |
2252 | + { |
2253 | + "machineTokenInfo": { |
2254 | + "contractInfo": { |
2255 | + "resourceEntitlements": [ |
2256 | + { |
2257 | + "type": "cc-eal", |
2258 | + "entitled": false |
2259 | + } |
2260 | + ] |
2261 | + } |
2262 | + } |
2263 | + } |
2264 | + """ |
2265 | + And I append the following on uaclient config: |
2266 | + """ |
2267 | + features: |
2268 | + machine_token_overlay: "/tmp/machine-token-overlay.json" |
2269 | + disable_auto_attach: true |
2270 | + other: false |
2271 | + """ |
2272 | + And I attach `contract_token` with sudo |
2273 | + And I run `ua status --all` with sudo |
2274 | + Then stdout matches regexp: |
2275 | + """ |
2276 | + SERVICE ENTITLED STATUS DESCRIPTION |
2277 | + cc-eal no |
2278 | + """ |
2279 | + When I run `ua --version` as non-root |
2280 | + Then I will see the uaclient version on stdout with features ` +disable_auto_attach +machine_token_overlay -other` |
2281 | + When I run `ua version` as non-root |
2282 | + Then I will see the uaclient version on stdout with features ` +disable_auto_attach +machine_token_overlay -other` |
2283 | + When I run `ua auto-attach` with sudo |
2284 | + Then stdout matches regexp: |
2285 | + """ |
2286 | + Skipping auto-attach. Config disable_auto_attach is set. |
2287 | + """ |
2288 | + |
2289 | + Examples: ubuntu release |
2290 | + | release | |
2291 | + | bionic | |
2292 | + | focal | |
2293 | + | trusty | |
2294 | + | xenial | |
2295 | + |
2296 | + @series.all |
2297 | + Scenario Outline: Attached disable of different services in a ubuntu machine |
2298 | + Given a `<release>` machine with ubuntu-advantage-tools installed |
2299 | + When I attach `contract_token` with sudo |
2300 | + Then I verify that running `ua disable esm-infra livepatch foobar` `as non-root` exits `1` |
2301 | + And stderr matches regexp: |
2302 | + """ |
2303 | + This command must be run as root \(try using sudo\) |
2304 | + """ |
2305 | + And I verify that running `ua disable esm-infra livepatch foobar` `with sudo` exits `1` |
2306 | + And I will see the following on stdout: |
2307 | + """ |
2308 | + Updating package lists |
2309 | + Livepatch is not currently enabled |
2310 | + See: sudo ua status |
2311 | + """ |
2312 | + And stderr matches regexp: |
2313 | + """ |
2314 | + Cannot disable unknown service 'foobar'. |
2315 | + Try cc-eal, cis, esm-apps, esm-infra, fips, fips-updates, livepatch |
2316 | + """ |
2317 | + When I run `ua status` with sudo |
2318 | + Then stdout matches regexp: |
2319 | + """ |
2320 | + esm-infra +yes +disabled +UA Infra: Extended Security Maintenance \(ESM\) |
2321 | + """ |
2322 | + |
2323 | + Examples: ubuntu release |
2324 | + | release | |
2325 | + | bionic | |
2326 | + | focal | |
2327 | + | trusty | |
2328 | + | xenial | |
2329 | + |
2330 | + @series.trusty |
2331 | + Scenario: Attached disable of an already enabled service in a trusty machine |
2332 | + Given a `trusty` machine with ubuntu-advantage-tools installed |
2333 | + When I attach `contract_token` with sudo |
2334 | + Then I verify that running `ua disable foobar` `as non-root` exits `1` |
2335 | + And stderr matches regexp: |
2336 | + """ |
2337 | + This command must be run as root \(try using sudo\) |
2338 | + """ |
2339 | + And I verify that running `ua disable foobar` `with sudo` exits `1` |
2340 | + And stderr matches regexp: |
2341 | + """ |
2342 | + Cannot disable unknown service 'foobar'. |
2343 | + Try cc-eal, cis, esm-apps, esm-infra, fips, fips-updates, livepatch |
2344 | + """ |
2345 | + And I verify that running `ua disable esm-infra` `as non-root` exits `1` |
2346 | + And stderr matches regexp: |
2347 | + """ |
2348 | + This command must be run as root \(try using sudo\) |
2349 | + """ |
2350 | + When I run `ua disable esm-infra` with sudo |
2351 | + Then I will see the following on stdout: |
2352 | + """ |
2353 | + Updating package lists |
2354 | + """ |
2355 | + When I run `ua status` with sudo |
2356 | + Then stdout matches regexp: |
2357 | + """ |
2358 | + esm-infra +yes +disabled +UA Infra: Extended Security Maintenance \(ESM\) |
2359 | + """ |
2360 | + And I verify that running `apt update` `with sudo` exits `0` |
2361 | + When I run `apt-cache policy` with sudo |
2362 | + Then apt-cache policy for the following url has permission `-32768` |
2363 | + """ |
2364 | + https://esm.ubuntu.com/ubuntu/ trusty-infra-security/main amd64 Packages |
2365 | + """ |
2366 | + And apt-cache policy for the following url has permission `-32768` |
2367 | + """ |
2368 | + https://esm.ubuntu.com/ubuntu/ trusty-infra-updates/main amd64 Packages |
2369 | + """ |
2370 | + |
2371 | + @series.all |
2372 | + Scenario Outline: Help command on an attached machine |
2373 | + Given a `<release>` machine with ubuntu-advantage-tools installed |
2374 | + When I attach `contract_token` with sudo |
2375 | + And I run `ua help esm-infra` with sudo |
2376 | + Then I will see the following on stdout: |
2377 | + """ |
2378 | + Name: |
2379 | + esm-infra |
2380 | + |
2381 | + Entitled: |
2382 | + yes |
2383 | + |
2384 | + Status: |
2385 | + enabled |
2386 | + |
2387 | + Help: |
2388 | + esm-infra provides access to a private ppa which includes available high |
2389 | + and critical CVE fixes for Ubuntu LTS packages in the Ubuntu Main |
2390 | + repository between the end of the standard Ubuntu LTS security |
2391 | + maintenance and its end of life. It is enabled by default with |
2392 | + Extended Security Maintenance (ESM) for UA Apps and UA Infra. |
2393 | + You can find our more about the esm service at |
2394 | + https://ubuntu.com/security/esm |
2395 | + """ |
2396 | + When I run `ua help esm-infra --format json` with sudo |
2397 | + Then I will see the following on stdout: |
2398 | + """ |
2399 | + {"name": "esm-infra", "entitled": "yes", "status": "enabled", "help": "esm-infra provides access to a private ppa which includes available high\nand critical CVE fixes for Ubuntu LTS packages in the Ubuntu Main\nrepository between the end of the standard Ubuntu LTS security\nmaintenance and its end of life. It is enabled by default with\nExtended Security Maintenance (ESM) for UA Apps and UA Infra.\nYou can find our more about the esm service at\nhttps://ubuntu.com/security/esm\n"} |
2400 | + """ |
2401 | + And I verify that running `ua help invalid-service` `with sudo` exits `1` |
2402 | + And I will see the following on stderr: |
2403 | + """ |
2404 | + No help available for 'invalid-service' |
2405 | + """ |
2406 | + When I run `ua --help` as non-root |
2407 | + Then stdout matches regexp: |
2408 | + """ |
2409 | + Client to manage Ubuntu Advantage services on a machine. |
2410 | + - esm-infra: UA Infra: Extended Security Maintenance \(ESM\) |
2411 | + \(https://ubuntu.com/security/esm\) |
2412 | + - fips-updates: Uncertified security updates to FIPS modules |
2413 | + \(https://ubuntu.com/security/certifications#fips\) |
2414 | + - fips: NIST-certified FIPS modules |
2415 | + \(https://ubuntu.com/security/certifications#fips\) |
2416 | + - livepatch: Canonical Livepatch service |
2417 | + \(https://ubuntu.com/security/livepatch\) |
2418 | + """ |
2419 | + When I run `ua help` as non-root |
2420 | + Then stdout matches regexp: |
2421 | + """ |
2422 | + Client to manage Ubuntu Advantage services on a machine. |
2423 | + - esm-infra: UA Infra: Extended Security Maintenance \(ESM\) |
2424 | + \(https://ubuntu.com/security/esm\) |
2425 | + - fips-updates: Uncertified security updates to FIPS modules |
2426 | + \(https://ubuntu.com/security/certifications#fips\) |
2427 | + - fips: NIST-certified FIPS modules |
2428 | + \(https://ubuntu.com/security/certifications#fips\) |
2429 | + - livepatch: Canonical Livepatch service |
2430 | + \(https://ubuntu.com/security/livepatch\) |
2431 | + """ |
2432 | + When I run `ua help --all` as non-root |
2433 | + Then stdout matches regexp: |
2434 | + """ |
2435 | + Client to manage Ubuntu Advantage services on a machine. |
2436 | + - cc-eal: Common Criteria EAL2 Provisioning Packages |
2437 | + \(https://ubuntu.com/cc-eal\) |
2438 | + - cis: Center for Internet Security Audit Tools |
2439 | + \(https://ubuntu.com/security/certifications#cis\) |
2440 | + - esm-apps: UA Apps: Extended Security Maintenance \(ESM\) |
2441 | + \(https://ubuntu.com/security/esm\) |
2442 | + - esm-infra: UA Infra: Extended Security Maintenance \(ESM\) |
2443 | + \(https://ubuntu.com/security/esm\) |
2444 | + - fips-updates: Uncertified security updates to FIPS modules |
2445 | + \(https://ubuntu.com/security/certifications#fips\) |
2446 | + - fips: NIST-certified FIPS modules |
2447 | + \(https://ubuntu.com/security/certifications#fips\) |
2448 | + - livepatch: Canonical Livepatch service |
2449 | + \(https://ubuntu.com/security/livepatch\) |
2450 | + """ |
2451 | + |
2452 | + Examples: ubuntu release |
2453 | + | release | |
2454 | + | bionic | |
2455 | + | focal | |
2456 | + | trusty | |
2457 | + | xenial | |
2458 | + |
2459 | + @series.all |
2460 | + Scenario Outline: Purge package after attaching it to a machine |
2461 | + Given a `<release>` machine with ubuntu-advantage-tools installed |
2462 | + When I attach `contract_token` with sudo |
2463 | + And I run `touch /etc/apt/preferences.d/ubuntu-esm-infra` with sudo |
2464 | + Then I verify that files exist matching `/var/log/ubuntu-advantage.log` |
2465 | + And I verify that running `test -d /var/lib/ubuntu-advantage` `with sudo` exits `0` |
2466 | + And I verify that files exist matching `/etc/apt/auth.conf.d/90ubuntu-advantage` |
2467 | + And I verify that files exist matching `/etc/apt/trusted.gpg.d/ubuntu-advantage-esm-infra-trusty.gpg` |
2468 | + And I verify that files exist matching `/etc/apt/sources.list.d/ubuntu-esm-infra.list` |
2469 | + And I verify that files exist matching `/etc/apt/preferences.d/ubuntu-esm-infra` |
2470 | + When I run `apt-get purge ubuntu-advantage-tools -y` with sudo, retrying exit [100] |
2471 | + Then stdout matches regexp: |
2472 | + """ |
2473 | + Purging configuration files for ubuntu-advantage-tools |
2474 | + """ |
2475 | + And I verify that no files exist matching `/var/log/ubuntu-advantage.log` |
2476 | + And I verify that no files exist matching `/var/lib/ubuntu-advantage` |
2477 | + And I verify that no files exist matching `/etc/apt/auth.conf.d/90ubuntu-advantage` |
2478 | + And I verify that no files exist matching `/etc/apt/sources.list.d/ubuntu-*` |
2479 | + And I verify that no files exist matching `/etc/apt/trusted.gpg.d/ubuntu-advantage-*` |
2480 | + And I verify that no files exist matching `/etc/apt/preferences.d/ubuntu-*` |
2481 | + |
2482 | + Examples: ubuntu release |
2483 | + | release | |
2484 | + | bionic | |
2485 | + | focal | |
2486 | + | trusty | |
2487 | + | xenial | |
2488 | + |
2489 | + @series.all |
2490 | + Scenario Outline: Enable command with invalid repositories in user machine |
2491 | + Given a `<release>` machine with ubuntu-advantage-tools installed |
2492 | + When I attach `contract_token` with sudo |
2493 | + And I run `ua disable esm-infra` with sudo |
2494 | + And I run `add-apt-repository ppa:ua-client/staging -y` with sudo, retrying exit [1] |
2495 | + And I run `apt update` with sudo |
2496 | + And I run `sed -i 's/ubuntu/ubun/' /etc/apt/sources.list.d/<ppa_file>.list` with sudo |
2497 | + And I run `ua enable esm-infra` with sudo |
2498 | + Then stdout matches regexp: |
2499 | + """ |
2500 | + One moment, checking your subscription first |
2501 | + Updating package lists |
2502 | + APT update failed. |
2503 | + APT update failed to read APT config for the following URL: |
2504 | + - http://ppa.launchpad.net/ua-client/staging/ubun |
2505 | + """ |
2506 | + |
2507 | + Examples: ubuntu release |
2508 | + | release | ppa_file | |
2509 | + | trusty | ua-client-staging-trusty | |
2510 | + | xenial | ua-client-ubuntu-staging-xenial | |
2511 | + | bionic | ua-client-ubuntu-staging-bionic | |
2512 | + | focal | ua-client-ubuntu-staging-focal | |
2513 | diff --git a/features/attached_enable.feature b/features/attached_enable.feature |
2514 | index 86f2a56..8a36fce 100644 |
2515 | --- a/features/attached_enable.feature |
2516 | +++ b/features/attached_enable.feature |
2517 | @@ -1,131 +1,437 @@ |
2518 | @uses.config.contract_token |
2519 | Feature: Enable command behaviour when attached to an UA subscription |
2520 | |
2521 | + @series.all |
2522 | + Scenario Outline: Attached enable Common Criteria service in a ubuntu machine |
2523 | + Given a `<release>` machine with ubuntu-advantage-tools installed |
2524 | + When I attach `contract_token` with sudo |
2525 | + Then I verify that running `ua enable cc-eal` `as non-root` exits `1` |
2526 | + And I will see the following on stderr: |
2527 | + """ |
2528 | + This command must be run as root (try using sudo) |
2529 | + """ |
2530 | + And I verify that running `ua enable cc-eal --beta` `with sudo` exits `1` |
2531 | + And I will see the following on stdout |
2532 | + """ |
2533 | + One moment, checking your subscription first |
2534 | + <msg> |
2535 | + """ |
2536 | + And I verify that running `ua enable cc-eal` `with sudo` exits `1` |
2537 | + And I will see the following on stdout: |
2538 | + """ |
2539 | + One moment, checking your subscription first |
2540 | + """ |
2541 | + And stderr matches regexp: |
2542 | + """ |
2543 | + Cannot enable unknown service 'cc-eal'. |
2544 | + Try esm-infra, fips, fips-updates, livepatch |
2545 | + """ |
2546 | |
2547 | - Scenario: Attached enable Livepatch service in a trusty lxd container |
2548 | - Given a trusty lxd container with ubuntu-advantage-tools installed |
2549 | - When I attach contract_token with sudo |
2550 | - And I run `ua enable livepatch` as non-root |
2551 | - Then I will see the following on stderr: |
2552 | + Examples: ubuntu release |
2553 | + | release | msg | |
2554 | + | bionic | CC EAL2 is not available for Ubuntu 18.04 LTS (Bionic Beaver). | |
2555 | + | focal | CC EAL2 is not available for Ubuntu 20.04 LTS (Focal Fossa). | |
2556 | + | trusty | CC EAL2 is not available for Ubuntu 14.04 LTS (Trusty Tahr). | |
2557 | + |
2558 | + @series.all |
2559 | + Scenario Outline: Attached enable a disabled beta service and unknown service in a ubuntu machine |
2560 | + Given a `<release>` machine with ubuntu-advantage-tools installed |
2561 | + When I attach `contract_token` with sudo |
2562 | + Then I verify that running `ua enable cc-eal foobar` `as non-root` exits `1` |
2563 | + And I will see the following on stderr: |
2564 | """ |
2565 | This command must be run as root (try using sudo) |
2566 | """ |
2567 | - When I run `ua enable livepatch` with sudo |
2568 | - Then I will see the following on stdout: |
2569 | + And I verify that running `ua enable cc-eal foobar` `with sudo` exits `1` |
2570 | + And I will see the following on stdout: |
2571 | """ |
2572 | One moment, checking your subscription first |
2573 | - Cannot install Livepatch on a container |
2574 | + """ |
2575 | + And stderr matches regexp: |
2576 | + """ |
2577 | + Cannot enable unknown service 'foobar, cc-eal'. |
2578 | + Try esm-infra, fips, fips-updates, livepatch |
2579 | """ |
2580 | |
2581 | + Examples: ubuntu release |
2582 | + | release | |
2583 | + | bionic | |
2584 | + | focal | |
2585 | + | trusty | |
2586 | + | xenial | |
2587 | |
2588 | - Scenario: Attached enable Common Criteria service in a trusty lxd container |
2589 | - Given a trusty lxd container with ubuntu-advantage-tools installed |
2590 | - When I attach contract_token with sudo |
2591 | - And I run `ua enable cc-eal` as non-root |
2592 | - Then I will see the following on stderr: |
2593 | + @series.all |
2594 | + Scenario Outline: Attached enable of an unknown service in a ubuntu machine |
2595 | + Given a `<release>` machine with ubuntu-advantage-tools installed |
2596 | + When I attach `contract_token` with sudo |
2597 | + Then I verify that running `ua enable foobar` `as non-root` exits `1` |
2598 | + And I will see the following on stderr: |
2599 | """ |
2600 | This command must be run as root (try using sudo) |
2601 | """ |
2602 | - When I run `ua enable cc-eal` with sudo |
2603 | - Then I will see the following on stdout |
2604 | + And I verify that running `ua enable foobar` `with sudo` exits `1` |
2605 | + And I will see the following on stdout: |
2606 | """ |
2607 | One moment, checking your subscription first |
2608 | - CC EAL2 is not available for Ubuntu 14.04 LTS (Trusty Tahr). |
2609 | + """ |
2610 | + And stderr matches regexp: |
2611 | + """ |
2612 | + Cannot enable unknown service 'foobar'. |
2613 | + Try esm-infra, fips, fips-updates, livepatch |
2614 | """ |
2615 | |
2616 | + Examples: ubuntu release |
2617 | + | release | |
2618 | + | bionic | |
2619 | + | focal | |
2620 | + | trusty | |
2621 | + | xenial | |
2622 | |
2623 | - Scenario: Attached enable CIS Audit service in a trusty lxd container |
2624 | - Given a trusty lxd container with ubuntu-advantage-tools installed |
2625 | - When I attach contract_token with sudo |
2626 | - And I run `ua enable cis-audit` as non-root |
2627 | - Then I will see the following on stderr: |
2628 | + @series.all |
2629 | + Scenario Outline: Attached enable of a known service already enabled (UA Infra) in a ubuntu machine |
2630 | + Given a `<release>` machine with ubuntu-advantage-tools installed |
2631 | + When I attach `contract_token` with sudo |
2632 | + Then I verify that running `ua enable esm-infra` `as non-root` exits `1` |
2633 | + And I will see the following on stderr: |
2634 | """ |
2635 | This command must be run as root (try using sudo) |
2636 | """ |
2637 | - When I run `ua enable cis-audit` with sudo |
2638 | + And I verify that running `ua enable esm-infra` `with sudo` exits `1` |
2639 | Then I will see the following on stdout: |
2640 | """ |
2641 | One moment, checking your subscription first |
2642 | - This subscription is not entitled to CIS Audit. |
2643 | - For more information see: https://ubuntu.com/advantage |
2644 | + ESM Infra is already enabled. |
2645 | + See: sudo ua status |
2646 | """ |
2647 | + When I run `apt-cache policy` with sudo |
2648 | + Then apt-cache policy for the following url has permission `500` |
2649 | + """ |
2650 | + <esm-infra-url> <release>-infra-updates/main amd64 Packages |
2651 | + """ |
2652 | + And I verify that running `apt update` `with sudo` exits `0` |
2653 | + When I run `apt install -y <infra-pkg>` with sudo, retrying exit [100] |
2654 | + And I run `apt-cache policy <infra-pkg>` as non-root |
2655 | + Then stdout matches regexp: |
2656 | + """ |
2657 | + \s*500 <esm-infra-url> <release>-infra-security/main amd64 Packages |
2658 | + \s*500 <esm-infra-url> <release>-infra-updates/main amd64 Packages |
2659 | + """ |
2660 | |
2661 | - Scenario: Attached enable UA Apps service in a trusty lxd container |
2662 | - Given a trusty lxd container with ubuntu-advantage-tools installed |
2663 | - When I attach contract_token with sudo |
2664 | - And I run `ua enable esm-apps` as non-root |
2665 | - Then I will see the following on stderr: |
2666 | + Examples: ubuntu release |
2667 | + | release | infra-pkg | esm-infra-url | |
2668 | + | bionic | libkrad0 | https://esm.ubuntu.com/infra/ubuntu | |
2669 | + | focal | hello | https://esm.ubuntu.com/infra/ubuntu | |
2670 | + | trusty | libgit2-0 | https://esm.ubuntu.com/ubuntu/ | |
2671 | + | xenial | libkrad0 | https://esm.ubuntu.com/infra/ubuntu | |
2672 | + |
2673 | + @series.xenial |
2674 | + @series.bionic |
2675 | + @series.focal |
2676 | + Scenario Outline: Attached enable of a know service shows update in a ubuntu machine |
2677 | + Given a `<release>` machine with ubuntu-advantage-tools installed |
2678 | + When I attach `contract_token` with sudo |
2679 | + Then I verify that running `ua enable esm-infra` `with sudo` exits `1` |
2680 | + And I will see the following on stdout: |
2681 | + """ |
2682 | + One moment, checking your subscription first |
2683 | + ESM Infra is already enabled. |
2684 | + See: sudo ua status |
2685 | + """ |
2686 | + When I run `apt install -y <pkg-version>` with sudo, retrying exit [100] |
2687 | + And I run `apt update` with sudo |
2688 | + Then stdout matches regexp |
2689 | + """ |
2690 | + \d+ of the updates (is|are) from UA Infra: ESM |
2691 | + """ |
2692 | + When I run `ua disable esm-infra` with sudo |
2693 | + And I run `apt update` with sudo |
2694 | + Then stdout does not match regexp |
2695 | + """ |
2696 | + \d+ of the updates (is|are) from UA Infra: ESM |
2697 | + """ |
2698 | + |
2699 | + Examples: ubuntu release |
2700 | + | release | pkg-version | |
2701 | + | bionic | libkrad0=1.16-2build1 | |
2702 | + | focal | hello=2.10-2ubuntu2 | |
2703 | + | xenial | libkrad0=1.13.2+dfsg-5 | |
2704 | + |
2705 | + @series.all |
2706 | + @uses.config.machine_type.lxd.container |
2707 | + Scenario Outline: Attached enable of non-container services in a ubuntu lxd container |
2708 | + Given a `<release>` machine with ubuntu-advantage-tools installed |
2709 | + When I attach `contract_token` with sudo |
2710 | + Then I verify that running `ua enable <service> <flag>` `as non-root` exits `1` |
2711 | + And I will see the following on stderr: |
2712 | """ |
2713 | This command must be run as root (try using sudo) |
2714 | """ |
2715 | - When I run `ua enable esm-apps` with sudo |
2716 | - Then I will see the following on stdout: |
2717 | + And I verify that running `ua enable <service> <flag>` `with sudo` exits `1` |
2718 | + And I will see the following on stdout: |
2719 | """ |
2720 | One moment, checking your subscription first |
2721 | - This subscription is not entitled to ESM Apps. |
2722 | - For more information see: https://ubuntu.com/advantage |
2723 | + Cannot install <title> on a container |
2724 | """ |
2725 | |
2726 | + Examples: Un-supported services in containers |
2727 | + | release | service | title | flag | |
2728 | + | bionic | livepatch | Livepatch | | |
2729 | + | bionic | fips | FIPS | --assume-yes | |
2730 | + | bionic | fips-updates | FIPS Updates | --assume-yes | |
2731 | + | focal | livepatch | Livepatch | | |
2732 | + | focal | fips | FIPS | --assume-yes | |
2733 | + | focal | fips-updates | FIPS Updates | --assume-yes | |
2734 | + | trusty | livepatch | Livepatch | | |
2735 | + | trusty | fips | FIPS | --assume-yes | |
2736 | + | trusty | fips-updates | FIPS Updates | --assume-yes | |
2737 | + | xenial | livepatch | Livepatch | | |
2738 | + | xenial | fips | FIPS | --assume-yes | |
2739 | + | xenial | fips-updates | FIPS Updates | --assume-yes | |
2740 | |
2741 | - Scenario: Attached enable NIST-certified FIPS service in a trusty lxd container |
2742 | - Given a trusty lxd container with ubuntu-advantage-tools installed |
2743 | - When I attach contract_token with sudo |
2744 | - And I run `ua enable fips` as non-root |
2745 | - Then I will see the following on stderr: |
2746 | + @series.all |
2747 | + Scenario Outline: Attached enable not entitled service in a ubuntu machine |
2748 | + Given a `<release>` machine with ubuntu-advantage-tools installed |
2749 | + When I attach `contract_token` with sudo |
2750 | + Then I verify that running `ua enable <service>` `as non-root` exits `1` |
2751 | + And I will see the following on stderr: |
2752 | """ |
2753 | This command must be run as root (try using sudo) |
2754 | """ |
2755 | - When I run `ua enable fips` with sudo |
2756 | - Then I will see the following on stdout: |
2757 | + And I verify that running `ua enable <service> --beta` `with sudo` exits `1` |
2758 | + And I will see the following on stdout: |
2759 | """ |
2760 | One moment, checking your subscription first |
2761 | - Cannot install FIPS on a container |
2762 | + This subscription is not entitled to <title>. |
2763 | + For more information see: https://ubuntu.com/advantage |
2764 | """ |
2765 | |
2766 | + Examples: not entitled services |
2767 | + | release | service | title | |
2768 | + | bionic | cis | CIS Audit | |
2769 | + | bionic | esm-apps | ESM Apps | |
2770 | + | focal | cis | CIS Audit | |
2771 | + | focal | esm-apps | ESM Apps | |
2772 | + | trusty | cis | CIS Audit | |
2773 | + | trusty | esm-apps | ESM Apps | |
2774 | + | xenial | cis | CIS Audit | |
2775 | + | xenial | esm-apps | ESM Apps | |
2776 | |
2777 | - Scenario: Attached enable Uncertified FIPS service in a trusty lxd container |
2778 | - Given a trusty lxd container with ubuntu-advantage-tools installed |
2779 | - When I attach contract_token with sudo |
2780 | - And I run `ua enable fips-updates` as non-root |
2781 | + @series.focal |
2782 | + @uses.config.machine_type.lxd.vm |
2783 | + Scenario: Attached enable of vm-based services in a focal lxd vm |
2784 | + Given a `focal` machine with ubuntu-advantage-tools installed |
2785 | + When I attach `contract_token` with sudo |
2786 | + Then I verify that running `ua enable fips --assume-yes` `with sudo` exits `1` |
2787 | + And I will see the following on stdout: |
2788 | + """ |
2789 | + One moment, checking your subscription first |
2790 | + FIPS is not available for Ubuntu 20.04 LTS (Focal Fossa). |
2791 | + """ |
2792 | + And I verify that running `ua enable fips-updates --assume-yes` `with sudo` exits `1` |
2793 | + And I will see the following on stdout: |
2794 | + """ |
2795 | + One moment, checking your subscription first |
2796 | + FIPS Updates is not available for Ubuntu 20.04 LTS (Focal Fossa). |
2797 | + """ |
2798 | + |
2799 | + @series.bionic |
2800 | + @series.xenial |
2801 | + @uses.config.machine_type.lxd.vm |
2802 | + Scenario Outline: Attached enable of vm-based services in a bionic lxd vm |
2803 | + Given a `<release>` machine with ubuntu-advantage-tools installed |
2804 | + When I attach `contract_token` with sudo |
2805 | + And I run `ua status` with sudo |
2806 | + Then stdout matches regexp: |
2807 | + """ |
2808 | + esm-infra +yes +enabled +UA Infra: Extended Security Maintenance \(ESM\) |
2809 | + fips +yes +disabled +NIST-certified FIPS modules |
2810 | + fips-updates +yes +disabled +Uncertified security updates to FIPS modules |
2811 | + livepatch +yes +enabled +Canonical Livepatch service |
2812 | + """ |
2813 | + When I run `ua disable livepatch` with sudo |
2814 | + Then I verify that running `canonical-livepatch status` `with sudo` exits `1` |
2815 | + And stdout matches regexp: |
2816 | + """ |
2817 | + Machine is not enabled. Please run 'sudo canonical-livepatch enable' with the |
2818 | + token obtained from https://ubuntu.com/livepatch. |
2819 | + """ |
2820 | + When I run `ua status` with sudo |
2821 | + Then stdout matches regexp: |
2822 | + """ |
2823 | + esm-infra +yes +enabled +UA Infra: Extended Security Maintenance \(ESM\) |
2824 | + fips +yes +disabled +NIST-certified FIPS modules |
2825 | + fips-updates +yes +disabled +Uncertified security updates to FIPS modules |
2826 | + livepatch +yes +disabled +Canonical Livepatch service |
2827 | + """ |
2828 | + |
2829 | + Examples: ubuntu release |
2830 | + | release | |
2831 | + | xenial | |
2832 | + | bionic | |
2833 | + |
2834 | + @series.bionic |
2835 | + @series.xenial |
2836 | + @uses.config.machine_type.lxd.vm |
2837 | + Scenario Outline: Attached enable livepatch on a machine with fips active |
2838 | + Given a `<release>` machine with ubuntu-advantage-tools installed |
2839 | + When I verify that running `canonical-livepatch status` `with sudo` exits `1` |
2840 | Then I will see the following on stderr: |
2841 | """ |
2842 | - This command must be run as root (try using sudo) |
2843 | + sudo: canonical-livepatch: command not found |
2844 | + """ |
2845 | + When I attach `contract_token` with sudo |
2846 | + Then stdout matches regexp: |
2847 | + """ |
2848 | + Installing canonical-livepatch snap |
2849 | + Canonical livepatch enabled |
2850 | """ |
2851 | - When I run `ua enable fips-updates` with sudo |
2852 | + When I run `ua status` with sudo |
2853 | + Then stdout matches regexp: |
2854 | + """ |
2855 | + livepatch yes enabled |
2856 | + """ |
2857 | + When I run `canonical-livepatch status` with sudo |
2858 | + Then stdout matches regexp: |
2859 | + """ |
2860 | + running: true |
2861 | + """ |
2862 | + |
2863 | + Examples: ubuntu release |
2864 | + | release | |
2865 | + | xenial | |
2866 | + | bionic | |
2867 | + |
2868 | + @series.bionic |
2869 | + @uses.config.machine_type.lxd.vm |
2870 | + Scenario: Attached enable fips on a machine with livepatch active |
2871 | + Given a `bionic` machine with ubuntu-advantage-tools installed |
2872 | + When I attach `contract_token` with sudo |
2873 | + Then stdout matches regexp: |
2874 | + """ |
2875 | + Updating package lists |
2876 | + ESM Infra enabled |
2877 | + Installing canonical-livepatch snap |
2878 | + Canonical livepatch enabled |
2879 | + """ |
2880 | + When I run `ua disable livepatch` with sudo |
2881 | + And I run `ua enable fips --assume-yes` with sudo |
2882 | Then I will see the following on stdout: |
2883 | """ |
2884 | One moment, checking your subscription first |
2885 | - Cannot install FIPS Updates on a container |
2886 | + Updating package lists |
2887 | + Installing FIPS packages |
2888 | + FIPS enabled |
2889 | + A reboot is required to complete install |
2890 | + """ |
2891 | + When I append the following on uaclient config: |
2892 | + """ |
2893 | + features: |
2894 | + block_disable_on_enable: true |
2895 | + """ |
2896 | + Then I verify that running `ua enable livepatch` `with sudo` exits `1` |
2897 | + And I will see the following on stdout |
2898 | + """ |
2899 | + One moment, checking your subscription first |
2900 | + Cannot enable Livepatch when FIPS is enabled |
2901 | """ |
2902 | |
2903 | + @series.bionic |
2904 | + @uses.config.machine_type.lxd.vm |
2905 | + Scenario: Attached enable livepatch on a machine with fips active |
2906 | + Given a `bionic` machine with ubuntu-advantage-tools installed |
2907 | + When I attach `contract_token` with sudo |
2908 | + Then stdout matches regexp: |
2909 | + """ |
2910 | + Updating package lists |
2911 | + ESM Infra enabled |
2912 | + Installing canonical-livepatch snap |
2913 | + Canonical livepatch enabled |
2914 | + """ |
2915 | + When I append the following on uaclient config: |
2916 | + """ |
2917 | + features: |
2918 | + block_disable_on_enable: true |
2919 | + """ |
2920 | + Then I verify that running `ua enable fips --assume-yes` `with sudo` exits `1` |
2921 | + And I will see the following on stdout |
2922 | + """ |
2923 | + One moment, checking your subscription first |
2924 | + Cannot enable FIPS when Livepatch is enabled |
2925 | + """ |
2926 | |
2927 | - Scenario: Attached enable of an unknown service in a trusty lxd container |
2928 | - Given a trusty lxd container with ubuntu-advantage-tools installed |
2929 | - When I attach contract_token with sudo |
2930 | - And I run `ua enable foobar` as non-root |
2931 | - Then I will see the following on stderr: |
2932 | + @series.xenial |
2933 | + @series.bionic |
2934 | + @uses.config.machine_type.lxd.vm |
2935 | + Scenario Outline: Attached enable fips on a machine with livepatch active |
2936 | + Given a `<release>` machine with ubuntu-advantage-tools installed |
2937 | + When I attach `contract_token` with sudo |
2938 | + Then stdout matches regexp: |
2939 | """ |
2940 | - This command must be run as root (try using sudo) |
2941 | + Updating package lists |
2942 | + ESM Infra enabled |
2943 | """ |
2944 | - When I run `ua enable foobar` with sudo |
2945 | - Then I will see the following on stderr: |
2946 | + And stdout matches regexp: |
2947 | + """ |
2948 | + Installing canonical-livepatch snap |
2949 | + Canonical livepatch enabled |
2950 | + """ |
2951 | + When I run `ua enable fips --assume-yes` with sudo |
2952 | + Then I will see the following on stdout |
2953 | + """ |
2954 | + One moment, checking your subscription first |
2955 | + Updating package lists |
2956 | + Installing FIPS packages |
2957 | + FIPS enabled |
2958 | + A reboot is required to complete install |
2959 | """ |
2960 | - Cannot enable 'foobar' |
2961 | - For a list of services see: sudo ua status |
2962 | + When I run `ua status` with sudo |
2963 | + Then stdout matches regexp: |
2964 | + """ |
2965 | + fips +yes +enabled |
2966 | + """ |
2967 | + And stdout matches regexp: |
2968 | + """ |
2969 | + livepatch +yes +n/a |
2970 | """ |
2971 | |
2972 | - Scenario: Attached enable of a known service already enabled (UA Infra) in a trusty lxd container |
2973 | - Given a trusty lxd container with ubuntu-advantage-tools installed |
2974 | - When I attach contract_token with sudo |
2975 | - And I run `ua enable esm-infra` as non-root |
2976 | - Then I will see the following on stderr: |
2977 | + Examples: ubuntu release |
2978 | + | release | |
2979 | + | bionic | |
2980 | + | xenial | |
2981 | + |
2982 | + @series.xenial |
2983 | + @series.bionic |
2984 | + @uses.config.machine_type.lxd.vm |
2985 | + Scenario Outline: Attached enable fips on a machine with fips-updates active |
2986 | + Given a `<release>` machine with ubuntu-advantage-tools installed |
2987 | + When I attach `contract_token` with sudo |
2988 | + Then stdout matches regexp: |
2989 | """ |
2990 | - This command must be run as root (try using sudo) |
2991 | + ESM Infra enabled |
2992 | + """ |
2993 | + And stdout matches regexp: |
2994 | + """ |
2995 | + Installing canonical-livepatch snap |
2996 | + Canonical livepatch enabled |
2997 | """ |
2998 | - When I run `ua enable esm-infra` with sudo |
2999 | + When I run `ua disable livepatch` with sudo |
3000 | + And I run `ua enable fips-updates --assume-yes` with sudo |
3001 | Then I will see the following on stdout: |
3002 | """ |
3003 | One moment, checking your subscription first |
3004 | - ESM Infra is already enabled. |
3005 | - See: sudo ua status |
3006 | + Updating package lists |
3007 | + Installing FIPS Updates packages |
3008 | + FIPS Updates enabled |
3009 | + A reboot is required to complete install |
3010 | """ |
3011 | + When I verify that running `ua enable fips --assume-yes` `with sudo` exits `1` |
3012 | + Then I will see the following on stdout |
3013 | + """ |
3014 | + One moment, checking your subscription first |
3015 | + Cannot enable FIPS when FIPS Updates is enabled |
3016 | + """ |
3017 | + |
3018 | + Examples: ubuntu release |
3019 | + | release | |
3020 | + | bionic | |
3021 | + | xenial | |
3022 | diff --git a/features/aws-ids.yaml b/features/aws-ids.yaml |
3023 | new file mode 100644 |
3024 | index 0000000..e065192 |
3025 | --- /dev/null |
3026 | +++ b/features/aws-ids.yaml |
3027 | @@ -0,0 +1,4 @@ |
3028 | +bionic: ami-0e11aa8c6a6d58146 |
3029 | +focal: ami-0383ece2c0f6de239 |
3030 | +trusty: ami-0a64b4493bc9dc321 |
3031 | +xenial: ami-09e110a448d322f4a |
3032 | diff --git a/features/azure-ids.yaml b/features/azure-ids.yaml |
3033 | new file mode 100644 |
3034 | index 0000000..0072983 |
3035 | --- /dev/null |
3036 | +++ b/features/azure-ids.yaml |
3037 | @@ -0,0 +1,4 @@ |
3038 | +bionic: "Canonical:0001-com-ubuntu-pro-bionic:pro-18_04-lts" |
3039 | +focal: "Canonical:0001-com-ubuntu-pro-focal:pro-20_04-lts" |
3040 | +trusty: "Canonical:0001-com-ubuntu-pro-trusty:pro-14_04-lts" |
3041 | +xenial: "Canonical:0001-com-ubuntu-pro-xenial:pro-16_04-lts" |
3042 | diff --git a/features/cloud.py b/features/cloud.py |
3043 | new file mode 100644 |
3044 | index 0000000..4443345 |
3045 | --- /dev/null |
3046 | +++ b/features/cloud.py |
3047 | @@ -0,0 +1,744 @@ |
3048 | +import json |
3049 | +import os |
3050 | +import logging |
3051 | +import pycloudlib # type: ignore |
3052 | +import time |
3053 | +import yaml |
3054 | + |
3055 | +try: |
3056 | + from typing import Tuple, List, Optional # noqa |
3057 | +except ImportError: |
3058 | + # typing isn't available on trusty, so ignore its absence |
3059 | + pass |
3060 | + |
3061 | + |
3062 | +class Cloud: |
3063 | + """Base class for cloud providers that should be tested through behave. |
3064 | + |
3065 | + :machine_type: |
3066 | + A string representing the type of machine to launch (pro or generic) |
3067 | + :region: |
3068 | + The region to create the cloud resources on |
3069 | + :param tag: |
3070 | + A tag to be used when creating the resources on the cloud provider |
3071 | + :timestamp_suffix: |
3072 | + Boolean set true to direct pycloudlib to append a timestamp to the end |
3073 | + of the provided tag. |
3074 | + """ |
3075 | + |
3076 | + name = "" |
3077 | + pro_ids_path = "" |
3078 | + env_vars: "Tuple[str, ...]" = () |
3079 | + |
3080 | + def __init__( |
3081 | + self, |
3082 | + machine_type: str, |
3083 | + region: "Optional[str]" = None, |
3084 | + tag: "Optional[str]" = None, |
3085 | + timestamp_suffix: bool = True, |
3086 | + ) -> None: |
3087 | + if tag: |
3088 | + self.tag = tag |
3089 | + else: |
3090 | + self.tag = "uaclient-ci" |
3091 | + self.machine_type = machine_type |
3092 | + self.region = region |
3093 | + self._api = None |
3094 | + self.key_name = pycloudlib.util.get_timestamped_tag(self.tag) |
3095 | + self.timestamp_suffix = timestamp_suffix |
3096 | + |
3097 | + missing_env_vars = self.missing_env_vars() |
3098 | + if missing_env_vars: |
3099 | + logging.warning( |
3100 | + "".join( |
3101 | + [ |
3102 | + "UACLIENT_BEHAVE_MACHINE_TYPE={} requires".format( |
3103 | + self.machine_type |
3104 | + ), |
3105 | + " the following env vars:\n", |
3106 | + *self.format_missing_env_vars(missing_env_vars), |
3107 | + ] |
3108 | + ) |
3109 | + ) |
3110 | + |
3111 | + @property |
3112 | + def api(self) -> pycloudlib.cloud.BaseCloud: |
3113 | + """Return the api used to interact with the cloud provider.""" |
3114 | + raise NotImplementedError |
3115 | + |
3116 | + def _create_instance( |
3117 | + self, |
3118 | + series: str, |
3119 | + instance_name: "Optional[str]" = None, |
3120 | + image_name: "Optional[str]" = None, |
3121 | + user_data: "Optional[str]" = None, |
3122 | + ) -> pycloudlib.instance: |
3123 | + """Create an instance for on the cloud provider. |
3124 | + |
3125 | + :param series: |
3126 | + The ubuntu release to be used when creating an instance. We will |
3127 | + create an image based on this value if the used does not provide |
3128 | + a image_name value |
3129 | + :param instance_name: |
3130 | + The name of the instance to be created |
3131 | + :param image_name: |
3132 | + The name of the image to be used when creating the instance |
3133 | + :param user_data: |
3134 | + The user data to be passed when creating the instance |
3135 | + |
3136 | + :returns: |
3137 | + A cloud provider instance |
3138 | + """ |
3139 | + raise NotImplementedError |
3140 | + |
3141 | + def _check_cloudinit_status( |
3142 | + self, instance: pycloudlib.instance.BaseInstance |
3143 | + ) -> None: |
3144 | + """ |
3145 | + Check if cloudinit was able to finish without errors. |
3146 | + |
3147 | + :param instance: |
3148 | + An instance created on the cloud provider |
3149 | + """ |
3150 | + result = instance.execute(["cloud-init", "status", "--wait", "--long"]) |
3151 | + |
3152 | + if result.failed: |
3153 | + raise OSError( |
3154 | + "cloud-init failed to start\n: out: %s\n error: %s" |
3155 | + % (result.stdout, result.stderr) |
3156 | + ) |
3157 | + |
3158 | + print("--- cloud-init succeeded") |
3159 | + |
3160 | + def launch( |
3161 | + self, |
3162 | + series: str, |
3163 | + instance_name: "Optional[str]" = None, |
3164 | + image_name: "Optional[str]" = None, |
3165 | + user_data: "Optional[str]" = None, |
3166 | + ) -> pycloudlib.instance.BaseInstance: |
3167 | + """Create and wait for cloud provider instance to be ready. |
3168 | + |
3169 | + :param series: |
3170 | + The ubuntu release to be used when creating an instance. We will |
3171 | + create an image based on this value if the used does not provide |
3172 | + a image_name value |
3173 | + :param instance_name: |
3174 | + The name of the instance to be created |
3175 | + :param image_name: |
3176 | + The name of the image to be used when creating the instance |
3177 | + :param user_data: |
3178 | + The user data to be passed when creating the instance |
3179 | + |
3180 | + :returns: |
3181 | + An cloud provider instance |
3182 | + """ |
3183 | + inst = self._create_instance( |
3184 | + series=series, |
3185 | + instance_name=instance_name, |
3186 | + image_name=image_name, |
3187 | + user_data=user_data, |
3188 | + ) |
3189 | + print( |
3190 | + "--- {} instance launched: {}. Waiting for ssh access".format( |
3191 | + self.name, inst.name |
3192 | + ) |
3193 | + ) |
3194 | + time.sleep(15) |
3195 | + for sleep in (5, 10, 15): |
3196 | + try: |
3197 | + inst.wait() |
3198 | + break |
3199 | + except Exception as e: |
3200 | + print("--- Retrying instance.wait on {}".format(str(e))) |
3201 | + |
3202 | + if series != "trusty": |
3203 | + self._check_cloudinit_status(inst) |
3204 | + |
3205 | + return inst |
3206 | + |
3207 | + def get_instance_id( |
3208 | + self, instance: pycloudlib.instance.BaseInstance |
3209 | + ) -> str: |
3210 | + """Return the instance identifier. |
3211 | + |
3212 | + :param instance: |
3213 | + An instance created on the cloud provider |
3214 | + |
3215 | + :returns: |
3216 | + The string of the unique instance id |
3217 | + """ |
3218 | + return instance.id |
3219 | + |
3220 | + def format_missing_env_vars(self, missing_env_vars: "List") -> "List[str]": |
3221 | + """Format missing env vars to be displayed in log. |
3222 | + |
3223 | + :returns: |
3224 | + A list of env string formatted to be used when logging |
3225 | + """ |
3226 | + return [" - {}\n".format(env_var) for env_var in missing_env_vars] |
3227 | + |
3228 | + def missing_env_vars(self) -> "List[str]": |
3229 | + """Return a list of env variables necessary for this cloud provider. |
3230 | + |
3231 | + :returns: |
3232 | + A list of string representing the missing variables |
3233 | + """ |
3234 | + return [ |
3235 | + env_name |
3236 | + for env_name in self.env_vars |
3237 | + if not getattr( |
3238 | + self, env_name.lower().replace("uaclient_behave_", "") |
3239 | + ) |
3240 | + ] |
3241 | + |
3242 | + def locate_image_name(self, series: str) -> str: |
3243 | + """Locate and return the image name to use for vm provision. |
3244 | + |
3245 | + :param series: |
3246 | + The ubuntu release to be used when locating the image name |
3247 | + |
3248 | + :returns: |
3249 | + A image name to use when provisioning a virtual machine |
3250 | + based on the series value |
3251 | + """ |
3252 | + if not series: |
3253 | + raise ValueError( |
3254 | + "Must provide either series or image_name to launch azure" |
3255 | + ) |
3256 | + |
3257 | + if "pro" in self.machine_type: |
3258 | + with open(self.pro_ids_path, "r") as stream: |
3259 | + pro_ids = yaml.safe_load(stream.read()) |
3260 | + image_name = pro_ids[series] |
3261 | + else: |
3262 | + image_name = self.api.daily_image(release=series) |
3263 | + |
3264 | + return image_name |
3265 | + |
3266 | + def manage_ssh_key(self, private_key_path: "Optional[str]" = None) -> None: |
3267 | + """Create and manage ssh key pairs to be used in the cloud provider. |
3268 | + |
3269 | + :param private_key_path: |
3270 | + Location of the private key path to use. If None, the location |
3271 | + will be a default location. |
3272 | + """ |
3273 | + cloud_name = self.name.lower().replace("_", "-") |
3274 | + pub_key_path = "{}-pubkey".format(cloud_name) |
3275 | + priv_key_path = "{}-privkey".format(cloud_name) |
3276 | + pub_key, priv_key = self.api.create_key_pair() |
3277 | + |
3278 | + with open(pub_key_path, "w") as f: |
3279 | + f.write(pub_key) |
3280 | + |
3281 | + with open(priv_key_path, "w") as f: |
3282 | + f.write(priv_key) |
3283 | + |
3284 | + os.chmod(pub_key_path, 0o600) |
3285 | + os.chmod(priv_key_path, 0o600) |
3286 | + |
3287 | + self.api.use_key( |
3288 | + public_key_path=pub_key_path, private_key_path=priv_key_path |
3289 | + ) |
3290 | + |
3291 | + |
3292 | +class EC2(Cloud): |
3293 | + """Class that represents the EC2 cloud provider. |
3294 | + |
3295 | + :param aws_access_key_id: |
3296 | + The aws access key id |
3297 | + :param aws_secret_access_key: |
3298 | + The aws secret access key |
3299 | + :region: |
3300 | + The region to be used to create the aws instances |
3301 | + :machine_type: |
3302 | + A string representing the type of machine to launch (pro or generic) |
3303 | + :tag: |
3304 | + A tag to be used when creating the resources on the cloud provider |
3305 | + :timestamp_suffix: |
3306 | + Boolean set true to direct pycloudlib to append a timestamp to the end |
3307 | + of the provided tag. |
3308 | + """ |
3309 | + |
3310 | + name = "aws" |
3311 | + env_vars: "Tuple[str, ...]" = ( |
3312 | + "aws_access_key_id", |
3313 | + "aws_secret_access_key", |
3314 | + ) |
3315 | + pro_ids_path = "features/aws-ids.yaml" |
3316 | + |
3317 | + def __init__( |
3318 | + self, |
3319 | + aws_access_key_id: "Optional[str]", |
3320 | + aws_secret_access_key: "Optional[str]", |
3321 | + machine_type: str, |
3322 | + region: "Optional[str]" = "us-east-2", |
3323 | + tag: "Optional[str]" = None, |
3324 | + timestamp_suffix: bool = True, |
3325 | + ) -> None: |
3326 | + self.aws_access_key_id = aws_access_key_id |
3327 | + self.aws_secret_access_key = aws_secret_access_key |
3328 | + logging.basicConfig( |
3329 | + filename="pycloudlib-behave.log", level=logging.DEBUG |
3330 | + ) |
3331 | + super().__init__( |
3332 | + region=region, |
3333 | + machine_type=machine_type, |
3334 | + tag=tag, |
3335 | + timestamp_suffix=timestamp_suffix, |
3336 | + ) |
3337 | + |
3338 | + @property |
3339 | + def api(self) -> pycloudlib.cloud.BaseCloud: |
3340 | + """Return the api used to interact with the cloud provider.""" |
3341 | + if self._api is None: |
3342 | + self._api = pycloudlib.EC2( |
3343 | + tag=self.tag, |
3344 | + access_key_id=self.aws_access_key_id, |
3345 | + secret_access_key=self.aws_secret_access_key, |
3346 | + region=self.region, |
3347 | + timestamp_suffix=self.timestamp_suffix, |
3348 | + ) |
3349 | + |
3350 | + return self._api |
3351 | + |
3352 | + def manage_ssh_key( |
3353 | + self, |
3354 | + private_key_path: "Optional[str]" = None, |
3355 | + key_name: "Optional[str]" = None, |
3356 | + ) -> None: |
3357 | + """Create and manage ssh key pairs to be used in the cloud provider. |
3358 | + |
3359 | + :param private_key_path: |
3360 | + Location of the private key path to use. If None, the location |
3361 | + will be a default location. |
3362 | + :param key_name: |
3363 | + Optional key_name to use when uploading to the cloud. Default is |
3364 | + uaclient-ci-<timestamp> |
3365 | + """ |
3366 | + if key_name: |
3367 | + self.key_name = key_name |
3368 | + if not private_key_path: |
3369 | + if self.key_name in self.api.list_keys(): |
3370 | + self.api.delete_key(self.key_name) |
3371 | + |
3372 | + private_key_path = "ec2-{}.pem".format(self.key_name) |
3373 | + print( |
3374 | + "--- Creating local keyfile {} for EC2".format( |
3375 | + private_key_path |
3376 | + ) |
3377 | + ) |
3378 | + keypair = self.api.client.create_key_pair(KeyName=self.key_name) |
3379 | + |
3380 | + with open(private_key_path, "w") as stream: |
3381 | + stream.write(keypair["KeyMaterial"]) |
3382 | + os.chmod(private_key_path, 0o600) |
3383 | + |
3384 | + self.api.use_key(private_key_path, private_key_path, self.key_name) |
3385 | + |
3386 | + def _create_instance( |
3387 | + self, |
3388 | + series: str, |
3389 | + instance_name: "Optional[str]" = None, |
3390 | + image_name: "Optional[str]" = None, |
3391 | + user_data: "Optional[str]" = None, |
3392 | + ) -> pycloudlib.instance: |
3393 | + """Launch an instance on the cloud provider. |
3394 | + |
3395 | + :param series: |
3396 | + The ubuntu release to be used when creating an instance. We will |
3397 | + create an image based on this value if the used does not provide |
3398 | + a image_name value |
3399 | + :param instance_name: |
3400 | + The name of the instance to be created |
3401 | + :param image_name: |
3402 | + The name of the image to be used when creating the instance |
3403 | + :param user_data: |
3404 | + The user data to be passed when creating the instance |
3405 | + |
3406 | + :returns: |
3407 | + An AWS cloud provider instance |
3408 | + """ |
3409 | + if not image_name: |
3410 | + image_name = self.locate_image_name(series) |
3411 | + |
3412 | + print("--- Launching AWS image {}({})".format(image_name, series)) |
3413 | + vpc = self.api.get_or_create_vpc(name="uaclient-integration") |
3414 | + |
3415 | + try: |
3416 | + inst = self.api.launch(image_name, user_data=user_data, vpc=vpc) |
3417 | + except Exception as e: |
3418 | + print(str(e)) |
3419 | + raise |
3420 | + |
3421 | + return inst |
3422 | + |
3423 | + |
3424 | +class Azure(Cloud): |
3425 | + """Class that represents the Azure cloud provider. |
3426 | + |
3427 | + :param az_client_id: |
3428 | + The Azure client id |
3429 | + :param az_client_secret |
3430 | + The Azure client secret |
3431 | + :param az_tenant_id: |
3432 | + The Azure tenant id |
3433 | + :param az_subscription_id: |
3434 | + The Azure subscription id |
3435 | + :machine_type: |
3436 | + A string representing the type of machine to launch (pro or generic) |
3437 | + :region: |
3438 | + The region to create the resources on |
3439 | + :tag: |
3440 | + A tag to be used when creating the resources on the cloud provider |
3441 | + :timestamp_suffix: |
3442 | + Boolean set true to direct pycloudlib to append a timestamp to the end |
3443 | + of the provided tag. |
3444 | + """ |
3445 | + |
3446 | + name = "Azure" |
3447 | + env_vars: "Tuple[str, ...]" = ( |
3448 | + "az_client_id", |
3449 | + "az_client_secret", |
3450 | + "az_tenant_id", |
3451 | + "az_subscription_id", |
3452 | + ) |
3453 | + pro_ids_path = "features/azure-ids.yaml" |
3454 | + |
3455 | + def __init__( |
3456 | + self, |
3457 | + machine_type: str, |
3458 | + region: "Optional[str]" = "centralus", |
3459 | + tag: "Optional[str]" = None, |
3460 | + timestamp_suffix: bool = True, |
3461 | + az_client_id: "Optional[str]" = None, |
3462 | + az_client_secret: "Optional[str]" = None, |
3463 | + az_tenant_id: "Optional[str]" = None, |
3464 | + az_subscription_id: "Optional[str]" = None, |
3465 | + ) -> None: |
3466 | + self.az_client_id = az_client_id |
3467 | + self.az_client_secret = az_client_secret |
3468 | + self.az_tenant_id = az_tenant_id |
3469 | + self.az_subscription_id = az_subscription_id |
3470 | + |
3471 | + super().__init__( |
3472 | + machine_type=machine_type, |
3473 | + region=region, |
3474 | + tag=tag, |
3475 | + timestamp_suffix=timestamp_suffix, |
3476 | + ) |
3477 | + |
3478 | + @property |
3479 | + def api(self) -> pycloudlib.cloud.BaseCloud: |
3480 | + """Return the api used to interact with the cloud provider.""" |
3481 | + if self._api is None: |
3482 | + self._api = pycloudlib.Azure( |
3483 | + tag=self.tag, |
3484 | + client_id=self.az_client_id, |
3485 | + client_secret=self.az_client_secret, |
3486 | + tenant_id=self.az_tenant_id, |
3487 | + subscription_id=self.az_subscription_id, |
3488 | + timestamp_suffix=self.timestamp_suffix, |
3489 | + ) |
3490 | + |
3491 | + return self._api |
3492 | + |
3493 | + def get_instance_id( |
3494 | + self, instance: pycloudlib.instance.BaseInstance |
3495 | + ) -> str: |
3496 | + """Return the instance identifier. |
3497 | + |
3498 | + :param instance: |
3499 | + An instance created on the cloud provider |
3500 | + |
3501 | + :returns: |
3502 | + The string of the unique instance id |
3503 | + """ |
3504 | + # For Azure, the API identifier uses the instance name |
3505 | + # instead of the instance id |
3506 | + return instance.name |
3507 | + |
3508 | + def manage_ssh_key(self, private_key_path: "Optional[str]" = None) -> None: |
3509 | + """Create and manage ssh key pairs to be used in the cloud provider. |
3510 | + |
3511 | + :param private_key_path: |
3512 | + Location of the private key path to use. If None, the location |
3513 | + will be a default location. |
3514 | + """ |
3515 | + if not private_key_path: |
3516 | + private_key_path = "azure-priv-{}.pem".format(self.key_name) |
3517 | + pub_key_path = "azure-pub-{}.txt".format(self.key_name) |
3518 | + print( |
3519 | + "--- Creating local keyfile {} for Azure".format( |
3520 | + private_key_path |
3521 | + ) |
3522 | + ) |
3523 | + if not os.path.exists(private_key_path): |
3524 | + pub_key, priv_key = self.api.create_key_pair( |
3525 | + key_name=self.key_name |
3526 | + ) |
3527 | + |
3528 | + with open(pub_key_path, "w") as stream: |
3529 | + stream.write(pub_key) |
3530 | + |
3531 | + with open(private_key_path, "w") as stream: |
3532 | + stream.write(priv_key) |
3533 | + |
3534 | + os.chmod(pub_key_path, 0o600) |
3535 | + os.chmod(private_key_path, 0o600) |
3536 | + |
3537 | + self.api.use_key(pub_key_path, private_key_path, self.key_name) |
3538 | + |
3539 | + def _create_instance( |
3540 | + self, |
3541 | + series: str, |
3542 | + instance_name: "Optional[str]" = None, |
3543 | + image_name: "Optional[str]" = None, |
3544 | + user_data: "Optional[str]" = None, |
3545 | + ) -> pycloudlib.instance: |
3546 | + """Launch an instance on the cloud provider. |
3547 | + |
3548 | + :param series: |
3549 | + The ubuntu release to be used when creating an instance. We will |
3550 | + create an image based on this value if the used does not provide |
3551 | + a image_name value |
3552 | + :param instance_name: |
3553 | + The name of the instance to be created |
3554 | + :param image_name: |
3555 | + The name of the image to be used when creating the instance |
3556 | + :param user_data: |
3557 | + The user data to be passed when creating the instance |
3558 | + |
3559 | + :returns: |
3560 | + An AWS cloud provider instance |
3561 | + """ |
3562 | + if not image_name: |
3563 | + image_name = self.locate_image_name(series) |
3564 | + |
3565 | + print("--- Launching Azure image {}({})".format(image_name, series)) |
3566 | + inst = self.api.launch(image_id=image_name, user_data=user_data) |
3567 | + return inst |
3568 | + |
3569 | + |
3570 | +class GCP(Cloud): |
3571 | + name = "gcp" |
3572 | + pro_ids_path = "features/gcp-ids.yaml" |
3573 | + |
3574 | + """Class that represents the Google Cloud Platform cloud provider. |
3575 | + |
3576 | + :param gcp_credentials_path |
3577 | + The GCP credentials path to use when authentiacting to GCP |
3578 | + :param gcp_project |
3579 | + The name of the GCP project to be used |
3580 | + :machine_type: |
3581 | + A string representing the type of machine to launch (pro or generic) |
3582 | + :region: |
3583 | + The region to create the resources on |
3584 | + :tag: |
3585 | + A tag to be used when creating the resources on the cloud provider |
3586 | + :timestamp_suffix: |
3587 | + Boolean set true to direct pycloudlib to append a timestamp to the end |
3588 | + of the provided tag. |
3589 | + """ |
3590 | + |
3591 | + env_vars: "Tuple[str, ...]" = ("gcp_credentials_path", "gcp_project") |
3592 | + |
3593 | + def __init__( |
3594 | + self, |
3595 | + machine_type: str, |
3596 | + region: "Optional[str]" = "us-west2", |
3597 | + tag: "Optional[str]" = None, |
3598 | + timestamp_suffix: bool = True, |
3599 | + zone: "Optional[str]" = "a", |
3600 | + gcp_credentials_path: "Optional[str]" = None, |
3601 | + gcp_project: "Optional[str]" = None, |
3602 | + ) -> None: |
3603 | + self.gcp_credentials_path = gcp_credentials_path |
3604 | + self.gcp_project = gcp_project |
3605 | + self.zone = zone |
3606 | + |
3607 | + super().__init__( |
3608 | + machine_type=machine_type, |
3609 | + region=region, |
3610 | + tag=tag, |
3611 | + timestamp_suffix=timestamp_suffix, |
3612 | + ) |
3613 | + |
3614 | + self._set_service_account_email() |
3615 | + |
3616 | + def _set_service_account_email(self): |
3617 | + """Set service account email if credentials provided.""" |
3618 | + json_credentials = {} |
3619 | + |
3620 | + if self.gcp_credentials_path: |
3621 | + with open(self.gcp_credentials_path, "r") as f: |
3622 | + json_credentials = json.load(f) |
3623 | + |
3624 | + self.service_account_email = json_credentials.get("client_email") |
3625 | + |
3626 | + @property |
3627 | + def api(self) -> pycloudlib.cloud.BaseCloud: |
3628 | + """Return the api used to interact with the cloud provider.""" |
3629 | + if self._api is None: |
3630 | + self._api = pycloudlib.GCE( |
3631 | + tag=self.tag, |
3632 | + timestamp_suffix=self.timestamp_suffix, |
3633 | + credentials_path=self.gcp_credentials_path, |
3634 | + project=self.gcp_project, |
3635 | + zone=self.zone, |
3636 | + region=self.region, |
3637 | + service_account_email=self.service_account_email, |
3638 | + ) |
3639 | + |
3640 | + return self._api |
3641 | + |
3642 | + def _create_instance( |
3643 | + self, |
3644 | + series: str, |
3645 | + instance_name: "Optional[str]" = None, |
3646 | + image_name: "Optional[str]" = None, |
3647 | + user_data: "Optional[str]" = None, |
3648 | + ) -> pycloudlib.instance: |
3649 | + """Launch an instance on the cloud provider. |
3650 | + |
3651 | + :param series: |
3652 | + The ubuntu release to be used when creating an instance. We will |
3653 | + create an image based on this value if the used does not provide |
3654 | + a image_name value |
3655 | + :param instance_name: |
3656 | + The name of the instance to be created |
3657 | + :param image_name: |
3658 | + The name of the image to be used when creating the instance |
3659 | + :param user_data: |
3660 | + The user data to be passed when creating the instance |
3661 | + |
3662 | + :returns: |
3663 | + An AWS cloud provider instance |
3664 | + """ |
3665 | + if not image_name: |
3666 | + image_name = self.locate_image_name(series) |
3667 | + |
3668 | + print("--- Launching GCP image {}({})".format(image_name, series)) |
3669 | + inst = self.api.launch(image_id=image_name, user_data=user_data) |
3670 | + return inst |
3671 | + |
3672 | + |
3673 | +class _LXD(Cloud): |
3674 | + name = "_lxd" |
3675 | + |
3676 | + @property |
3677 | + def pycloudlib_cls(self): |
3678 | + """Return the pycloudlib cls to be used as an api.""" |
3679 | + raise NotImplementedError |
3680 | + |
3681 | + def _create_instance( |
3682 | + self, |
3683 | + series: str, |
3684 | + instance_name: "Optional[str]" = None, |
3685 | + image_name: "Optional[str]" = None, |
3686 | + user_data: "Optional[str]" = None, |
3687 | + ) -> pycloudlib.instance: |
3688 | + """Launch an instance on the cloud provider. |
3689 | + |
3690 | + :param series: |
3691 | + The ubuntu release to be used when creating an instance. We will |
3692 | + create an image based on this value if the used does not provide |
3693 | + a image_name value |
3694 | + :param instance_name: |
3695 | + The name of the instance to be created |
3696 | + :param image_name: |
3697 | + The name of the image to be used when creating the instance |
3698 | + :param user_data: |
3699 | + The user data to be passed when creating the instance |
3700 | + |
3701 | + :returns: |
3702 | + An AWS cloud provider instance |
3703 | + """ |
3704 | + if not image_name: |
3705 | + image_name = self.locate_image_name(series) |
3706 | + |
3707 | + image_type = self.name.title().replace("-", " ") |
3708 | + |
3709 | + print( |
3710 | + "--- Launching {} image {}({})".format( |
3711 | + image_type, image_name, series |
3712 | + ) |
3713 | + ) |
3714 | + |
3715 | + inst = self.api.launch( |
3716 | + name=instance_name, image_id=image_name, user_data=user_data |
3717 | + ) |
3718 | + return inst |
3719 | + |
3720 | + def get_instance_id( |
3721 | + self, instance: pycloudlib.instance.BaseInstance |
3722 | + ) -> str: |
3723 | + """Return the instance identifier. |
3724 | + |
3725 | + :param instance: |
3726 | + An instance created on the cloud provider |
3727 | + |
3728 | + :returns: |
3729 | + The string of the unique instance id |
3730 | + """ |
3731 | + # For LXD, the API identifier uses the instance name |
3732 | + # instead of the instance id |
3733 | + return instance.name |
3734 | + |
3735 | + def locate_image_name(self, series: str) -> str: |
3736 | + """Locate and return the image name to use for vm provision. |
3737 | + |
3738 | + :param series: |
3739 | + The ubuntu release to be used when locating the image name |
3740 | + |
3741 | + :returns: |
3742 | + A image name to use when provisioning a virtual machine |
3743 | + based on the series value |
3744 | + """ |
3745 | + if not series: |
3746 | + raise ValueError( |
3747 | + "Must provide either series or image_name to launch azure" |
3748 | + ) |
3749 | + |
3750 | + image_name = self.api.daily_image(release=series) |
3751 | + return image_name |
3752 | + |
3753 | + @property |
3754 | + def api(self) -> pycloudlib.cloud.BaseCloud: |
3755 | + """Return the api used to interact with the cloud provider.""" |
3756 | + if self._api is None: |
3757 | + self._api = self.pycloudlib_cls( |
3758 | + tag=self.tag, timestamp_suffix=self.timestamp_suffix |
3759 | + ) |
3760 | + |
3761 | + return self._api |
3762 | + |
3763 | + |
3764 | +class LXDVirtualMachine(_LXD): |
3765 | + name = "lxd-virtual-machine" |
3766 | + |
3767 | + @property |
3768 | + def pycloudlib_cls(self): |
3769 | + """Return the pycloudlib cls to be used as an api.""" |
3770 | + return pycloudlib.LXDVirtualMachine |
3771 | + |
3772 | + |
3773 | +class LXDContainer(_LXD): |
3774 | + name = "lxd-container" |
3775 | + |
3776 | + @property |
3777 | + def pycloudlib_cls(self): |
3778 | + """Return the pycloudlib cls to be used as an api.""" |
3779 | + return pycloudlib.LXDContainer |
3780 | + |
3781 | + def manage_ssh_key(self, private_key_path: "Optional[str]" = None) -> None: |
3782 | + """Create and manage ssh key pairs to be used in the cloud provider. |
3783 | + |
3784 | + On a LXD container, we do not use ssh keys to communicate with the |
3785 | + instance. Therefore, this method should not be used. |
3786 | + |
3787 | + :param private_key_path: |
3788 | + Location of the private key path to use. If None, the location |
3789 | + will be a default location. |
3790 | + """ |
3791 | + pass |
3792 | diff --git a/features/environment.py b/features/environment.py |
3793 | index 54d00eb..9a53933 100644 |
3794 | --- a/features/environment.py |
3795 | +++ b/features/environment.py |
3796 | @@ -1,13 +1,70 @@ |
3797 | import datetime |
3798 | +import errno |
3799 | import os |
3800 | -import subprocess |
3801 | -from typing import Dict, Union |
3802 | +import itertools |
3803 | +import tempfile |
3804 | +import textwrap |
3805 | +import logging |
3806 | +import pycloudlib # type: ignore |
3807 | |
3808 | -from behave.model import Scenario |
3809 | +try: |
3810 | + from typing import Dict, Optional, Union, List, Tuple, Any # noqa: F401 |
3811 | +except ImportError: |
3812 | + # typing isn't available on trusty, so ignore its absence |
3813 | + pass |
3814 | + |
3815 | +from behave.model import Feature, Scenario |
3816 | |
3817 | from behave.runner import Context |
3818 | |
3819 | -from features.util import launch_lxd_container, lxc_exec |
3820 | +import features.cloud as cloud |
3821 | + |
3822 | +from features.util import emit_spinner_on_travis, lxc_get_property, build_debs |
3823 | + |
3824 | +ALL_SUPPORTED_SERIES = ["bionic", "focal", "trusty", "xenial"] |
3825 | + |
3826 | +DAILY_PPA = "http://ppa.launchpad.net/canonical-server/ua-client-daily/ubuntu" |
3827 | +DAILY_PPA_KEYID = "8A295C4FB8B190B7" |
3828 | + |
3829 | +USERDATA_BLOCK_AUTO_ATTACH_IMG = """\ |
3830 | +#cloud-config |
3831 | +bootcmd: |
3832 | + - cp /usr/bin/ua /usr/bin/ua.orig |
3833 | + - 'echo "#!/bin/sh\ndate >> /root/ua-calls\n" > /usr/bin/ua' |
3834 | + - chmod 755 /usr/bin/ua |
3835 | +""" |
3836 | + |
3837 | +USERDATA_APT_SOURCE_PPA_TRUSTY = """\ |
3838 | +apt_sources: # for trusty |
3839 | + - source: deb {ppa_url} $RELEASE main |
3840 | + keyid: {ppa_keyid} |
3841 | +packages: [{packages}] |
3842 | +""" |
3843 | + |
3844 | +USERDATA_APT_SOURCE_PPA = """\ |
3845 | +apt: |
3846 | + sources: |
3847 | + ua-tools-ppa: |
3848 | + source: deb {ppa_url} $RELEASE main |
3849 | + keyid: {ppa_keyid} |
3850 | +packages: [{packages}] |
3851 | +""" |
3852 | + |
3853 | +PROCESS_LOG_TMPL = """\ |
3854 | +returncode: {} |
3855 | +stdout: |
3856 | +{stdout} |
3857 | +stderr: |
3858 | +{stderr} |
3859 | +""" |
3860 | + |
3861 | +PROCESS_LOG_TMPL = """\ |
3862 | +returncode: {returncode} |
3863 | +stdout: |
3864 | +{stdout} |
3865 | +stderr: |
3866 | +{stderr} |
3867 | +""" |
3868 | |
3869 | |
3870 | class UAClientBehaveConfig: |
3871 | @@ -19,16 +76,32 @@ class UAClientBehaveConfig: |
3872 | |
3873 | :param contract_token: |
3874 | A valid contract token to use during attach scenarios |
3875 | + :param contract_token_staging: |
3876 | + A valid staging contract token to use during attach scenarios |
3877 | :param image_clean: |
3878 | This indicates whether the image created for this test run should be |
3879 | cleaned up when all tests are complete. |
3880 | + :param machine_type: |
3881 | + The default machine_type to test: lxd.container, lxd.vm, azure.pro, |
3882 | + azure.generic, aws.pro or aws.generic |
3883 | + :param private_key_file: |
3884 | + Optional path to pre-existing private key file to use when connecting |
3885 | + launched VMs via ssh. |
3886 | + :param private_key_name: |
3887 | + Optional name of the cloud's named private key object to use when |
3888 | + connecting to launched VMs via ssh. Default: uaclient-integration. |
3889 | :param reuse_image: |
3890 | A string with an image name that should be used instead of building a |
3891 | - fresh image for this test run. If specified, image_clean will be set |
3892 | - to False. |
3893 | + fresh image for this test run. If specified, this image will not be |
3894 | + deleted. |
3895 | :param destroy_instances: |
3896 | This boolean indicates that test containers should be destroyed after |
3897 | the completion. Set to False to leave instances running. |
3898 | + :param debs_path: |
3899 | + Location of the debs to be used when lauching a focal integration |
3900 | + test. If that path is None, we will build those debs locally. |
3901 | + :param artifact_dir: |
3902 | + Location where test artifacts are emitted. |
3903 | """ |
3904 | |
3905 | prefix = "UACLIENT_BEHAVE_" |
3906 | @@ -36,48 +109,200 @@ class UAClientBehaveConfig: |
3907 | # These variables are used in .from_environ() to convert the string |
3908 | # environment variable input to the appropriate Python types for use within |
3909 | # the test framework |
3910 | - boolean_options = ["image_clean", "destroy_instances"] |
3911 | - str_options = ["contract_token", "reuse_image"] |
3912 | - redact_options = ["contract_token"] |
3913 | + boolean_options = ["build_pr", "image_clean", "destroy_instances"] |
3914 | + str_options = [ |
3915 | + "aws_access_key_id", |
3916 | + "aws_secret_access_key", |
3917 | + "az_client_id", |
3918 | + "az_client_secret", |
3919 | + "az_tenant_id", |
3920 | + "az_subscription_id", |
3921 | + "gcp_credentials_path", |
3922 | + "gcp_project", |
3923 | + "contract_token", |
3924 | + "contract_token_staging", |
3925 | + "machine_type", |
3926 | + "private_key_file", |
3927 | + "private_key_name", |
3928 | + "reuse_image", |
3929 | + "debs_path", |
3930 | + "artifact_dir", |
3931 | + "ppa", |
3932 | + "ppa_keyid", |
3933 | + ] |
3934 | + redact_options = [ |
3935 | + "aws_access_key_id", |
3936 | + "aws_secret_access_key", |
3937 | + "az_client_id", |
3938 | + "az_client_secret", |
3939 | + "az_tenant_id", |
3940 | + "az_subscription_id", |
3941 | + "contract_token", |
3942 | + "contract_token_staging", |
3943 | + ] |
3944 | |
3945 | # This variable is used in .from_environ() but also to emit the "Config |
3946 | # options" stanza in __init__ |
3947 | all_options = boolean_options + str_options |
3948 | + cloud_api = None # type: pycloudlib.cloud.BaseCloud |
3949 | + cloud_manager = None # type: cloud.Cloud |
3950 | |
3951 | def __init__( |
3952 | self, |
3953 | *, |
3954 | + aws_access_key_id: str = None, |
3955 | + aws_secret_access_key: str = None, |
3956 | + az_client_id: str = None, |
3957 | + az_client_secret: str = None, |
3958 | + az_tenant_id: str = None, |
3959 | + az_subscription_id: str = None, |
3960 | + gcp_credentials_path: str = None, |
3961 | + gcp_project: str = None, |
3962 | + build_pr: bool = False, |
3963 | image_clean: bool = True, |
3964 | destroy_instances: bool = True, |
3965 | + machine_type: str = "lxd.container", |
3966 | + private_key_file: str = None, |
3967 | + private_key_name: str = "uaclient-integration", |
3968 | reuse_image: str = None, |
3969 | - contract_token: str = None |
3970 | + contract_token: str = None, |
3971 | + contract_token_staging: str = None, |
3972 | + debs_path: str = None, |
3973 | + artifact_dir: str = None, |
3974 | + ppa: str = DAILY_PPA, |
3975 | + ppa_keyid: str = DAILY_PPA_KEYID, |
3976 | + cmdline_tags: "List" = [] |
3977 | ) -> None: |
3978 | # First, store the values we've detected |
3979 | + self.aws_access_key_id = aws_access_key_id |
3980 | + self.aws_secret_access_key = aws_secret_access_key |
3981 | + self.az_client_id = az_client_id |
3982 | + self.az_client_secret = az_client_secret |
3983 | + self.az_tenant_id = az_tenant_id |
3984 | + self.az_subscription_id = az_subscription_id |
3985 | + self.gcp_credentials_path = gcp_credentials_path |
3986 | + self.gcp_project = gcp_project |
3987 | + self.build_pr = build_pr |
3988 | self.contract_token = contract_token |
3989 | + self.contract_token_staging = contract_token_staging |
3990 | self.image_clean = image_clean |
3991 | self.destroy_instances = destroy_instances |
3992 | + self.machine_type = machine_type |
3993 | + self.private_key_file = private_key_file |
3994 | + self.private_key_name = private_key_name |
3995 | self.reuse_image = reuse_image |
3996 | - |
3997 | + self.cmdline_tags = cmdline_tags |
3998 | + self.debs_path = debs_path |
3999 | + self.artifact_dir = artifact_dir |
4000 | + self.ppa = ppa |
4001 | + self.ppa_keyid = ppa_keyid |
4002 | + self.filter_series = set( |
4003 | + [ |
4004 | + tag.split(".")[1] |
4005 | + for tag in cmdline_tags |
4006 | + if tag.startswith("series.") and "series.all" not in tag |
4007 | + ] |
4008 | + ) |
4009 | # Next, perform any required validation |
4010 | if self.reuse_image is not None: |
4011 | if self.image_clean: |
4012 | - print("reuse_image specified, setting image_clean = False") |
4013 | - self.image_clean = False |
4014 | + print(" Reuse_image specified, it will not be deleted.") |
4015 | + |
4016 | + ignore_vars = () # type: Tuple[str, ...] |
4017 | + if "aws" not in self.machine_type: |
4018 | + ignore_vars += cloud.EC2.env_vars |
4019 | + if "azure" not in self.machine_type: |
4020 | + ignore_vars += cloud.Azure.env_vars |
4021 | + if "gcp" not in self.machine_type: |
4022 | + ignore_vars += cloud.GCP.env_vars |
4023 | + if "pro" in self.machine_type: |
4024 | + ignore_vars += ( |
4025 | + "UACLIENT_BEHAVE_CONTRACT_TOKEN", |
4026 | + "UACLIENT_BEHAVE_CONTRACT_TOKEN_STAGING", |
4027 | + ) |
4028 | + for env_name in ignore_vars: |
4029 | + attr_name = env_name.replace("UACLIENT_BEHAVE_", "").lower() |
4030 | + if getattr(self, attr_name): |
4031 | + print( |
4032 | + " --- Ignoring {} because machine_type is {}".format( |
4033 | + env_name, self.machine_type |
4034 | + ) |
4035 | + ) |
4036 | + setattr(self, attr_name, None) |
4037 | + timed_job_tag = datetime.datetime.utcnow().strftime( |
4038 | + "uaclient-ci-%m%d-%H%M-" |
4039 | + ) |
4040 | + # Jenkinsfile provides us with UACLIENT_BEHAVE_JENKINS_BUILD_TAG |
4041 | + job_suffix = os.environ.get("UACLIENT_BEHAVE_JENKINS_BUILD_TAG") |
4042 | + print("--- job suffix: {}".format(job_suffix), flush=True) |
4043 | + if not job_suffix: |
4044 | + job_suffix = os.environ.get("CHANGE_ID", "dev") |
4045 | + else: |
4046 | + job_suffix = job_suffix.split("PR-")[-1] |
4047 | + timed_job_tag += str(job_suffix) |
4048 | + timed_job_tag = timed_job_tag.replace(".", "-") |
4049 | + if "aws" in self.machine_type: |
4050 | + self.cloud_manager = cloud.EC2( |
4051 | + aws_access_key_id, |
4052 | + aws_secret_access_key, |
4053 | + region=os.environ.get("AWS_DEFAULT_REGION", "us-east-2"), |
4054 | + machine_type=self.machine_type, |
4055 | + tag=timed_job_tag, |
4056 | + timestamp_suffix=False, |
4057 | + ) |
4058 | + elif "azure" in self.machine_type: |
4059 | + self.cloud_manager = cloud.Azure( |
4060 | + az_client_id=az_client_id, |
4061 | + az_client_secret=az_client_secret, |
4062 | + az_tenant_id=az_tenant_id, |
4063 | + az_subscription_id=az_subscription_id, |
4064 | + machine_type=self.machine_type, |
4065 | + tag=timed_job_tag, |
4066 | + timestamp_suffix=False, |
4067 | + ) |
4068 | + elif "gcp" in self.machine_type: |
4069 | + self.cloud_manager = cloud.GCP( |
4070 | + machine_type=self.machine_type, |
4071 | + tag=timed_job_tag, |
4072 | + timestamp_suffix=False, |
4073 | + gcp_credentials_path=self.gcp_credentials_path, |
4074 | + gcp_project=gcp_project, |
4075 | + ) |
4076 | + elif "lxd.vm" in self.machine_type: |
4077 | + self.cloud_manager = cloud.LXDVirtualMachine( |
4078 | + machine_type=self.machine_type |
4079 | + ) |
4080 | + else: |
4081 | + self.cloud_manager = cloud.LXDContainer( |
4082 | + machine_type=self.machine_type |
4083 | + ) |
4084 | + |
4085 | + self.cloud_api = self.cloud_manager.api |
4086 | |
4087 | # Finally, print the config options. This helps users debug the use of |
4088 | # config options, and means they'll be included in test logs in CI. |
4089 | print("Config options:") |
4090 | for option in self.all_options: |
4091 | - value = getattr(self, option, "ERROR") |
4092 | - if option in self.redact_options and value not in (None, "ERROR"): |
4093 | + value = getattr(self, option, "<UNSET>") |
4094 | + if option in self.redact_options and value not in ( |
4095 | + None, |
4096 | + "<UNSET>", |
4097 | + ): |
4098 | value = "<REDACTED>" |
4099 | print(" {}".format(option), "=", value) |
4100 | |
4101 | @classmethod |
4102 | - def from_environ(cls) -> "UAClientBehaveConfig": |
4103 | + def from_environ(cls, config) -> "UAClientBehaveConfig": |
4104 | """Gather config options from os.environ and return a config object""" |
4105 | # First, gather all known options |
4106 | - kwargs: Dict[str, Union[str, bool]] = {} |
4107 | + kwargs: Dict[str, Union[str, bool, "List"]] = {} |
4108 | + # Preserve cmdline_tags for reference |
4109 | + if not config.tags.ands: |
4110 | + kwargs["cmdline_tags"] = [] |
4111 | + else: |
4112 | + kwargs["cmdline_tags"] = list( |
4113 | + itertools.chain.from_iterable(config.tags.ands) |
4114 | + ) |
4115 | for key, value in os.environ.items(): |
4116 | if not key.startswith(cls.prefix): |
4117 | continue |
4118 | @@ -98,96 +323,440 @@ class UAClientBehaveConfig: |
4119 | |
4120 | |
4121 | def before_all(context: Context) -> None: |
4122 | - """behave will invoke this before anything else happens. |
4123 | - |
4124 | - In this function, we launch a container, install ubuntu-advantage-tools and |
4125 | - then capture an image. This image is then reused by each feature, reducing |
4126 | - test execution time. |
4127 | - """ |
4128 | + """behave will invoke this before anything else happens.""" |
4129 | + context.config.setup_logging() |
4130 | userdata = context.config.userdata |
4131 | - context.reuse_container = userdata.get("reuse_container") |
4132 | - context.config = UAClientBehaveConfig.from_environ() |
4133 | - if context.config.reuse_image is None: |
4134 | - create_trusty_uat_lxd_image(context) |
4135 | - else: |
4136 | - context.image_name = context.config.reuse_image |
4137 | - |
4138 | - |
4139 | -def before_scenario(context: Context, scenario: Scenario): |
4140 | - for tag in scenario.effective_tags: |
4141 | + if userdata: |
4142 | + logging.debug("Userdata key / value pairs:") |
4143 | + print("Userdata key / value pairs:") |
4144 | + for key, value in userdata.items(): |
4145 | + logging.debug(" - {} = {}".format(key, value)) |
4146 | + print(" - {} = {}".format(key, value)) |
4147 | + context.series_image_name = {} |
4148 | + context.series_reuse_image = "" |
4149 | + context.reuse_container = {} |
4150 | + context.config = UAClientBehaveConfig.from_environ(context.config) |
4151 | + context.config.cloud_manager.manage_ssh_key() |
4152 | + |
4153 | + if context.config.reuse_image: |
4154 | + series = lxc_get_property( |
4155 | + context.config.reuse_image, property_name="series", image=True |
4156 | + ) |
4157 | + machine_type = lxc_get_property( |
4158 | + context.config.reuse_image, |
4159 | + property_name="machine_type", |
4160 | + image=True, |
4161 | + ) |
4162 | + if machine_type: |
4163 | + print("Found machine_type: {vm_type}".format(vm_type=machine_type)) |
4164 | + if series is not None: |
4165 | + context.series_reuse_image = series |
4166 | + context.series_image_name[series] = context.config.reuse_image |
4167 | + else: |
4168 | + print(" Could not check image series. It will not be used. ") |
4169 | + context.config.reuse_image = None |
4170 | + |
4171 | + if userdata.get("reuse_container"): |
4172 | + inst = context.config.cloud_api.get_instance( |
4173 | + userdata.get("reuse_container") |
4174 | + ) |
4175 | + codename = inst.execute( |
4176 | + ["grep", "UBUNTU_CODENAME", "/etc/os-release"] |
4177 | + ).strip() |
4178 | + [_, series] = codename.split("=") |
4179 | + |
4180 | + context.reuse_container = {series: userdata.get("reuse_container")} |
4181 | + print( |
4182 | + textwrap.dedent( |
4183 | + """ |
4184 | + You are providing a {series} container. Make sure you are running |
4185 | + this series tests. For instance: --tags=series.{series}""".format( |
4186 | + series=series |
4187 | + ) |
4188 | + ) |
4189 | + ) |
4190 | + |
4191 | + |
4192 | +def _should_skip_tags(context: Context, tags: "List") -> str: |
4193 | + """Return a reason if a feature or scenario should be skipped""" |
4194 | + machine_type = getattr(context.config, "machine_type", "") |
4195 | + machine_types = [] |
4196 | + |
4197 | + for tag in tags: |
4198 | parts = tag.split(".") |
4199 | - if parts[0] == "uses": |
4200 | - val = context |
4201 | - for attr in parts[1:]: |
4202 | - val = getattr(val, attr, None) |
4203 | - if val is None: |
4204 | - scenario.skip( |
4205 | - reason="Skipped because tag value was None: {}".format( |
4206 | - tag |
4207 | + if parts[0] != "uses": |
4208 | + continue # Only process @uses.* tags for skipping: |
4209 | + val = context |
4210 | + for idx, attr in enumerate(parts[1:], 1): |
4211 | + val = getattr(val, attr, None) |
4212 | + if attr == "machine_type": |
4213 | + curr_machine_type = ".".join(parts[idx + 1 :]) |
4214 | + machine_types.append(curr_machine_type) |
4215 | + if curr_machine_type == machine_type: |
4216 | + if machine_type.startswith("lxd"): |
4217 | + return "" |
4218 | + |
4219 | + cloud_manager = context.config.cloud_manager |
4220 | + if cloud_manager and cloud_manager.missing_env_vars(): |
4221 | + return "".join( |
4222 | + ( |
4223 | + "Skipped: {} machine_type requires:\n".format( |
4224 | + machine_type |
4225 | + ), |
4226 | + *cloud_manager.format_missing_env_vars( |
4227 | + cloud_manager.missing_env_vars() |
4228 | + ), |
4229 | + ) |
4230 | ) |
4231 | - ) |
4232 | + return "" |
4233 | + break |
4234 | + if val is None: |
4235 | + return "Skipped: tag value was None: {}".format(tag) |
4236 | + |
4237 | + if machine_types: |
4238 | + return "Skipped: machine type {} was not found in tags:\n {}".format( |
4239 | + machine_type, ", ".join(machine_types) |
4240 | + ) |
4241 | + |
4242 | + return "" |
4243 | + |
4244 | |
4245 | +def before_feature(context: Context, feature: Feature): |
4246 | + reason = _should_skip_tags(context, feature.tags) |
4247 | + if reason: |
4248 | + feature.skip(reason=reason) |
4249 | |
4250 | -def _capture_container_as_image(container_name: str, image_name: str) -> None: |
4251 | - """Capture a lxd container as an image. |
4252 | + |
4253 | +def before_scenario(context: Context, scenario: Scenario): |
4254 | + """ |
4255 | + In this function, we launch a container, install ubuntu-advantage-tools and |
4256 | + then capture an image. This image is then reused by each scenario, reducing |
4257 | + test execution time. |
4258 | + """ |
4259 | + reason = _should_skip_tags(context, scenario.effective_tags) |
4260 | + if reason: |
4261 | + scenario.skip(reason=reason) |
4262 | + |
4263 | + |
4264 | +FAILURE_FILES = ( |
4265 | + "/etc/ubuntu-advantage/uaclient.log", |
4266 | + "/var/log/cloud-init.log", |
4267 | + "/var/log/ubuntu-advantage.log", |
4268 | + "/var/lib/cloud/instance/user-data.txt", |
4269 | + "/var/lib/cloud/instance/vendor-data.txt", |
4270 | +) |
4271 | +FAILURE_CMDS = { |
4272 | + "ua-version": ["ua", "version"], |
4273 | + "cloud-init-analyze": ["cloud-init", "analyze", "show"], |
4274 | + "cloud-init.status": ["cloud-init", "status", "--long"], |
4275 | + "status.json": ["ua", "status", "--all", "--format=json"], |
4276 | + "journal.log": ["journalctl", "-b", "0"], |
4277 | + "systemd-analyze-blame": ["systemd-analyze", "blame"], |
4278 | + "systemctl-status": ["systemctl", "status"], |
4279 | + "systemctl-status-ua-auto-attach": [ |
4280 | + "systemctl", |
4281 | + "status", |
4282 | + "ua-auto-attach.service", |
4283 | + ], |
4284 | + "systemctl-status-ua-reboot-cmds": [ |
4285 | + "systemctl", |
4286 | + "status", |
4287 | + "ua-reboot-cmds.service", |
4288 | + ], |
4289 | +} |
4290 | + |
4291 | + |
4292 | +def after_step(context, step): |
4293 | + """Collect test artifacts in the event of failure.""" |
4294 | + if step.status == "failed": |
4295 | + if context.config.artifact_dir: |
4296 | + artifacts_dir = context.config.artifact_dir |
4297 | + else: |
4298 | + artifacts_dir = "artifacts" |
4299 | + artifacts_dir = os.path.join( |
4300 | + artifacts_dir, |
4301 | + "{}_{}".format(os.path.basename(step.filename), step.line), |
4302 | + ) |
4303 | + if hasattr(context, "process"): |
4304 | + if not os.path.exists(artifacts_dir): |
4305 | + os.makedirs(artifacts_dir) |
4306 | + artifact_file = os.path.join(artifacts_dir, "process.log") |
4307 | + process = context.process |
4308 | + with open(artifact_file, "w") as stream: |
4309 | + stream.write( |
4310 | + PROCESS_LOG_TMPL.format( |
4311 | + returncode=process.returncode, |
4312 | + stdout=process.stdout, |
4313 | + stderr=process.stderr, |
4314 | + ) |
4315 | + ) |
4316 | + |
4317 | + if hasattr(context, "instance"): |
4318 | + if not os.path.exists(artifacts_dir): |
4319 | + os.makedirs(artifacts_dir) |
4320 | + for log_file in FAILURE_FILES: |
4321 | + artifact_file = os.path.join( |
4322 | + artifacts_dir, os.path.basename(log_file) |
4323 | + ) |
4324 | + print("-- pull instance:{} {}".format(log_file, artifact_file)) |
4325 | + try: |
4326 | + context.instance.pull_file(log_file, artifact_file) |
4327 | + except IOError as e: |
4328 | + if e.errno == errno.EACCES: |
4329 | + result = context.instance.execute( |
4330 | + ["cat", log_file], use_sudo=True |
4331 | + ) |
4332 | + with open(artifact_file, "w") as stream: |
4333 | + stream.write(result.stdout) |
4334 | + except RuntimeError: |
4335 | + # File did not exist |
4336 | + with open(artifact_file, "w") as stream: |
4337 | + stream.write("") |
4338 | + for artifact_file, cmd in FAILURE_CMDS.items(): |
4339 | + result = context.instance.execute(cmd, use_sudo=True) |
4340 | + artifact_file = os.path.join(artifacts_dir, artifact_file) |
4341 | + with open(artifact_file, "w") as stream: |
4342 | + stream.write(result.stdout) |
4343 | + |
4344 | + |
4345 | +def after_all(context): |
4346 | + if context.config.image_clean: |
4347 | + for key, image in context.series_image_name.items(): |
4348 | + if key == context.series_reuse_image: |
4349 | + print( |
4350 | + " Not deleting this image: ", |
4351 | + context.series_image_name[key], |
4352 | + ) |
4353 | + else: |
4354 | + context.config.cloud_api.delete_image(image) |
4355 | + |
4356 | + |
4357 | +def _capture_container_as_image( |
4358 | + container_name: str, |
4359 | + image_name: str, |
4360 | + cloud_api: "pycloudlib.cloud.BaseCloud", |
4361 | +) -> str: |
4362 | + """Capture a container as an image. |
4363 | |
4364 | :param container_name: |
4365 | The name of the container to be captured. Note that this container |
4366 | will be stopped. |
4367 | :param image_name: |
4368 | The name under which the image should be published. |
4369 | + :param cloud_api: Optional pycloud BaseCloud api for applicable |
4370 | + machine_types. |
4371 | + """ |
4372 | + print( |
4373 | + "--- Creating base image snapshot from vm {}".format(container_name) |
4374 | + ) |
4375 | + inst = cloud_api.get_instance(container_name) |
4376 | + return cloud_api.snapshot(instance=inst) |
4377 | + |
4378 | + |
4379 | +def build_debs_from_dev_instance(context: Context, series: str) -> "List[str]": |
4380 | + """Create a development instance, instal build dependencies and build debs |
4381 | + |
4382 | + |
4383 | + Will stop the development instance after deb build succeeds. |
4384 | + |
4385 | + :return: A list of paths to applicable deb files published. |
4386 | """ |
4387 | - subprocess.run(["lxc", "stop", container_name]) |
4388 | - subprocess.run(["lxc", "publish", container_name, "--alias", image_name]) |
4389 | + time_suffix = datetime.datetime.now().strftime("%s%f") |
4390 | + deb_paths = [] |
4391 | + |
4392 | + if context.config.debs_path: |
4393 | + print( |
4394 | + "--- Checking if debs can be reused in {}".format( |
4395 | + context.config.debs_path |
4396 | + ) |
4397 | + ) |
4398 | + debs_path = context.config.debs_path |
4399 | + if os.path.isdir(debs_path): |
4400 | + deb_paths = [ |
4401 | + os.path.join(debs_path, deb_file) |
4402 | + for deb_file in os.listdir(debs_path) |
4403 | + if series in deb_file |
4404 | + ] |
4405 | + |
4406 | + if len(deb_paths): |
4407 | + print("--- Reusing debs: {}".format(", ".join(deb_paths))) |
4408 | + else: |
4409 | + print("--- Could not find any debs to reuse. Building it locally") |
4410 | + print( |
4411 | + "--- Launching vm to build ubuntu-advantage*debs from local source" |
4412 | + ) |
4413 | + build_container_name = ( |
4414 | + "ubuntu-behave-image-pre-build-%s-" % series + time_suffix |
4415 | + ) |
4416 | + |
4417 | + cloud_manager = context.config.cloud_manager |
4418 | + if "pro" in context.config.machine_type: |
4419 | + user_data = USERDATA_BLOCK_AUTO_ATTACH_IMG |
4420 | + else: |
4421 | + user_data = "" |
4422 | + inst = cloud_manager.launch( |
4423 | + instance_name=build_container_name, |
4424 | + series=series, |
4425 | + user_data=user_data, |
4426 | + ) |
4427 | + |
4428 | + build_container_name = cloud_manager.get_instance_id(inst) |
4429 | |
4430 | + with emit_spinner_on_travis("Building debs from local source... "): |
4431 | + deb_paths = build_debs( |
4432 | + build_container_name, |
4433 | + output_deb_dir=os.path.join(tempfile.gettempdir(), series), |
4434 | + cloud_api=context.config.cloud_api, |
4435 | + ) |
4436 | |
4437 | -def create_trusty_uat_lxd_image(context: Context) -> None: |
4438 | - """Create a trusty lxd image with ubuntu-advantage-tools installed |
4439 | + if "pro" in context.config.machine_type: |
4440 | + return deb_paths |
4441 | + # Redact ubuntu-advantage-pro deb as inapplicable |
4442 | + return [deb_path for deb_path in deb_paths if "pro" not in deb_path] |
4443 | + |
4444 | + |
4445 | +def create_uat_image(context: Context, series: str) -> None: |
4446 | + """Create a given series lxd image with ubuntu-advantage-tools installed |
4447 | |
4448 | This will launch a container, install ubuntu-advantage-tools, and publish |
4449 | - the image. The image's name is stored in context.image_name for use within |
4450 | - step code. |
4451 | + the image. The image's name is stored in context.series_image_name for |
4452 | + use within step code. |
4453 | |
4454 | :param context: |
4455 | - A `behave.runner.Context`; this will have `image_name` set on it. |
4456 | + A `behave.runner.Context`; this will have `series.image_name` set on |
4457 | + it. |
4458 | + :param series: |
4459 | + A string representing the series name to create |
4460 | """ |
4461 | |
4462 | - def image_cleanup() -> None: |
4463 | - if context.config.image_clean: |
4464 | - subprocess.run(["lxc", "image", "delete", context.image_name]) |
4465 | + if series in context.reuse_container: |
4466 | + print( |
4467 | + "\n Reusing the existing container: ", |
4468 | + context.reuse_container[series], |
4469 | + ) |
4470 | + return |
4471 | + time_suffix = datetime.datetime.now().strftime("%s%f") |
4472 | + deb_paths = [] |
4473 | + if context.config.build_pr: |
4474 | + deb_paths = build_debs_from_dev_instance(context, series) |
4475 | + |
4476 | + print( |
4477 | + "--- Launching VM to create a base image with updated ubuntu-advantage" |
4478 | + ) |
4479 | + |
4480 | + is_vm = bool(context.config.machine_type == "lxd.vm") |
4481 | + build_container_name = "ubuntu-behave-image-build-%s-%s" % ( |
4482 | + "-vm" if is_vm else "", |
4483 | + series + time_suffix, |
4484 | + ) |
4485 | + |
4486 | + user_data = "" |
4487 | + if "pro" in context.config.machine_type: |
4488 | + user_data = USERDATA_BLOCK_AUTO_ATTACH_IMG |
4489 | + if not deb_paths: |
4490 | + if not user_data: |
4491 | + user_data = "#cloud-config\n" |
4492 | + ppa = context.config.ppa |
4493 | + ppa_keyid = context.config.ppa_keyid |
4494 | + if context.config.ppa.startswith("ppa:"): |
4495 | + ppa = ppa.replace("ppa:", "http://ppa.launchpad.net/") + "/ubuntu" |
4496 | + if series == "trusty": |
4497 | + packages = ["ubuntu-advantage-tools"] |
4498 | + |
4499 | + if "pro" in context.config.machine_type: |
4500 | + packages.append("ubuntu-advantage-pro") |
4501 | + |
4502 | + user_data += USERDATA_APT_SOURCE_PPA_TRUSTY.format( |
4503 | + ppa_url=ppa, ppa_keyid=ppa_keyid, packages=", ".join(packages) |
4504 | + ) |
4505 | else: |
4506 | - print("Image cleanup disabled, not deleting:", context.image_name) |
4507 | + packages = ["openssh-server", "ubuntu-advantage-tools"] |
4508 | |
4509 | - if context.reuse_container: |
4510 | - print(" Reusing the existent container: ", context.reuse_container) |
4511 | - else: |
4512 | - now = datetime.datetime.now() |
4513 | - context.image_name = "behave-image-" + now.strftime("%s%f") |
4514 | - build_container_name = "behave-image-build-" + now.strftime("%s%f") |
4515 | - launch_lxd_container(context, "ubuntu:trusty", build_container_name) |
4516 | - _install_uat_in_container(build_container_name) |
4517 | - _capture_container_as_image(build_container_name, context.image_name) |
4518 | - context.add_cleanup(image_cleanup) |
4519 | + if "pro" in context.config.machine_type: |
4520 | + packages.append("ubuntu-advantage-pro") |
4521 | |
4522 | + user_data += USERDATA_APT_SOURCE_PPA.format( |
4523 | + ppa_url=ppa, ppa_keyid=ppa_keyid, packages=", ".join(packages) |
4524 | + ) |
4525 | + inst = context.config.cloud_manager.launch( |
4526 | + instance_name=build_container_name, series=series, user_data=user_data |
4527 | + ) |
4528 | + build_container_name = context.config.cloud_manager.get_instance_id(inst) |
4529 | |
4530 | -def _install_uat_in_container(container_name: str) -> None: |
4531 | + _install_uat_in_container( |
4532 | + build_container_name, |
4533 | + series=series, |
4534 | + config=context.config, |
4535 | + deb_paths=deb_paths, |
4536 | + ) |
4537 | + |
4538 | + image_name = _capture_container_as_image( |
4539 | + build_container_name, |
4540 | + image_name="ubuntu-behave-image-%s-" % series + time_suffix, |
4541 | + cloud_api=context.config.cloud_api, |
4542 | + ) |
4543 | + context.series_image_name[series] = image_name |
4544 | + inst.delete(wait=False) |
4545 | + |
4546 | + |
4547 | +def _install_uat_in_container( |
4548 | + container_name: str, |
4549 | + series: str, |
4550 | + config: UAClientBehaveConfig, |
4551 | + deb_paths: "Optional[List[str]]" = None, |
4552 | +) -> None: |
4553 | """Install ubuntu-advantage-tools into the specified container |
4554 | |
4555 | :param container_name: |
4556 | The name of the container into which ubuntu-advantage-tools should be |
4557 | installed. |
4558 | + :param series: The name of the series that is being used |
4559 | + :param config: UAClientBehaveConfig |
4560 | + :param deb_paths: Optional paths to local deb files we need to install |
4561 | """ |
4562 | - lxc_exec( |
4563 | - container_name, |
4564 | - [ |
4565 | - "sudo", |
4566 | - "add-apt-repository", |
4567 | - "--yes", |
4568 | - "ppa:canonical-server/ua-client-daily", |
4569 | - ], |
4570 | - ) |
4571 | - lxc_exec(container_name, ["sudo", "apt-get", "update", "-qq"]) |
4572 | - lxc_exec( |
4573 | - container_name, |
4574 | - ["sudo", "apt-get", "install", "-qq", "-y", "ubuntu-advantage-tools"], |
4575 | - ) |
4576 | + cmds: "List[Any]" = [["systemctl", "is-system-running", "--wait"]] |
4577 | + |
4578 | + if deb_paths is None: |
4579 | + deb_paths = [] |
4580 | + |
4581 | + if deb_paths: |
4582 | + cmds.append(["sudo", "apt-get", "update", "-qqy"]) |
4583 | + |
4584 | + deb_files = [] |
4585 | + inst = config.cloud_api.get_instance(container_name) |
4586 | + |
4587 | + for deb_file in deb_paths: |
4588 | + if "pro" in deb_file and "pro" not in config.machine_type: |
4589 | + continue |
4590 | + |
4591 | + deb_name = os.path.basename(deb_file) |
4592 | + deb_files.append("/tmp/" + deb_name) |
4593 | + inst.push_file(deb_file, "/tmp/" + deb_name) |
4594 | + |
4595 | + if series == "trusty": |
4596 | + cmds.append(["sudo", "dpkg", "-i"] + deb_files) |
4597 | + else: |
4598 | + cmds.append(["sudo", "apt-get", "install", "-y"] + deb_files) |
4599 | + |
4600 | + if "pro" in config.machine_type: |
4601 | + features = "features:\n disable_auto_attach: true\n" |
4602 | + conf_path = "/etc/ubuntu-advantage/uaclient.conf" |
4603 | + cmd = "printf '{}' > /tmp/uaclient.conf".format(features) |
4604 | + cmds.append('sh -c "{}"'.format(cmd)) |
4605 | + cmds.append( |
4606 | + 'sudo -- sh -c "cat /tmp/uaclient.conf >> {}"'.format(conf_path) |
4607 | + ) |
4608 | + cmds.append("sudo ua detach --assume-yes") |
4609 | + |
4610 | + cmds.append(["ua", "version"]) |
4611 | + instance = config.cloud_api.get_instance(container_name) |
4612 | + for cmd in cmds: # type: ignore |
4613 | + result = instance.execute(cmd) |
4614 | + if result.failed: |
4615 | + print( |
4616 | + "--- Failed {}: out {} err {}".format( |
4617 | + cmd, result.stdout, result.stderr |
4618 | + ) |
4619 | + ) |
4620 | + elif "version" in cmd: |
4621 | + print("--- " + result) |
4622 | diff --git a/features/gcp-ids.yaml b/features/gcp-ids.yaml |
4623 | new file mode 100644 |
4624 | index 0000000..a3ca5bd |
4625 | --- /dev/null |
4626 | +++ b/features/gcp-ids.yaml |
4627 | @@ -0,0 +1,3 @@ |
4628 | +xenial: "projects/ubuntu-os-cloud-image-proposed/global/images/testing-ubuntu-pro-1604-xenial-v20210205" |
4629 | +bionic: "projects/ubuntu-os-cloud-image-proposed/global/images/testing-ubuntu-pro-1804-bionic-v20210205" |
4630 | +focal: "projects/ubuntu-os-cloud-image-proposed/global/images/testing-ubuntu-pro-2004-focal-v20210205" |
4631 | diff --git a/features/staging_commands.feature b/features/staging_commands.feature |
4632 | new file mode 100644 |
4633 | index 0000000..90c212f |
4634 | --- /dev/null |
4635 | +++ b/features/staging_commands.feature |
4636 | @@ -0,0 +1,395 @@ |
4637 | +@uses.config.contract_token_staging |
4638 | +Feature: Enable command behaviour when attached to an UA staging subscription |
4639 | + |
4640 | + @series.xenial |
4641 | + Scenario: Attached enable CC EAL service in a xenial lxd container |
4642 | + Given a `xenial` machine with ubuntu-advantage-tools installed |
4643 | + When I attach `contract_token_staging` with sudo |
4644 | + Then I verify that running `ua enable cc-eal` `as non-root` exits `1` |
4645 | + And I will see the following on stderr: |
4646 | + """ |
4647 | + This command must be run as root (try using sudo) |
4648 | + """ |
4649 | + When I run `ua enable cc-eal --beta` with sudo |
4650 | + Then I will see the following on stdout: |
4651 | + """ |
4652 | + One moment, checking your subscription first |
4653 | + GPG key '/usr/share/keyrings/ubuntu-cc-keyring.gpg' not found |
4654 | + """ |
4655 | + @series.xenial |
4656 | + @series.bionic |
4657 | + @series.focal |
4658 | + Scenario Outline: Attached enable esm-apps on a machine |
4659 | + Given a `<release>` machine with ubuntu-advantage-tools installed |
4660 | + When I attach `contract_token_staging` with sudo |
4661 | + And I run `ua status --all` as non-root |
4662 | + Then stdout matches regexp |
4663 | + """ |
4664 | + esm-apps yes enabled UA Apps: Extended Security Maintenance \(ESM\) |
4665 | + """ |
4666 | + And I verify that running `apt update` `with sudo` exits `0` |
4667 | + When I run `apt-cache policy` as non-root |
4668 | + Then apt-cache policy for the following url has permission `500` |
4669 | + """ |
4670 | + https://esm.staging.ubuntu.com/apps/ubuntu <release>-apps-updates/main amd64 Packages |
4671 | + """ |
4672 | + And apt-cache policy for the following url has permission `500` |
4673 | + """ |
4674 | + https://esm.staging.ubuntu.com/apps/ubuntu <release>-apps-security/main amd64 Packages |
4675 | + """ |
4676 | + And I verify that running `apt update` `with sudo` exits `0` |
4677 | + When I run `apt install -y <apps-pkg>` with sudo, retrying exit [100] |
4678 | + And I run `apt-cache policy <apps-pkg>` as non-root |
4679 | + Then stdout matches regexp: |
4680 | + """ |
4681 | + Version table: |
4682 | + \s*\*\*\* .* 500 |
4683 | + \s*500 https://esm.staging.ubuntu.com/apps/ubuntu <release>-apps-security/main amd64 Packages |
4684 | + """ |
4685 | + |
4686 | + Examples: ubuntu release |
4687 | + | release | apps-pkg | |
4688 | + | bionic | bundler | |
4689 | + | focal | ant | |
4690 | + | trusty | ant | |
4691 | + | xenial | jq | |
4692 | + |
4693 | + @series.xenial |
4694 | + @series.bionic |
4695 | + @uses.config.machine_type.lxd.vm |
4696 | + Scenario Outline: Attached enable of vm-based services in an ubuntu lxd vm |
4697 | + Given a `<release>` machine with ubuntu-advantage-tools installed |
4698 | + When I attach `contract_token_staging` with sudo |
4699 | + And I run `ua disable livepatch` with sudo |
4700 | + And I run `apt-get install openssh-client openssh-server strongswan -y` with sudo, retrying exit [100] |
4701 | + And I run `apt-mark hold openssh-client openssh-server strongswan` with sudo |
4702 | + And I run `ua enable <fips-service> --assume-yes` with sudo |
4703 | + Then stdout matches regexp: |
4704 | + """ |
4705 | + Updating package lists |
4706 | + Installing <fips-name> packages |
4707 | + <fips-name> enabled |
4708 | + A reboot is required to complete install |
4709 | + """ |
4710 | + When I run `ua status --all` with sudo |
4711 | + Then stdout matches regexp: |
4712 | + """ |
4713 | + <fips-service> +yes enabled |
4714 | + """ |
4715 | + And stdout matches regexp: |
4716 | + """ |
4717 | + FIPS support requires system reboot to complete configuration |
4718 | + """ |
4719 | + And I verify that running `apt update` `with sudo` exits `0` |
4720 | + And I verify that running `grep Traceback /var/log/ubuntu-advantage.log` `with sudo` exits `1` |
4721 | + And I verify that `openssh-server` is installed from apt source `<fips-apt-source>` |
4722 | + And I verify that `openssh-client` is installed from apt source `<fips-apt-source>` |
4723 | + And I verify that `strongswan` is installed from apt source `<fips-apt-source>` |
4724 | + And I verify that `openssh-server-hmac` is installed from apt source `<fips-apt-source>` |
4725 | + And I verify that `openssh-client-hmac` is installed from apt source `<fips-apt-source>` |
4726 | + And I verify that `strongswan-hmac` is installed from apt source `<fips-apt-source>` |
4727 | + When I reboot the `<release>` machine |
4728 | + And I run `uname -r` as non-root |
4729 | + Then stdout matches regexp: |
4730 | + """ |
4731 | + fips |
4732 | + """ |
4733 | + When I run `cat /proc/sys/crypto/fips_enabled` with sudo |
4734 | + Then I will see the following on stdout: |
4735 | + """ |
4736 | + 1 |
4737 | + """ |
4738 | + When I run `ua status --all` with sudo |
4739 | + Then stdout does not match regexp: |
4740 | + """ |
4741 | + FIPS support requires system reboot to complete configuration |
4742 | + """ |
4743 | + When I run `ua disable <fips-service> --assume-yes` with sudo |
4744 | + Then stdout matches regexp: |
4745 | + """ |
4746 | + Updating package lists |
4747 | + A reboot is required to complete disable operation |
4748 | + """ |
4749 | + When I run `ua status --all` with sudo |
4750 | + Then stdout matches regexp: |
4751 | + """ |
4752 | + Disabling FIPS requires system reboot to complete operation |
4753 | + """ |
4754 | + When I run `apt-cache policy ubuntu-fips` as non-root |
4755 | + Then stdout matches regexp: |
4756 | + """ |
4757 | + .*Installed: \(none\) |
4758 | + """ |
4759 | + When I reboot the `<release>` machine |
4760 | + Then I verify that `openssh-server` installed version matches regexp `fips` |
4761 | + And I verify that `openssh-client` installed version matches regexp `fips` |
4762 | + And I verify that `strongswan` installed version matches regexp `fips` |
4763 | + And I verify that `openssh-server-hmac` installed version matches regexp `fips` |
4764 | + And I verify that `openssh-client-hmac` installed version matches regexp `fips` |
4765 | + And I verify that `strongswan-hmac` installed version matches regexp `fips` |
4766 | + When I run `apt-mark unhold openssh-client openssh-server strongswan` with sudo |
4767 | + Then I will see the following on stdout: |
4768 | + """ |
4769 | + openssh-client was already not hold. |
4770 | + openssh-server was already not hold. |
4771 | + strongswan was already not hold. |
4772 | + """ |
4773 | + When I run `ua status --all` with sudo |
4774 | + Then stdout matches regexp: |
4775 | + """ |
4776 | + <fips-service> +yes disabled |
4777 | + """ |
4778 | + Then stdout does not match regexp: |
4779 | + """ |
4780 | + Disabling FIPS requires system reboot to complete operation |
4781 | + """ |
4782 | + |
4783 | + Examples: ubuntu release |
4784 | + | release | fips-name | fips-service |fips-apt-source | |
4785 | + | xenial | FIPS | fips |https://esm.staging.ubuntu.com/fips/ubuntu xenial/main | |
4786 | + | bionic | FIPS | fips |https://esm.staging.ubuntu.com/fips/ubuntu bionic/main | |
4787 | + |
4788 | + @series.xenial |
4789 | + @series.bionic |
4790 | + @uses.config.machine_type.lxd.vm |
4791 | + Scenario Outline: Attached enable of vm-based services in an ubuntu lxd vm |
4792 | + Given a `<release>` machine with ubuntu-advantage-tools installed |
4793 | + When I attach `contract_token_staging` with sudo |
4794 | + And I run `ua disable livepatch` with sudo |
4795 | + And I run `apt-get install openssh-client openssh-server strongswan -y` with sudo, retrying exit [100] |
4796 | + When I run `ua enable <fips-service> --assume-yes` with sudo |
4797 | + Then stdout matches regexp: |
4798 | + """ |
4799 | + Updating package lists |
4800 | + Installing <fips-name> packages |
4801 | + <fips-name> enabled |
4802 | + A reboot is required to complete install |
4803 | + """ |
4804 | + When I run `ua status --all` with sudo |
4805 | + Then stdout matches regexp: |
4806 | + """ |
4807 | + <fips-service> +yes enabled |
4808 | + """ |
4809 | + And I verify that running `apt update` `with sudo` exits `0` |
4810 | + And I verify that running `grep Traceback /var/log/ubuntu-advantage.log` `with sudo` exits `1` |
4811 | + And I verify that `openssh-server` is installed from apt source `<fips-apt-source>` |
4812 | + And I verify that `openssh-client` is installed from apt source `<fips-apt-source>` |
4813 | + And I verify that `strongswan` is installed from apt source `<fips-apt-source>` |
4814 | + And I verify that `openssh-server-hmac` is installed from apt source `<fips-apt-source>` |
4815 | + And I verify that `openssh-client-hmac` is installed from apt source `<fips-apt-source>` |
4816 | + And I verify that `strongswan-hmac` is installed from apt source `<fips-apt-source>` |
4817 | + When I reboot the `<release>` machine |
4818 | + And I run `uname -r` as non-root |
4819 | + Then stdout matches regexp: |
4820 | + """ |
4821 | + fips |
4822 | + """ |
4823 | + When I run `cat /proc/sys/crypto/fips_enabled` with sudo |
4824 | + Then I will see the following on stdout: |
4825 | + """ |
4826 | + 1 |
4827 | + """ |
4828 | + When I run `ua disable <fips-service> --assume-yes` with sudo |
4829 | + Then stdout matches regexp: |
4830 | + """ |
4831 | + Updating package lists |
4832 | + A reboot is required to complete disable operation |
4833 | + """ |
4834 | + When I reboot the `<release>` machine |
4835 | + Then I verify that `openssh-server` installed version matches regexp `fips` |
4836 | + And I verify that `openssh-client` installed version matches regexp `fips` |
4837 | + And I verify that `strongswan` installed version matches regexp `fips` |
4838 | + And I verify that `openssh-server-hmac` installed version matches regexp `fips` |
4839 | + And I verify that `openssh-client-hmac` installed version matches regexp `fips` |
4840 | + And I verify that `strongswan-hmac` installed version matches regexp `fips` |
4841 | + When I run `apt-mark unhold openssh-client openssh-server strongswan` with sudo |
4842 | + Then I will see the following on stdout: |
4843 | + """ |
4844 | + openssh-client was already not hold. |
4845 | + openssh-server was already not hold. |
4846 | + strongswan was already not hold. |
4847 | + """ |
4848 | + When I run `ua status --all` with sudo |
4849 | + Then stdout matches regexp: |
4850 | + """ |
4851 | + <fips-service> +yes disabled |
4852 | + """ |
4853 | + |
4854 | + Examples: ubuntu release |
4855 | + | release | fips-name | fips-service |fips-apt-source | |
4856 | + | xenial | FIPS Updates | fips-updates |https://esm.staging.ubuntu.com/fips-updates/ubuntu xenial-updates/main | |
4857 | + | bionic | FIPS Updates | fips-updates |https://esm.staging.ubuntu.com/fips-updates/ubuntu bionic-updates/main | |
4858 | + |
4859 | + @series.xenial |
4860 | + @uses.config.machine_type.lxd.vm |
4861 | + Scenario Outline: Attached FIPS upgrade across LTS releases |
4862 | + Given a `<release>` machine with ubuntu-advantage-tools installed |
4863 | + When I attach `contract_token_staging` with sudo |
4864 | + And I run `apt-get install lsof` with sudo, retrying exit [100] |
4865 | + And I run `ua disable livepatch` with sudo |
4866 | + And I run `ua enable <fips-service> --assume-yes` with sudo |
4867 | + Then stdout matches regexp: |
4868 | + """ |
4869 | + Updating package lists |
4870 | + Installing <fips-name> packages |
4871 | + <fips-name> enabled |
4872 | + A reboot is required to complete install |
4873 | + """ |
4874 | + When I run `ua status --all` with sudo |
4875 | + Then stdout matches regexp: |
4876 | + """ |
4877 | + <fips-service> +yes enabled |
4878 | + """ |
4879 | + And I verify that running `apt update` `with sudo` exits `0` |
4880 | + When I reboot the `<release>` machine |
4881 | + And I run `uname -r` as non-root |
4882 | + Then stdout matches regexp: |
4883 | + """ |
4884 | + fips |
4885 | + """ |
4886 | + When I run `cat /proc/sys/crypto/fips_enabled` with sudo |
4887 | + Then I will see the following on stdout: |
4888 | + """ |
4889 | + 1 |
4890 | + """ |
4891 | + When I run `apt-get dist-upgrade -y --allow-downgrades` with sudo |
4892 | + # A package may need a reboot after running dist-upgrade |
4893 | + And I reboot the `<release>` machine |
4894 | + And I create the file `/etc/update-manager/release-upgrades.d/ua-test.cfg` with the following |
4895 | + """ |
4896 | + [Sources] |
4897 | + AllowThirdParty=yes |
4898 | + """ |
4899 | + Then I verify that running `do-release-upgrade --frontend DistUpgradeViewNonInteractive` `with sudo` exits `0` |
4900 | + When I reboot the `<release>` machine |
4901 | + And I run `lsb_release -cs` as non-root |
4902 | + Then I will see the following on stdout: |
4903 | + """ |
4904 | + <next_release> |
4905 | + """ |
4906 | + When I verify that running `egrep "disabled" /etc/apt/sources.list.d/<source-file>.list` `as non-root` exits `1` |
4907 | + Then I will see the following on stdout: |
4908 | + """ |
4909 | + """ |
4910 | + When I run `ua status --all` with sudo |
4911 | + Then stdout matches regexp: |
4912 | + """ |
4913 | + <fips-service> +yes enabled |
4914 | + """ |
4915 | + When I run `uname -r` as non-root |
4916 | + Then stdout matches regexp: |
4917 | + """ |
4918 | + fips |
4919 | + """ |
4920 | + When I run `cat /proc/sys/crypto/fips_enabled` with sudo |
4921 | + Then I will see the following on stdout: |
4922 | + """ |
4923 | + 1 |
4924 | + """ |
4925 | + |
4926 | + Examples: ubuntu release |
4927 | + | release | next_release | fips-service | fips-name | source-file | |
4928 | + | xenial | bionic | fips | FIPS | ubuntu-fips | |
4929 | + | xenial | bionic | fips-updates | FIPS Updates | ubuntu-fips-updates | |
4930 | + |
4931 | + @series.xenial |
4932 | + @series.bionic |
4933 | + Scenario Outline: Attached enable of cis service in a ubuntu machine |
4934 | + Given a `<release>` machine with ubuntu-advantage-tools installed |
4935 | + When I attach `contract_token_staging` with sudo |
4936 | + And I verify that running `ua enable cis --beta` `with sudo` exits `0` |
4937 | + Then I will see the following on stdout: |
4938 | + """ |
4939 | + One moment, checking your subscription first |
4940 | + Updating package lists |
4941 | + Installing CIS Audit packages |
4942 | + CIS Audit enabled |
4943 | + """ |
4944 | + When I run `apt-cache policy usg-cisbenchmark` as non-root |
4945 | + Then stdout does not match regexp: |
4946 | + """ |
4947 | + .*Installed: \(none\) |
4948 | + """ |
4949 | + And stdout matches regexp: |
4950 | + """ |
4951 | + \s* 500 https://esm.staging.ubuntu.com/cis/ubuntu <release>/main amd64 Packages |
4952 | + """ |
4953 | + When I run `apt-cache policy usg-common` as non-root |
4954 | + Then stdout does not match regexp: |
4955 | + """ |
4956 | + .*Installed: \(none\) |
4957 | + """ |
4958 | + And stdout matches regexp: |
4959 | + """ |
4960 | + \s* 500 https://esm.staging.ubuntu.com/cis/ubuntu <release>/main amd64 Packages |
4961 | + """ |
4962 | + |
4963 | + Examples: not entitled services |
4964 | + | release | |
4965 | + | bionic | |
4966 | + | xenial | |
4967 | + |
4968 | + @series.xenial |
4969 | + @series.bionic |
4970 | + @uses.config.machine_type.lxd.vm |
4971 | + Scenario Outline: Attached enable fips-updates on fips enabled vm |
4972 | + Given a `<release>` machine with ubuntu-advantage-tools installed |
4973 | + When I attach `contract_token_staging` with sudo |
4974 | + And I run `ua disable livepatch` with sudo |
4975 | + And I run `apt-get install openssh-client openssh-server strongswan -y` with sudo, retrying exit [100] |
4976 | + And I run `ua enable fips --assume-yes` with sudo |
4977 | + Then stdout matches regexp: |
4978 | + """ |
4979 | + Updating package lists |
4980 | + Installing FIPS packages |
4981 | + FIPS enabled |
4982 | + A reboot is required to complete install |
4983 | + """ |
4984 | + When I run `ua status --all` with sudo |
4985 | + Then stdout matches regexp: |
4986 | + """ |
4987 | + fips +yes enabled |
4988 | + """ |
4989 | + When I reboot the `<release>` machine |
4990 | + And I run `ua enable fips-updates --assume-yes` with sudo |
4991 | + Then stdout matches regexp: |
4992 | + """ |
4993 | + Updating package lists |
4994 | + Installing FIPS Updates packages |
4995 | + FIPS Updates enabled |
4996 | + A reboot is required to complete install |
4997 | + """ |
4998 | + When I run `ua status --all` with sudo |
4999 | + Then stdout matches regexp: |
5000 | + """ |
----- Autopkgtest results: ---------
csmith@ downtown: /tmp/ubuntu- advantage- client (ubuntu/devel)$ autopkgtest -o autopkgtest- ua-tools -U ../out/ ubuntu- advantage- tools_26. 1~21.04. 1.dsc -- lxd ubuntu-daily:xenial autopkgtest -o autopkgtest- ua-tools -U '../out/ ubuntu- advantage- tools_26. 1~21.04. 1.dsc' -- lxd ubuntu-daily:xenial @@@@@@@ @@@@@@ test bed setup archive. ubuntu. com/ubuntu xenial InRelease security. ubuntu. com/ubuntu xenial-security InRelease archive. ubuntu. com/ubuntu xenial-updates InRelease archive. ubuntu. com/ubuntu xenial-backports InRelease archive. ubuntu. com/ubuntu xenial-updates/main amd64 libldap-2.4-2 amd64 2.4.42+ dfsg-2ubuntu3. 13 [159 kB] 2.4-2_2. 4.42+dfsg- 2ubuntu3. 13_amd64. deb ... dfsg-2ubuntu3. 13) over (2.4.42+ dfsg-2ubuntu3. 12) ... dfsg-2ubuntu3. 13) ... @@@@@@@ @@@@@@ source ../out/ ubuntu- advantage- tools_26. 1~21.04. 1.dsc ..Starting pkgProblemResolver with broken count: 0 merge-perl fcntllock- perl archive. ubuntu. com/ubuntu xenial- updates/ ma...
autopkgtest [14:10:51]: starting date: 2021-02-22
autopkgtest [14:10:51]: version 5.13.1
autopkgtest [14:10:51]: host downtown; command line: /usr/bin/
autopkgtest [14:11:01]: @@@@@@@
tee: /proc/self/fd/2: Permission denied
Hit:1 http://
Hit:2 http://
Hit:3 http://
Hit:4 http://
Reading package lists...
Reading package lists...
Building dependency tree...
Reading state information...
Calculating upgrade...
The following package was automatically installed and is no longer required:
libfreetype6
Use 'apt autoremove' to remove it.
The following packages will be upgraded:
libldap-2.4-2
1 upgraded, 0 newly installed, 0 to remove and 0 not upgraded.
Need to get 159 kB of archives.
After this operation, 0 B of additional disk space will be used.
Get:1 http://
Fetched 159 kB in 0s (218 kB/s)
(Reading database ... 25810 files and directories currently installed.)
Preparing to unpack .../libldap-
Unpacking libldap-2.4-2:amd64 (2.4.42+
Processing triggers for man-db (2.7.5-1) ...
Setting up libldap-2.4-2:amd64 (2.4.42+
Processing triggers for libc-bin (2.23-0ubuntu11.2) ...
autopkgtest [14:11:28]: testbed dpkg architecture: amd64
autopkgtest [14:11:29]: testbed running kernel: Linux 5.8.0-43-generic #49-Ubuntu SMP Fri Feb 5 03:01:28 UTC 2021
autopkgtest [14:11:29]: @@@@@@@
Reading package lists...
Building dependency tree...
Reading state information...
Correcting dependencies.
Starting 2 pkgProblemResolver with broken count: 0
Done
Done
Starting pkgProblemResolver with broken count: 0
Starting 2 pkgProblemResolver with broken count: 0
Done
The following package was automatically installed and is no longer required:
libfreetype6
Use 'apt autoremove' to remove it.
The following additional packages will be installed:
binutils dpkg-dev libdpkg-perl make
Suggested packages:
binutils-doc debian-keyring gcc | c-compiler make-doc
Recommended packages:
gcc | c-compiler build-essential fakeroot libalgorithm-
libfile-
The following NEW packages will be installed:
binutils dpkg-dev libdpkg-perl make
0 upgraded, 4 newly installed, 0 to remove and 0 not upgraded.
1 not fully installed or removed.
Need to get 3,242 kB of archives.
After this operation, 17.6 MB of additional disk space will be used.
Get:1 http://