Merge ~rgildein/charm-hw-health:bug1983398 into charm-hw-health:master

Proposed by Robert Gildein
Status: Merged
Approved by: Eric Chen
Approved revision: eea54585346932b4294a738b19d4291f6ce49f0c
Merged at revision: 5f6c95198de83f732655b7b204855dc5ff183b97
Proposed branch: ~rgildein/charm-hw-health:bug1983398
Merge into: charm-hw-health:master
Diff against target: 286 lines (+63/-58)
4 files modified
src/README.md (+1/-1)
src/tests/functional/conftest.py (+12/-9)
src/tests/functional/requirements.txt (+3/-4)
src/tests/functional/test_hwhealth.py (+47/-44)
Reviewer Review Type Date Requested Status
Eric Chen Approve
BootStack Reviewers Pending
Review via email: mp+428506@code.launchpad.net

Commit message

Update pytest fixtures and fix deployment

- update to pytest_asyncio.fixture
- fix deploy_app

fixes: #1983398

Description of the change

Update pytest fixtures and fix deployment

- update to pytest_asyncio.fixture
- fix deploy_app

result from functional tests: https://pastebin.ubuntu.com/p/hCnHZb4j6s/

To post a comment you must log in.
Revision history for this message
🤖 Canonical IS Merge Bot (canonical-is-mergebot) wrote :

This merge proposal is being monitored by mergebot. Change the status to Approved to merge.

Revision history for this message
Eric Chen (eric-chen) wrote :

LGTM

review: Approve
Revision history for this message
Robert Gildein (rgildein) wrote :

I forgot to run lint and unit tests [1].

---
[1]: https://pastebin.ubuntu.com/p/jGrQtDQ5Zn/

Revision history for this message
🤖 Canonical IS Merge Bot (canonical-is-mergebot) wrote :

