Merge ~barryprice/charm-canonical-livepatch/+git/canonical-livepatch-charm:zazatests into ~livepatch-charmers/charm-canonical-livepatch:master
- Git
- lp:~barryprice/charm-canonical-livepatch/+git/canonical-livepatch-charm
- zazatests
- Merge into master
Proposed by
Barry Price
Status: | Work in progress |
---|---|
Proposed branch: | ~barryprice/charm-canonical-livepatch/+git/canonical-livepatch-charm:zazatests |
Merge into: | ~livepatch-charmers/charm-canonical-livepatch:master |
Diff against target: |
506 lines (+140/-215) 12 files modified
.gitignore (+1/-0) Makefile (+11/-21) dev/null (+0/-159) files/check_canonical-livepatch.py (+1/-3) metadata.yaml (+1/-1) reactive/canonical_livepatch.py (+11/-29) test-requirements.txt (+1/-0) tests/basic_deployment.py (+13/-0) tests/bundles/bionic.yaml (+18/-0) tests/bundles/xenial.yaml (+18/-0) tests/tests.yaml (+21/-2) tox.ini (+44/-0) |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Livepatch charm developers | Pending | ||
Review via email: mp+369790@code.launchpad.net |
Commit message
First pass at switching from amulet to tox+zaza for tests. Also dropping official support for Trusty as it's EOL. Oh, and some reformatting via `black`.
Description of the change
To post a comment you must log in.
- 3b5ee0d... by Barry Price
-
Obsolete comment removed
- 4bfc463... by Barry Price
-
Basic tests for an LXD deploy, need to figure out whether/how we can require an OpenStack controller for some test suites
Unmerged commits
- 4bfc463... by Barry Price
-
Basic tests for an LXD deploy, need to figure out whether/how we can require an OpenStack controller for some test suites
- 3b5ee0d... by Barry Price
-
Obsolete comment removed
- f8061f8... by Barry Price
-
First pass at switching from amulet to tox+zaza for tests. Also dropping official support for Trusty as it's EOL
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | diff --git a/.gitignore b/.gitignore |
2 | new file mode 100644 |
3 | index 0000000..33defe4 |
4 | --- /dev/null |
5 | +++ b/.gitignore |
6 | @@ -0,0 +1 @@ |
7 | +.tox/ |
8 | diff --git a/Makefile b/Makefile |
9 | index e7f78ad..7459cb2 100644 |
10 | --- a/Makefile |
11 | +++ b/Makefile |
12 | @@ -5,35 +5,25 @@ all: test |
13 | |
14 | .PHONY: clean |
15 | clean: |
16 | - @rm -f .unit-state.db |
17 | @find . -name "*.pyc" -type f -exec rm -f '{}' \; |
18 | @find . -name "__pycache__" -type d -prune -exec rm -rf '{}' \; |
19 | |
20 | -.PHONY: testdeps |
21 | -testdeps: |
22 | - @sudo apt-get update |
23 | - @sudo apt-get install -y make flake8 python3-flake8 python3-pip python-pip snapd libffi-dev |
24 | - @which juju >/dev/null || (sudo snap install juju --classic) |
25 | - @which charm >/dev/null || (sudo snap install charm --classic) |
26 | - @which bundletester >/dev/null || (pip2 install bundletester juju-deployer) |
27 | - @pip3 install amulet |
28 | - |
29 | .PHONY: lint |
30 | lint: |
31 | - @flake8 --max-complexity=16 --max-line-length=120 --exclude=lib/* && echo OK |
32 | + @echo "Normalising python layout with black." |
33 | + @tox -e black |
34 | + @echo "Running flake8" |
35 | + @tox -e lint |
36 | |
37 | .PHONY: charmbuild |
38 | charmbuild: |
39 | - mkdir $(BUILDDEST) |
40 | + mkdir -p $(BUILDDEST) |
41 | charm build --output-dir $(BUILDDEST) --report |
42 | |
43 | -.PHONY: test |
44 | -test: check-jujumodel |
45 | - @echo "Running functional tests (including lint and unit tests)..." |
46 | - bundletester -t $(BUILTCHARMDIR) -Fvl DEBUG -e $(JUJU_MODEL) |
47 | +.PHONY: smoketest |
48 | +smoketest: |
49 | + @tox -e func-smoke |
50 | |
51 | -.PHONY: check-jujumodel |
52 | -check-jujumodel: |
53 | -ifndef JUJU_MODEL |
54 | - $(error JUJU_MODEL is undefined) |
55 | -endif |
56 | +.PHONY: test |
57 | +test: |
58 | + @tox -e func |
59 | diff --git a/files/check_canonical-livepatch.py b/files/check_canonical-livepatch.py |
60 | index cafd472..0006714 100755 |
61 | --- a/files/check_canonical-livepatch.py |
62 | +++ b/files/check_canonical-livepatch.py |
63 | @@ -142,9 +142,7 @@ def is_container(): |
64 | def main(): |
65 | arch = os.uname()[4] |
66 | if arch not in supported_archs: |
67 | - raise nagios_plugin3.CriticalError( |
68 | - "canonical-livepatch not supported on this architecture ({}).".format(arch) |
69 | - ) |
70 | + raise nagios_plugin3.CriticalError("canonical-livepatch not supported on this architecture ({}).".format(arch)) |
71 | elif is_container(): |
72 | print("canonical-livepatch not needed in OS containers.") |
73 | else: |
74 | diff --git a/metadata.yaml b/metadata.yaml |
75 | index 6c22c45..e3e557f 100644 |
76 | --- a/metadata.yaml |
77 | +++ b/metadata.yaml |
78 | @@ -2,7 +2,7 @@ name: canonical-livepatch |
79 | display-name: Canonical Livepatch |
80 | summary: Ubuntu Linux Livepatching Utility and Daemon |
81 | maintainer: Livepatch charm developers <livepatch-charmers@lists.launchpad.net> |
82 | -series: ['bionic', 'xenial', 'trusty'] |
83 | +series: ['bionic', 'xenial'] |
84 | description: | |
85 | This charms installs and configures the Ubuntu Linux Livepatching Utility and Daemon |
86 | tags: |
87 | diff --git a/reactive/canonical_livepatch.py b/reactive/canonical_livepatch.py |
88 | index f9c1e6e..30692a1 100644 |
89 | --- a/reactive/canonical_livepatch.py |
90 | +++ b/reactive/canonical_livepatch.py |
91 | @@ -19,12 +19,7 @@ def file_to_units(local_path, unit_path): |
92 | perms = 0o644 |
93 | |
94 | fh = open(local_path, 'r') |
95 | - write_file( |
96 | - path=unit_path, |
97 | - content=fh.read().encode(), |
98 | - owner='root', |
99 | - perms=perms, |
100 | - ) |
101 | + write_file(path=unit_path, content=fh.read().encode(), owner='root', perms=perms) |
102 | |
103 | |
104 | def wait_for_path(file_path, timeout=30): |
105 | @@ -74,12 +69,7 @@ def write_status_to_disk(): |
106 | |
107 | current_status = get_livepatch_status() |
108 | perms = 0o644 |
109 | - write_file( |
110 | - path='/var/lib/nagios/canonical-livepatch-status.txt', |
111 | - content=current_status, |
112 | - owner='root', |
113 | - perms=perms, |
114 | - ) |
115 | + write_file(path='/var/lib/nagios/canonical-livepatch-status.txt', content=current_status, owner='root', perms=perms) |
116 | |
117 | |
118 | def get_patch_details(): |
119 | @@ -161,7 +151,7 @@ register_trigger(when='config.changed.livepatch_proxy', clear_flag='livepatch-pr |
120 | @when_not('canonical-livepatch.supported') |
121 | def livepatch_supported(): |
122 | arch = uname()[4] |
123 | - supported_archs = ['x86_64', ] |
124 | + supported_archs = ['x86_64'] |
125 | if arch not in supported_archs: |
126 | hookenv.log('Livepatch does not currently support {} architecture'.format(arch)) |
127 | unit_update('blocked', 'Architecture {} is not supported by livepatch'.format(arch)) |
128 | @@ -177,7 +167,7 @@ def livepatch_supported(): |
129 | def install_livepatch(): |
130 | config = hookenv.config() |
131 | snap_channel = config.get('snap_channel') |
132 | - snap.install('canonical-livepatch', **{'channel': snap_channel, }) |
133 | + snap.install('canonical-livepatch', **{'channel': snap_channel}) |
134 | |
135 | |
136 | @when('snap.installed.canonical-livepatch') |
137 | @@ -210,8 +200,8 @@ def proxy_settings(): |
138 | @when('livepatch-proxy.configured') |
139 | @when_not('canonical-livepatch.connected') |
140 | def canonical_livepatch_connect(): |
141 | - # So if we've just installed snapd on a trusty system, we will not be on |
142 | - # the HWE kernel yet and unfortunately need to reboot first! |
143 | + # So if we've just installed snapd on a trusty system, or are somehow |
144 | + # running an older kernel onto a supported series, we will need to reboot |
145 | current = LooseVersion(uname()[2]) |
146 | required = LooseVersion('4.4') |
147 | uptrack_path = '/usr/sbin/uptrack-upgrade' |
148 | @@ -250,7 +240,7 @@ def change_channel(): |
149 | config = hookenv.config() |
150 | snap_channel = config.get('snap_channel') |
151 | # refresh to the given channel |
152 | - snap.refresh('canonical-livepatch', **{'channel': snap_channel, }) |
153 | + snap.refresh('canonical-livepatch', **{'channel': snap_channel}) |
154 | |
155 | |
156 | # Set up Nagios checks when the nrpe-external-master subordinate is related |
157 | @@ -266,28 +256,20 @@ def configure_nagios(nagios): |
158 | nrpe_setup = nrpe.NRPE(hostname=hostname, primary=False) |
159 | |
160 | # install nagios support files |
161 | - file_to_units( |
162 | - 'files/check_canonical-livepatch.cron', |
163 | - '/etc/cron.d/check_canonical-livepatch', |
164 | - ) |
165 | - file_to_units( |
166 | - 'files/check_canonical-livepatch.py', |
167 | - '/usr/lib/nagios/plugins/check_canonical-livepatch.py', |
168 | - ) |
169 | + file_to_units('files/check_canonical-livepatch.cron', '/etc/cron.d/check_canonical-livepatch') |
170 | + file_to_units('files/check_canonical-livepatch.py', '/usr/lib/nagios/plugins/check_canonical-livepatch.py') |
171 | |
172 | # write current status to disk to satisfy the nagios check |
173 | write_status_to_disk() |
174 | |
175 | # remove check from previous release with poorly formed name |
176 | - nrpe_setup.remove_check( |
177 | - shortname='check_canonical-livepatch' |
178 | - ) |
179 | + nrpe_setup.remove_check(shortname='check_canonical-livepatch') |
180 | |
181 | # use charmhelpers to create the check |
182 | nrpe_setup.add_check( |
183 | 'canonical-livepatch', |
184 | 'Verify canonical-livepatch is working', |
185 | - '/usr/lib/nagios/plugins/check_canonical-livepatch.py' |
186 | + '/usr/lib/nagios/plugins/check_canonical-livepatch.py', |
187 | ) |
188 | |
189 | nrpe_setup.write() |
190 | diff --git a/test-requirements.txt b/test-requirements.txt |
191 | new file mode 100644 |
192 | index 0000000..b7c9112 |
193 | --- /dev/null |
194 | +++ b/test-requirements.txt |
195 | @@ -0,0 +1 @@ |
196 | +git+https://github.com/openstack-charmers/zaza.git#egg=zaza |
197 | diff --git a/tests/basic_deployment.py b/tests/basic_deployment.py |
198 | new file mode 100644 |
199 | index 0000000..a07e880 |
200 | --- /dev/null |
201 | +++ b/tests/basic_deployment.py |
202 | @@ -0,0 +1,13 @@ |
203 | +#!/usr/bin/python3 |
204 | + |
205 | +import unittest |
206 | + |
207 | +import zaza.model as model |
208 | + |
209 | + |
210 | +class BasicDeployment(unittest.TestCase): |
211 | + def test_ubuntu_series(self): |
212 | + first_unit = model.get_units('mongo')[0] |
213 | + result = model.run_on_leader('mongo', 'lsb_release -cs') |
214 | + self.assertEqual(result['Code'], '0') |
215 | + self.assertEqual(result['Stdout'].strip(), first_unit.series) |
216 | diff --git a/tests/bundles/bionic.yaml b/tests/bundles/bionic.yaml |
217 | new file mode 100644 |
218 | index 0000000..f95419d |
219 | --- /dev/null |
220 | +++ b/tests/bundles/bionic.yaml |
221 | @@ -0,0 +1,18 @@ |
222 | +series: bionic |
223 | +applications: |
224 | + mongo: |
225 | + charm: cs:mongodb |
226 | + num_units: 1 |
227 | + livepatch: |
228 | + charm: ../../../builds/canonical-livepatch |
229 | + series: bionic |
230 | + nrpe: |
231 | + charm: cs:nrpe |
232 | + num_units: 0 |
233 | +relations: |
234 | + - - mongo |
235 | + - livepatch |
236 | + - - mongo |
237 | + - nrpe:nrpe-external-master |
238 | + - - livepatch |
239 | + - nrpe:nrpe-external-master |
240 | diff --git a/tests/bundles/xenial.yaml b/tests/bundles/xenial.yaml |
241 | new file mode 100644 |
242 | index 0000000..5b52957 |
243 | --- /dev/null |
244 | +++ b/tests/bundles/xenial.yaml |
245 | @@ -0,0 +1,18 @@ |
246 | +series: xenial |
247 | +applications: |
248 | + mongo: |
249 | + charm: cs:mongodb |
250 | + num_units: 1 |
251 | + livepatch: |
252 | + charm: ../../../builds/canonical-livepatch |
253 | + series: xenial |
254 | + nrpe: |
255 | + charm: cs:nrpe |
256 | + num_units: 0 |
257 | +relations: |
258 | + - - mongo |
259 | + - livepatch |
260 | + - - mongo |
261 | + - nrpe:nrpe-external-master |
262 | + - - livepatch |
263 | + - nrpe:nrpe-external-master |
264 | diff --git a/tests/multiseries b/tests/multiseries |
265 | deleted file mode 100755 |
266 | index 55adc62..0000000 |
267 | --- a/tests/multiseries |
268 | +++ /dev/null |
269 | @@ -1,159 +0,0 @@ |
270 | -#!/usr/bin/env python3 |
271 | - |
272 | -import amulet |
273 | -import unittest |
274 | -from time import sleep |
275 | -from yaml import safe_load |
276 | - |
277 | - |
278 | -class TestDeployment(unittest.TestCase): |
279 | - series = 'bionic' # latest LTS |
280 | - |
281 | - @classmethod |
282 | - def setUpClass(cls): |
283 | - cls.deployment = amulet.Deployment(series=cls.series) |
284 | - |
285 | - # deploy mongodb as our parent |
286 | - cls.deployment.add('mongodb-{}'.format(cls.series), 'mongodb') |
287 | - |
288 | - # deploy our own charm |
289 | - cls.deployment.add('livepatch-{}'.format(cls.series), 'canonical-livepatch') |
290 | - |
291 | - # and deploy the nrpe subordinate to test nagios checks |
292 | - cls.deployment.add('nrpe-{}'.format(cls.series), 'nrpe') |
293 | - |
294 | - # set nrpe to export its definitions |
295 | - cls.deployment.configure('nrpe-{}'.format(cls.series), { |
296 | - 'export_nagios_definitions': True, |
297 | - }) |
298 | - |
299 | - # relate subordinates to parent charm |
300 | - cls.deployment.relate( |
301 | - 'mongodb-{}:juju-info'.format(cls.series), |
302 | - 'livepatch-{}:juju-info'.format(cls.series) |
303 | - ) |
304 | - cls.deployment.relate( |
305 | - 'mongodb-{}:nrpe-external-master'.format(cls.series), |
306 | - 'nrpe-{}:nrpe-external-master'.format(cls.series) |
307 | - ) |
308 | - |
309 | - # relate livepatch to nrpe for its own nagios checks |
310 | - cls.deployment.relate( |
311 | - 'livepatch-{}:nrpe-external-master'.format(cls.series), |
312 | - 'nrpe-{}:nrpe-external-master'.format(cls.series) |
313 | - ) |
314 | - |
315 | - try: |
316 | - cls.deployment.setup(timeout=3600) |
317 | - cls.deployment.sentry.wait() |
318 | - except amulet.helpers.TimeoutError: |
319 | - amulet.raise_status( |
320 | - amulet.SKIP, |
321 | - msg="Environment wasn't stood up in time" |
322 | - ) |
323 | - |
324 | - def test_install(self): |
325 | - livepatch = self.deployment.sentry['livepatch-{}'.format(self.series)][0] |
326 | - |
327 | - # verify the snap was installed |
328 | - output, exit_code = livepatch.run( |
329 | - 'stat /snap/bin/canonical-livepatch' |
330 | - ) |
331 | - self.assertEqual(exit_code, 0) |
332 | - |
333 | - def test_status(self): |
334 | - livepatch = self.deployment.sentry['livepatch-{}'.format(self.series)][0] |
335 | - |
336 | - # run a status check - we expect this to return 1 due to no access key |
337 | - output, exit_code = livepatch.run('sudo canonical-livepatch status') |
338 | - self.assertEqual(exit_code, 1) |
339 | - |
340 | - def test_nagios_init(self): |
341 | - livepatch = self.deployment.sentry['livepatch-{}'.format(self.series)][0] |
342 | - |
343 | - # check for nagios bits |
344 | - for path in [ |
345 | - '/etc/cron.d/check_canonical-livepatch', |
346 | - '/usr/lib/nagios/plugins/check_canonical-livepatch.py', |
347 | - '/var/lib/nagios/canonical-livepatch-status.txt' |
348 | - ]: |
349 | - output, exit_code = livepatch.run('stat {}'.format(path)) |
350 | - self.assertEqual(exit_code, 0) |
351 | - |
352 | - def test_nagios_context_change(self): |
353 | - livepatch = self.deployment.sentry['livepatch-{}'.format(self.series)][0] |
354 | - |
355 | - test_context_name = 'amulet1' |
356 | - |
357 | - # set context name |
358 | - self.deployment.configure('livepatch-{}'.format(self.series), { |
359 | - 'nagios_context': test_context_name, |
360 | - }) |
361 | - |
362 | - # nrpe updates can take a while |
363 | - sleep(30) |
364 | - |
365 | - # confirm it showed up in the right place |
366 | - output, exit_code = livepatch.run( |
367 | - 'grep {} /var/lib/nagios/export/' |
368 | - 'service__*_check_canonical-livepatch' |
369 | - '.cfg'.format(test_context_name)) |
370 | - self.assertEqual(exit_code, 0) |
371 | - |
372 | - def test_channel_change(self): |
373 | - livepatch = self.deployment.sentry['livepatch-{}'.format(self.series)][0] |
374 | - |
375 | - # verify the current channel |
376 | - output, exit_code = livepatch.run('snap info canonical-livepatch') |
377 | - self.assertEqual(exit_code, 0) |
378 | - |
379 | - # confirm we're tracking 'stable' |
380 | - output_yaml = safe_load(output) |
381 | - channel = output_yaml['tracking'] |
382 | - self.assertEqual(channel, 'stable') |
383 | - |
384 | - # change channel to 'beta' |
385 | - self.deployment.configure('livepatch-{}'.format(self.series), { |
386 | - 'snap_channel': 'beta', |
387 | - }) |
388 | - |
389 | - # wait for that to settle |
390 | - sleep(30) |
391 | - |
392 | - # verify the current channel |
393 | - output, exit_code = livepatch.run('snap info canonical-livepatch') |
394 | - self.assertEqual(exit_code, 0) |
395 | - |
396 | - # confirm we're tracking 'beta' |
397 | - output_yaml = safe_load(output) |
398 | - channel = output_yaml['tracking'] |
399 | - self.assertEqual(channel, 'beta') |
400 | - |
401 | - def test_nagios_servicegroup_change(self): |
402 | - livepatch = self.deployment.sentry['livepatch-{}'.format(self.series)][0] |
403 | - |
404 | - test_servicegroup_name = 'amulet2' |
405 | - |
406 | - # set servicegroup name |
407 | - self.deployment.configure('livepatch-{}'.format(self.series), { |
408 | - 'nagios_servicegroups': test_servicegroup_name, |
409 | - }) |
410 | - |
411 | - # nrpe updates can take a while |
412 | - sleep(30) |
413 | - |
414 | - # confirm it showed up in the right place |
415 | - output, exit_code = livepatch.run( |
416 | - 'grep {} /var/lib/nagios/export/' |
417 | - 'service__*_check_canonical-livepatch' |
418 | - '.cfg'.format(test_servicegroup_name) |
419 | - ) |
420 | - self.assertEqual(exit_code, 0) |
421 | - |
422 | - |
423 | -class TestXenialDeployment(TestDeployment): |
424 | - series = 'xenial' |
425 | - |
426 | - |
427 | -if __name__ == '__main__': |
428 | - unittest.main() |
429 | diff --git a/tests/tests.yaml b/tests/tests.yaml |
430 | index 757bcc2..2754f7c 100644 |
431 | --- a/tests/tests.yaml |
432 | +++ b/tests/tests.yaml |
433 | @@ -1,2 +1,21 @@ |
434 | -makefile: |
435 | - - lint |
436 | +charm-name: canonical-livepatch |
437 | +tests: |
438 | + - zaza.charm_tests.noop.tests.NoopTest |
439 | +configure: |
440 | + - zaza.charm_tests.noop.setup.basic_setup |
441 | +gate_bundles: |
442 | + - bionic |
443 | +smoke_bundles: |
444 | + - bionic |
445 | +tests: |
446 | + - tests.basic_deployment.BasicDeployment |
447 | +target_deploy_status: |
448 | + mongo: |
449 | + workload-status: active |
450 | + workload-status-message: Unit is ready |
451 | + livepatch: |
452 | + workload-status: blocked |
453 | + workload-status-message: Livepatch is not needed in OS containers |
454 | + nrpe: |
455 | + workload-status: active |
456 | + workload-status-message: ready |
457 | diff --git a/tox.ini b/tox.ini |
458 | new file mode 100644 |
459 | index 0000000..4b3e051 |
460 | --- /dev/null |
461 | +++ b/tox.ini |
462 | @@ -0,0 +1,44 @@ |
463 | +[tox] |
464 | +envlist = pep8 |
465 | +skipsdist = True |
466 | + |
467 | +[testenv] |
468 | +setenv = VIRTUAL_ENV={envdir} |
469 | + PYTHONHASHSEED=0 |
470 | +whitelist_externals = juju |
471 | +passenv = HOME TERM CS_API_* OS_* AMULET_* |
472 | +deps = -r{toxinidir}/test-requirements.txt |
473 | +install_command = |
474 | + pip install {opts} {packages} |
475 | + |
476 | +[testenv:proof] |
477 | +basepython = python3 |
478 | +deps=charm-tools |
479 | +commands = charm-proof |
480 | + |
481 | +[testenv:black] |
482 | +commands = black --skip-string-normalization --line-length=120 . |
483 | +deps = black |
484 | + |
485 | +[testenv:lint] |
486 | +commands = flake8 |
487 | +deps = flake8 |
488 | + |
489 | +[testenv:func-noop] |
490 | +basepython = python3 |
491 | +commands = |
492 | + true |
493 | + |
494 | +[testenv:func] |
495 | +basepython = python3 |
496 | +commands = |
497 | + functest-run-suite --keep-model |
498 | + |
499 | +[testenv:func-smoke] |
500 | +basepython = python3 |
501 | +commands = |
502 | + functest-run-suite --keep-model --smoke |
503 | + |
504 | +[testenv:venv] |
505 | +commands = {posargs} |
506 | + |