Merge ~barryprice/charm-canonical-livepatch/+git/canonical-livepatch-charm:zazatests into ~livepatch-charmers/charm-canonical-livepatch: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)
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`.

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
1diff --git a/.gitignore b/.gitignore
2new file mode 100644
3index 0000000..33defe4
4--- /dev/null
5+++ b/.gitignore
6@@ -0,0 +1 @@
7+.tox/
8diff --git a/Makefile b/Makefile
9index 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
59diff --git a/files/check_canonical-livepatch.py b/files/check_canonical-livepatch.py
60index 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:
74diff --git a/metadata.yaml b/metadata.yaml
75index 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:
87diff --git a/reactive/canonical_livepatch.py b/reactive/canonical_livepatch.py
88index 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()
190diff --git a/test-requirements.txt b/test-requirements.txt
191new file mode 100644
192index 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
197diff --git a/tests/basic_deployment.py b/tests/basic_deployment.py
198new file mode 100644
199index 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)
216diff --git a/tests/bundles/bionic.yaml b/tests/bundles/bionic.yaml
217new file mode 100644
218index 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
240diff --git a/tests/bundles/xenial.yaml b/tests/bundles/xenial.yaml
241new file mode 100644
242index 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
264diff --git a/tests/multiseries b/tests/multiseries
265deleted file mode 100755
266index 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()
429diff --git a/tests/tests.yaml b/tests/tests.yaml
430index 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
457diff --git a/tox.ini b/tox.ini
458new file mode 100644
459index 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+

Subscribers

People subscribed via source and target branches