Change successfully merged at revision 5f6c95198de83f732655b7b204855dc5ff183b97

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1diff --git a/src/README.md b/src/README.md
2index c3d71d1..2889eed 100644
3--- a/src/README.md
4+++ b/src/README.md
5@@ -116,7 +116,7 @@ For example:
6 [megacli](https://docs.broadcom.com/docs/12351586)/
7 [sas3ircu](https://docs.broadcom.com/docs/SAS3IRCU_P16.zip)/
8 [sas2ircu](https://docs.broadcom.com/docs/12351735)/
9-[perccli] (https://dl.dell.com/FOLDER07576010M/1/PERCCLI_7.1623.00_A11_Linux.tar.gz)
10+[perccli](https://dl.dell.com/FOLDER07576010M/1/PERCCLI_7.1623.00_A11_Linux.tar.gz)
11
12 You will then have to extract, rename, and compress the binaries to obtain the
13 following structure:
14diff --git a/src/tests/functional/conftest.py b/src/tests/functional/conftest.py
15index c7c856c..b0a1353 100644
16--- a/src/tests/functional/conftest.py
17+++ b/src/tests/functional/conftest.py
18@@ -19,6 +19,9 @@ from juju.errors import JujuError
19
20 import pytest
21
22+import pytest_asyncio
23+
24+
25 STAT_CMD = """python3 - <<EOF
26 import json
27 import os
28@@ -48,7 +51,7 @@ def event_loop():
29 asyncio.set_event_loop(None)
30
31
32-@pytest.fixture(scope="module")
33+@pytest_asyncio.fixture(scope="module")
34 async def controller():
35 """Connect to the current controller."""
36 _controller = Controller()
37@@ -57,7 +60,7 @@ async def controller():
38 await _controller.disconnect()
39
40
41-@pytest.fixture(scope="module")
42+@pytest_asyncio.fixture(scope="module")
43 async def model(controller): # pylint: disable=redefined-outer-name
44 """Create model which lives only for the duration of the test."""
45 model_name = "functest-{}".format(uuid.uuid4())
46@@ -70,7 +73,7 @@ async def model(controller): # pylint: disable=redefined-outer-name
47 await asyncio.sleep(1)
48
49
50-@pytest.fixture()
51+@pytest_asyncio.fixture()
52 async def get_app(model): # pylint: disable=redefined-outer-name
53 """Return the application requested."""
54
55@@ -83,7 +86,7 @@ async def get_app(model): # pylint: disable=redefined-outer-name
56 return _get_app
57
58
59-@pytest.fixture()
60+@pytest_asyncio.fixture()
61 async def get_unit(model): # pylint: disable=redefined-outer-name
62 """Return the requested <app_name>/<unit_number> unit."""
63
64@@ -97,7 +100,7 @@ async def get_unit(model): # pylint: disable=redefined-outer-name
65 return _get_unit
66
67
68-@pytest.fixture()
69+@pytest_asyncio.fixture()
70 async def get_entity(get_unit, get_app): # pylint: disable=redefined-outer-name
71 """Return a unit or an application."""
72
73@@ -113,7 +116,7 @@ async def get_entity(get_unit, get_app): # pylint: disable=redefined-outer-name
74 return _get_entity
75
76
77-@pytest.fixture
78+@pytest_asyncio.fixture
79 async def run_command(get_unit): # pylint: disable=redefined-outer-name
80 """Run a command on a unit.
81
82@@ -129,7 +132,7 @@ async def run_command(get_unit): # pylint: disable=redefined-outer-name
83 return _run_command
84
85
86-@pytest.fixture
87+@pytest_asyncio.fixture
88 async def file_stat(run_command): # pylint: disable=redefined-outer-name
89 """Run stat on a file.
90
91@@ -152,7 +155,7 @@ async def file_stat(run_command): # pylint: disable=redefined-outer-name
92 return _file_stat
93
94
95-@pytest.fixture
96+@pytest_asyncio.fixture
97 async def file_contents(run_command): # pylint: disable=redefined-outer-name
98 """Return the contents of a file.
99
100@@ -168,7 +171,7 @@ async def file_contents(run_command): # pylint: disable=redefined-outer-name
101 return _file_contents
102
103
104-@pytest.fixture
105+@pytest_asyncio.fixture
106 async def reconfigure_app(get_app, model): # pylint: disable=redefined-outer-name
107 """Apply a different config to the requested app."""
108
109diff --git a/src/tests/functional/requirements.txt b/src/tests/functional/requirements.txt
110index a10cbae..457c0ae 100644
111--- a/src/tests/functional/requirements.txt
112+++ b/src/tests/functional/requirements.txt
113@@ -1,8 +1,7 @@
114-flake8
115-juju
116+juju < 3.0.0
117 mock
118-pytest<6
119-pytest-asyncio<0.17.*
120+pytest
121+pytest-asyncio
122 requests
123 charmhelpers
124 charms.reactive
125diff --git a/src/tests/functional/test_hwhealth.py b/src/tests/functional/test_hwhealth.py
126index 936d9c8..c97cec7 100644
127--- a/src/tests/functional/test_hwhealth.py
128+++ b/src/tests/functional/test_hwhealth.py
129@@ -12,6 +12,8 @@ from hwhealth import tools # noqa: E402
130
131 import pytest # noqa: E402
132
133+import pytest_asyncio # noqa: E402
134+
135
136 # Treat all tests as coroutines
137 pytestmark = pytest.mark.asyncio
138@@ -68,7 +70,7 @@ async def update_hwhealth_res(model, app_name, res_filename):
139 ###################
140
141
142-@pytest.fixture(scope="module", params=SERIES)
143+@pytest_asyncio.fixture(scope="module", params=SERIES)
144 async def deploy_app(request, model):
145 """Deploy the hw-health charm as a subordinate of ubuntu."""
146 # TODO: this might look nicer if we deployed a bundle instead. It could be
147@@ -78,25 +80,34 @@ async def deploy_app(request, model):
148 hw_health_app_name = "hw-health-{}".format(release)
149 hw_health_checksum_app_name = "hw-health-checksum-{}".format(release)
150
151- for principal_app in ["ubuntu", "nagios"]:
152+ if release == "focal":
153+ # NOTE(aluria): nagios was not available in focal
154+ # On the other hand, bionic testing would create nagios-bionic
155+ # hence nagios-bionic2
156+ relname = "bionic2"
157+ series = "bionic"
158+ else:
159 relname = series = release
160- if principal_app == "nagios" and release == "focal":
161- # NOTE(aluria): cs:nagios was not available in focal
162- # On the other hand, bionic testing would create nagios-bionic
163- # hence nagios-bionic2
164- relname = "bionic2"
165- series = "bionic"
166- await model.deploy(
167- principal_app,
168- application_name="{}-{}".format(principal_app, relname),
169- series=series,
170- channel=channel,
171- )
172+
173+ await model.deploy(
174+ "nagios",
175+ application_name="{}-{}".format("nagios", relname),
176+ series=series,
177+ channel=channel,
178+ )
179+ await model.deploy(
180+ "ubuntu",
181+ application_name="{}-{}".format("ubuntu", release),
182+ series=release,
183+ channel=channel,
184+ to="lxd", # to ensure that hw-health would be deployed on LXD container
185+ )
186 await model.deploy(
187 "ubuntu",
188 application_name="ubuntu-checksum-{}".format(release),
189 series=release,
190 channel=channel,
191+ to="lxd", # to ensure that hw-health would be deployed on LXD container
192 )
193 nrpe_app = await model.deploy(
194 "nrpe",
195@@ -105,10 +116,12 @@ async def deploy_app(request, model):
196 num_units=0,
197 channel=channel,
198 )
199- for ubuntu_unit in ["ubuntu", "ubuntu-checksum"]:
200- await nrpe_app.add_relation(
201- "general-info", "{}-{}:juju-info".format(ubuntu_unit, release)
202- )
203+ await nrpe_app.add_relation(
204+ "general-info", "{}-{}:juju-info".format("ubuntu", release)
205+ )
206+ await nrpe_app.add_relation(
207+ "general-info", "{}-{}:juju-info".format("ubuntu-checksum", release)
208+ )
209 await nrpe_app.add_relation("monitors", "nagios-{}:monitors".format(relname))
210
211 # Attaching resources is not implemented yet in libjuju
212@@ -116,14 +129,12 @@ async def deploy_app(request, model):
213 await deploy_hwhealth_res(model, hw_health_app_name, "tools.zip")
214 await deploy_hwhealth_res(model, hw_health_checksum_app_name, "tools-checksum.zip")
215
216- # This is pretty horrible, but we can't deploy via libjuju
217- while True:
218- try:
219- hw_health_app = model.applications[hw_health_app_name]
220- hw_health_checksum_app = model.applications[hw_health_checksum_app_name]
221- break
222- except KeyError:
223- await asyncio.sleep(5)
224+ other_apps = [
225+ app for app in model.applications if not app.startswith == "hw-health"
226+ ]
227+ await model.wait_for_idle(apps=other_apps, timeout=DEF_TIMEOUT)
228+ hw_health_app = model.applications[hw_health_app_name]
229+ hw_health_checksum_app = model.applications[hw_health_checksum_app_name]
230
231 await hw_health_app.add_relation(
232 "general-info", "ubuntu-{}:juju-info".format(release)
233@@ -139,19 +150,15 @@ async def deploy_app(request, model):
234 "nrpe-external-master", "{}:nrpe-external-master".format(nrpe_app.name)
235 )
236
237- # The app will initially be in blocked state because it's running in a
238- # container
239- await model.block_until(
240- lambda: (
241- hw_health_app.status == "blocked"
242- and hw_health_checksum_app.status == "blocked" # noqa W503
243- ),
244+ await model.wait_for_idle(
245+ apps=[hw_health_app_name, hw_health_checksum_app_name],
246+ status="blocked",
247 timeout=DEF_TIMEOUT,
248 )
249 yield hw_health_app
250
251
252-@pytest.fixture(scope="module")
253+@pytest_asyncio.fixture(scope="module")
254 async def deployed_unit(deploy_app):
255 """Return the hw-health unit we've deployed."""
256 return deploy_app.units[0]
257@@ -163,7 +170,7 @@ def _monkey_config(k=None):
258 return {"manufacturer": "test"}.get(k)
259
260
261-@pytest.fixture(scope="function")
262+@pytest_asyncio.fixture(scope="function")
263 async def toolset(monkeypatch):
264 # All tool classes know which files should be installed and how, so we can
265 # use them to read the expected stat results. Monkeypatching is however
266@@ -193,15 +200,11 @@ async def test_forced_deploy(deploy_app, model, run_command):
267 # Create a fake NVMe device for the cronjob to be configured
268 create_fake_nvme_cmd = "/bin/bash -c 'touch /dev/nvme0'"
269 series = deploy_app.name.split("-")[-1]
270- for unit in model.units.values():
271- if unit.entity_id.startswith("ubuntu-{}".format(series)):
272- ubuntu_unit = unit
273- await model.block_until(
274- lambda: ubuntu_unit.workload_status == "active", timeout=DEF_TIMEOUT
275- )
276- await run_command(create_fake_nvme_cmd, ubuntu_unit)
277- break
278-
279+ ubuntu_unit = model.applications["ubuntu-{}".format(series)].units[0]
280+ await model.block_until(
281+ lambda: ubuntu_unit.workload_status == "active", timeout=DEF_TIMEOUT
282+ )
283+ await run_command(create_fake_nvme_cmd, ubuntu_unit)
284 await deploy_app.set_config({"manufacturer": "test"})
285 await model.block_until(lambda: deploy_app.status == "active", timeout=DEF_TIMEOUT)
286 assert deploy_app.status == "active"

Subscribers

People subscribed via source and target branches

to all changes: