Merge ~logrotate-charmers/charm-logrotated:bugs_1833095_1833093 into charm-logrotated:master
- Git
- lp:~logrotate-charmers/charm-logrotated
- bugs_1833095_1833093
- Merge into master
Proposed by
Jeremy Lounder
Status: | Merged |
---|---|
Approved by: | Paul Goins |
Approved revision: | 6d391ef597fad5552bfdee132025c4aa603a21d9 |
Merged at revision: | b2e03efd1888e6644d178af2f5f098ee326e9df5 |
Proposed branch: | ~logrotate-charmers/charm-logrotated:bugs_1833095_1833093 |
Merge into: | charm-logrotated:master |
Diff against target: |
674 lines (+151/-132) 10 files modified
actions/actions.py (+12/-21) dev/null (+0/-13) lib/lib_cron.py (+38/-32) lib/lib_logrotate.py (+20/-25) reactive/logrotate.py (+20/-8) tests/functional/conftest.py (+14/-9) tests/functional/juju_tools.py (+14/-13) tests/functional/test_logrotate.py (+5/-2) tests/unit/conftest.py (+11/-0) tests/unit/test_logrotate.py (+17/-9) |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Paul Goins | Approve | ||
Canonical IS Reviewers | Pending | ||
Review via email: mp+378375@code.launchpad.net |
Commit message
LP#1833095 LP#1833093 Fixes linting and unit test issues.
Description of the change
To post a comment you must log in.
Revision history for this message
🤖 Canonical IS Merge Bot (canonical-is-mergebot) wrote : | # |
Revision history for this message
🤖 Canonical IS Merge Bot (canonical-is-mergebot) wrote : | # |
Unable to determine commit message from repository - please click "Set commit message" and enter the commit message manually.
Revision history for this message
Paul Goins (vultaire) wrote : | # |
Looks pretty good. I've suggested a few small improvements, although functionally the code is fine as-is without them. However, removal of the copyright blocks concerns me - I think those need to be restored.
review:
Needs Fixing
Revision history for this message
Paul Goins (vultaire) wrote : | # |
Adding one more comment
Revision history for this message
Paul Goins (vultaire) wrote : | # |
Created bug regarding this code review: https:/
As this code is already merged into the current released charm, am merging this as-is.
review:
Approve
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | diff --git a/actions/__init__.py b/actions/__init__.py |
2 | deleted file mode 100755 |
3 | index 9b088de..0000000 |
4 | --- a/actions/__init__.py |
5 | +++ /dev/null |
6 | @@ -1,13 +0,0 @@ |
7 | -# Copyright 2016 Canonical Ltd |
8 | -# |
9 | -# Licensed under the Apache License, Version 2.0 (the "License"); |
10 | -# you may not use this file except in compliance with the License. |
11 | -# You may obtain a copy of the License at |
12 | -# |
13 | -# http://www.apache.org/licenses/LICENSE-2.0 |
14 | -# |
15 | -# Unless required by applicable law or agreed to in writing, software |
16 | -# distributed under the License is distributed on an "AS IS" BASIS, |
17 | -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
18 | -# See the License for the specific language governing permissions and |
19 | -# limitations under the License. |
20 | diff --git a/actions/actions.py b/actions/actions.py |
21 | index aee6bb7..8178850 100755 |
22 | --- a/actions/actions.py |
23 | +++ b/actions/actions.py |
24 | @@ -1,45 +1,36 @@ |
25 | #!/usr/bin/env python3 |
26 | -# |
27 | -# Copyright 2016 Canonical Ltd |
28 | -# |
29 | -# Licensed under the Apache License, Version 2.0 (the "License"); |
30 | -# you may not use this file except in compliance with the License. |
31 | -# You may obtain a copy of the License at |
32 | -# |
33 | -# http://www.apache.org/licenses/LICENSE-2.0 |
34 | -# |
35 | -# Unless required by applicable law or agreed to in writing, software |
36 | -# distributed under the License is distributed on an "AS IS" BASIS, |
37 | -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
38 | -# See the License for the specific language governing permissions and |
39 | -# limitations under the License. |
40 | +"""Actions module.""" |
41 | |
42 | import os |
43 | import sys |
44 | |
45 | -sys.path.insert(0, os.path.join(os.environ['CHARM_DIR'], 'lib')) |
46 | -from charmhelpers.core import ( |
47 | - hookenv, |
48 | - host, |
49 | -) |
50 | +from charmhelpers.core import hookenv |
51 | |
52 | -from lib_logrotate import LogrotateHelper |
53 | from lib_cron import CronHelper |
54 | |
55 | +from lib_logrotate import LogrotateHelper |
56 | + |
57 | +sys.path.insert(0, os.path.join(os.environ['CHARM_DIR'], 'lib')) |
58 | + |
59 | hooks = hookenv.Hooks() |
60 | logrotate = LogrotateHelper() |
61 | cron = CronHelper() |
62 | |
63 | + |
64 | @hooks.hook("update-logrotate-files") |
65 | def update_logrotate_files(): |
66 | + """Update the logrotate files.""" |
67 | logrotate.read_config() |
68 | logrotate.modify_configs() |
69 | |
70 | + |
71 | @hooks.hook("update-cronjob") |
72 | def update_cronjob(): |
73 | + """Update the cronjob file.""" |
74 | cron.read_config() |
75 | cron.install_cronjob() |
76 | |
77 | + |
78 | if __name__ == "__main__": |
79 | + """Main function.""" |
80 | hooks.execute(sys.argv) |
81 | - |
82 | diff --git a/lib/lib_cron.py b/lib/lib_cron.py |
83 | index 15bcdaf..f560084 100644 |
84 | --- a/lib/lib_cron.py |
85 | +++ b/lib/lib_cron.py |
86 | @@ -1,24 +1,27 @@ |
87 | +"""Cron helper module.""" |
88 | import os |
89 | -import re |
90 | + |
91 | from lib_logrotate import LogrotateHelper |
92 | |
93 | + |
94 | class CronHelper: |
95 | """Helper class for logrotate charm.""" |
96 | |
97 | - @classmethod |
98 | def __init__(self): |
99 | - """Init function""" |
100 | - self.cronjob_check_paths = [ "hourly", "daily", "weekly", "monthly" ] |
101 | + """Init function.""" |
102 | + self.cronjob_base_path = "/etc/cron." |
103 | + self.cronjob_etc_config = "/etc/logrotate_cronjob_config" |
104 | + self.cronjob_check_paths = ["hourly", "daily", "weekly", "monthly"] |
105 | self.cronjob_logrotate_cron_file = "charm-logrotate" |
106 | |
107 | - |
108 | - @classmethod |
109 | def read_config(self): |
110 | - """Config changed/install hooks dumps config out to disk, |
111 | - Here we read that config to update the cronjob""" |
112 | + """Read the configuration from the file. |
113 | |
114 | - config_file = open("/etc/logrotate_cronjob_config", "r") |
115 | - lines = config_file.read() |
116 | + Config changed/install hooks dumps config out to disk, |
117 | + Here we read that config to update the cronjob. |
118 | + """ |
119 | + config_file = open(self.cronjob_etc_config, "r") |
120 | + lines = config_file.read() |
121 | lines = lines.split('\n') |
122 | |
123 | if lines[0] == 'True': |
124 | @@ -28,51 +31,54 @@ class CronHelper: |
125 | |
126 | self.cronjob_frequency = int(self.cronjob_check_paths.index(lines[1])) |
127 | |
128 | - |
129 | - @classmethod |
130 | def install_cronjob(self): |
131 | - """If logrotate-cronjob config option is set to True |
132 | - install cronjob. Otherwise cleanup""" |
133 | + """Install the cron job task. |
134 | |
135 | + If logrotate-cronjob config option is set to True install cronjob, |
136 | + otherwise cleanup. |
137 | + """ |
138 | clean_up_file = self.cronjob_frequency if self.cronjob_enabled else -1 |
139 | |
140 | if self.cronjob_enabled is True: |
141 | path_to_lib = os.path.realpath(__file__) |
142 | - cron_file_path = "/etc/cron." + self.cronjob_check_paths[clean_up_file] \ |
143 | - + "/" + self.cronjob_logrotate_cron_file |
144 | + cron_file_path = self.cronjob_base_path\ |
145 | + + self.cronjob_check_paths[clean_up_file]\ |
146 | + + "/" + self.cronjob_logrotate_cron_file |
147 | |
148 | # upgrade to template if logic increases |
149 | cron_file = open(cron_file_path, 'w') |
150 | cron_file.write("#!/bin/sh\n/usr/bin/python3 " + path_to_lib + "\n\n") |
151 | cron_file.close() |
152 | - os.chmod(cron_file_path,700) |
153 | - |
154 | - self.cleanup_cronjob(clean_up_file) |
155 | + os.chmod(cron_file_path, 700) |
156 | |
157 | + self.cleanup_cronjob(clean_up_file) |
158 | |
159 | - @classmethod |
160 | - def cleanup_cronjob(self, frequency = -1): |
161 | - """Cleanup previous config""" |
162 | - for i in range(4): |
163 | - if frequency != i: |
164 | - path = "/etc/cron." + self.cronjob_check_paths[i] + "/" +\ |
165 | - self.cronjob_logrotate_cron_file |
166 | + def cleanup_cronjob(self, frequency=-1): |
167 | + """Cleanup previous config.""" |
168 | + if frequency == -1: |
169 | + for check_path in self.cronjob_check_paths: |
170 | + path = self.cronjob_base_path \ |
171 | + + check_path \ |
172 | + + "/" \ |
173 | + + self.cronjob_logrotate_cron_file |
174 | if os.path.exists(path): |
175 | os.remove(path) |
176 | + if os.path.exists(self.cronjob_etc_config): |
177 | + os.remove(self.cronjob_etc_config) |
178 | |
179 | - @classmethod |
180 | def update_logrotate_etc(self): |
181 | - """Run logrotate update config""" |
182 | + """Run logrotate update config.""" |
183 | logrotate = LogrotateHelper() |
184 | logrotate.read_config() |
185 | logrotate.modify_configs() |
186 | |
187 | |
188 | def main(): |
189 | - cronHelper = CronHelper() |
190 | - cronHelper.read_config() |
191 | - cronHelper.update_logrotate_etc() |
192 | - cronHelper.install_cronjob() |
193 | + """Ran by cron.""" |
194 | + cronhelper = CronHelper() |
195 | + cronhelper.read_config() |
196 | + cronhelper.update_logrotate_etc() |
197 | + cronhelper.install_cronjob() |
198 | |
199 | |
200 | if __name__ == '__main__': |
201 | diff --git a/lib/lib_logrotate.py b/lib/lib_logrotate.py |
202 | index 145a41b..67245cb 100644 |
203 | --- a/lib/lib_logrotate.py |
204 | +++ b/lib/lib_logrotate.py |
205 | @@ -1,6 +1,8 @@ |
206 | +"""Logrotate module.""" |
207 | import os |
208 | import re |
209 | |
210 | +from charmhelpers.core import hookenv |
211 | |
212 | LOGROTATE_DIR = "/etc/logrotate.d/" |
213 | |
214 | @@ -8,27 +10,24 @@ LOGROTATE_DIR = "/etc/logrotate.d/" |
215 | class LogrotateHelper: |
216 | """Helper class for logrotate charm.""" |
217 | |
218 | - @classmethod |
219 | def __init__(self): |
220 | - """Init function""" |
221 | - pass |
222 | + """Init function.""" |
223 | + self.retention = hookenv.config('logrotate-retention') |
224 | |
225 | - @classmethod |
226 | def read_config(self): |
227 | - """Config changed/install hooks dumps config out to disk, |
228 | - Here we read that config to update the cronjob""" |
229 | + """Read changes from disk. |
230 | |
231 | + Config changed/install hooks dumps config out to disk, |
232 | + Here we read that config to update the cronjob |
233 | + """ |
234 | config_file = open("/etc/logrotate_cronjob_config", "r") |
235 | lines = config_file.read() |
236 | lines = lines.split('\n') |
237 | |
238 | self.retention = int(lines[2]) |
239 | |
240 | - |
241 | - @classmethod |
242 | def modify_configs(self): |
243 | """Modify the logrotate config files.""" |
244 | - |
245 | for config_file in os.listdir(LOGROTATE_DIR): |
246 | file_path = LOGROTATE_DIR + config_file |
247 | |
248 | @@ -44,11 +43,8 @@ class LogrotateHelper: |
249 | logrotate_file.write(mod_contents) |
250 | logrotate_file.close() |
251 | |
252 | - |
253 | - @classmethod |
254 | def modify_content(self, content): |
255 | - """Helper function to edit the content of a logrotate file.""" |
256 | - |
257 | + """Edit the content of a logrotate file.""" |
258 | # Split the contents in a logrotate file in separate entries (if |
259 | # multiple are found in the file) and put in a list for further |
260 | # processing |
261 | @@ -66,7 +62,7 @@ class LogrotateHelper: |
262 | # the rotate option to the appropriate value |
263 | results = [] |
264 | for item in items: |
265 | - count = self.calculate_count(item) |
266 | + count = self.calculate_count(item, self.retention) |
267 | rotate = 'rotate {}'.format(count) |
268 | result = re.sub(r'rotate \d+\.?[0-9]*', rotate, item) |
269 | results.append(result) |
270 | @@ -75,12 +71,9 @@ class LogrotateHelper: |
271 | |
272 | return results |
273 | |
274 | - @classmethod |
275 | def modify_header(self, content): |
276 | - """Helper function to add Juju headers to the file.""" |
277 | - |
278 | - header = ("# Configuration file maintained by Juju. " |
279 | - "Local changes may be overwritten") |
280 | + """Add Juju headers to the file.""" |
281 | + header = "# Configuration file maintained by Juju. Local changes may be overwritten" |
282 | |
283 | split = content.split('\n') |
284 | if split[0].startswith(header): |
285 | @@ -91,20 +84,22 @@ class LogrotateHelper: |
286 | return result |
287 | |
288 | @classmethod |
289 | - def calculate_count(self, item): |
290 | + def calculate_count(cls, item, retention): |
291 | """Calculate rotate based on rotation interval. Always round up.""" |
292 | - |
293 | + # Fallback to default lowest retention - days |
294 | + # better to keep the logs than lose them |
295 | + count = retention |
296 | # Daily 1:1 to configuration retention period (in days) |
297 | if 'daily' in item: |
298 | - count = self.retention |
299 | + count = retention |
300 | # Weekly rounding up, as weeks are 7 days |
301 | if 'weekly' in item: |
302 | - count = int(round(self.retention/7)) |
303 | + count = int(round(retention/7)) |
304 | # Monthly default 30 days and round up because of 28/31 days months |
305 | if 'monthly' in item: |
306 | - count = int(round(self.retention/30)) |
307 | + count = int(round(retention/30)) |
308 | # For every 360 days - add 1 year |
309 | if 'yearly' in item: |
310 | - count = self.retention // 360 + 1 if self.retention > 360 else 1 |
311 | + count = retention // 360 + 1 if retention > 360 else 1 |
312 | |
313 | return count |
314 | diff --git a/reactive/logrotate.py b/reactive/logrotate.py |
315 | index 4a8d5c1..1810707 100644 |
316 | --- a/reactive/logrotate.py |
317 | +++ b/reactive/logrotate.py |
318 | @@ -1,36 +1,48 @@ |
319 | -from lib_logrotate import LogrotateHelper |
320 | -from lib_cron import CronHelper |
321 | +"""Reactive charm hooks.""" |
322 | from charmhelpers.core import hookenv |
323 | + |
324 | from charms.reactive import set_flag, when, when_not |
325 | |
326 | +from lib_cron import CronHelper |
327 | + |
328 | +from lib_logrotate import LogrotateHelper |
329 | + |
330 | + |
331 | +hooks = hookenv.Hooks() |
332 | logrotate = LogrotateHelper() |
333 | cron = CronHelper() |
334 | |
335 | + |
336 | @when_not('logrotate.installed') |
337 | def install_logrotate(): |
338 | - dump_config_to_disk(); |
339 | + """Install the logrotate charm.""" |
340 | + dump_config_to_disk() |
341 | logrotate.read_config() |
342 | cron.read_config() |
343 | logrotate.modify_configs() |
344 | hookenv.status_set('active', 'Unit is ready.') |
345 | set_flag('logrotate.installed') |
346 | - cron.install_cronjob(); |
347 | + cron.install_cronjob() |
348 | + |
349 | |
350 | @when('config.changed') |
351 | def config_changed(): |
352 | + """Run when configuration changes.""" |
353 | dump_config_to_disk() |
354 | cron.read_config() |
355 | logrotate.read_config() |
356 | hookenv.status_set('maintenance', 'Modifying configs.') |
357 | logrotate.modify_configs() |
358 | hookenv.status_set('active', 'Unit is ready.') |
359 | - cron.install_cronjob(); |
360 | + cron.install_cronjob() |
361 | + |
362 | |
363 | def dump_config_to_disk(): |
364 | + """Dump configurations to disk.""" |
365 | cronjob_enabled = hookenv.config('logrotate-cronjob') |
366 | cronjob_frequency = hookenv.config('logrotate-cronjob-frequency') |
367 | logrotate_retention = hookenv.config('logrotate-retention') |
368 | with open('/etc/logrotate_cronjob_config', 'w+') as cronjob_config_file: |
369 | - cronjob_config_file.write(str(cronjob_enabled) + '\n') |
370 | - cronjob_config_file.write(str(cronjob_frequency) + '\n') |
371 | - cronjob_config_file.write(str(logrotate_retention) + '\n') |
372 | + cronjob_config_file.write(str(cronjob_enabled) + '\n') |
373 | + cronjob_config_file.write(str(cronjob_frequency) + '\n') |
374 | + cronjob_config_file.write(str(logrotate_retention) + '\n') |
375 | diff --git a/tests/functional/conftest.py b/tests/functional/conftest.py |
376 | index 56925ff..1b22cb8 100644 |
377 | --- a/tests/functional/conftest.py |
378 | +++ b/tests/functional/conftest.py |
379 | @@ -1,28 +1,32 @@ |
380 | #!/usr/bin/python3 |
381 | -''' |
382 | -Reusable pytest fixtures for functional testing |
383 | +""" |
384 | +Reusable pytest fixtures for functional testing. |
385 | |
386 | Environment variables |
387 | --------------------- |
388 | |
389 | test_preserve_model: |
390 | if set, the testing model won't be torn down at the end of the testing session |
391 | -''' |
392 | +""" |
393 | |
394 | import asyncio |
395 | import os |
396 | -import uuid |
397 | -import pytest |
398 | import subprocess |
399 | +import uuid |
400 | |
401 | from juju.controller import Controller |
402 | + |
403 | from juju_tools import JujuTools |
404 | |
405 | +import pytest |
406 | + |
407 | |
408 | @pytest.fixture(scope='module') |
409 | def event_loop(): |
410 | - '''Override the default pytest event loop to allow for fixtures using a |
411 | - broader scope''' |
412 | + """Override the default pytest event loop. |
413 | + |
414 | + Do this too allow for fixtures using a broader scope. |
415 | + """ |
416 | loop = asyncio.get_event_loop_policy().new_event_loop() |
417 | asyncio.set_event_loop(loop) |
418 | loop.set_debug(True) |
419 | @@ -33,7 +37,7 @@ def event_loop(): |
420 | |
421 | @pytest.fixture(scope='module') |
422 | async def controller(): |
423 | - '''Connect to the current controller''' |
424 | + """Connect to the current controller.""" |
425 | _controller = Controller() |
426 | await _controller.connect_current() |
427 | yield _controller |
428 | @@ -42,7 +46,7 @@ async def controller(): |
429 | |
430 | @pytest.fixture(scope='module') |
431 | async def model(controller): |
432 | - '''This model lives only for the duration of the test''' |
433 | + """Live only for the duration of the test.""" |
434 | model_name = "functest-{}".format(str(uuid.uuid4())[-12:]) |
435 | _model = await controller.add_model(model_name, |
436 | cloud_name=os.getenv('PYTEST_CLOUD_NAME'), |
437 | @@ -62,5 +66,6 @@ async def model(controller): |
438 | |
439 | @pytest.fixture(scope='module') |
440 | async def jujutools(controller, model): |
441 | + """Juju tools.""" |
442 | tools = JujuTools(controller, model) |
443 | return tools |
444 | diff --git a/tests/functional/juju_tools.py b/tests/functional/juju_tools.py |
445 | index 2fd501d..5e4a1cc 100644 |
446 | --- a/tests/functional/juju_tools.py |
447 | +++ b/tests/functional/juju_tools.py |
448 | @@ -1,22 +1,26 @@ |
449 | +"""Juju tools.""" |
450 | +import base64 |
451 | import pickle |
452 | + |
453 | import juju |
454 | -import base64 |
455 | |
456 | # from juju.errors import JujuError |
457 | |
458 | |
459 | class JujuTools: |
460 | + """Juju tools.""" |
461 | + |
462 | def __init__(self, controller, model): |
463 | + """Init.""" |
464 | self.controller = controller |
465 | self.model = model |
466 | |
467 | async def run_command(self, cmd, target): |
468 | - ''' |
469 | - Runs a command on a unit. |
470 | + """Run a command on a unit. |
471 | |
472 | :param cmd: Command to be run |
473 | :param unit: Unit object or unit name string |
474 | - ''' |
475 | + """ |
476 | unit = ( |
477 | target |
478 | if isinstance(target, juju.unit.Unit) |
479 | @@ -26,13 +30,12 @@ class JujuTools: |
480 | return action.results |
481 | |
482 | async def remote_object(self, imports, remote_cmd, target): |
483 | - ''' |
484 | - Runs command on target machine and returns a python object of the result |
485 | + """Run command on target machine and returns a python object of the result. |
486 | |
487 | :param imports: Imports needed for the command to run |
488 | :param remote_cmd: The python command to execute |
489 | :param target: Unit object or unit name string |
490 | - ''' |
491 | + """ |
492 | python3 = "python3 -c '{}'" |
493 | python_cmd = ('import pickle;' |
494 | 'import base64;' |
495 | @@ -44,12 +47,11 @@ class JujuTools: |
496 | return pickle.loads(base64.b64decode(bytes(results['Stdout'][2:-1], 'utf8'))) |
497 | |
498 | async def file_stat(self, path, target): |
499 | - ''' |
500 | - Runs stat on a file |
501 | + """Run stat on a file. |
502 | |
503 | :param path: File path |
504 | :param target: Unit object or unit name string |
505 | - ''' |
506 | + """ |
507 | imports = 'import os;' |
508 | python_cmd = ('os.stat("{}")' |
509 | .format(path)) |
510 | @@ -57,12 +59,11 @@ class JujuTools: |
511 | return await self.remote_object(imports, python_cmd, target) |
512 | |
513 | async def file_contents(self, path, target): |
514 | - ''' |
515 | - Returns the contents of a file |
516 | + """Return the contents of a file. |
517 | |
518 | :param path: File path |
519 | :param target: Unit object or unit name string |
520 | - ''' |
521 | + """ |
522 | cmd = 'cat {}'.format(path) |
523 | result = await self.run_command(cmd, target) |
524 | return result['Stdout'] |
525 | diff --git a/tests/functional/test_logrotate.py b/tests/functional/test_logrotate.py |
526 | index b4402be..100690f 100644 |
527 | --- a/tests/functional/test_logrotate.py |
528 | +++ b/tests/functional/test_logrotate.py |
529 | @@ -1,6 +1,8 @@ |
530 | #!/usr/bin/python3.6 |
531 | +"""Main module for functional testing.""" |
532 | |
533 | import os |
534 | + |
535 | import pytest |
536 | |
537 | pytestmark = pytest.mark.asyncio |
538 | @@ -16,7 +18,7 @@ SERIES = ['xenial', |
539 | @pytest.fixture(scope='module', |
540 | params=SERIES) |
541 | async def deploy_app(request, model): |
542 | - '''Deploys the logrotate charm as a subordinate of ubuntu''' |
543 | + """Deploy the logrotate charm as a subordinate of ubuntu.""" |
544 | release = request.param |
545 | |
546 | await model.deploy( |
547 | @@ -42,7 +44,7 @@ async def deploy_app(request, model): |
548 | |
549 | @pytest.fixture(scope='module') |
550 | async def unit(deploy_app): |
551 | - '''Returns the logrotate unit we've deployed''' |
552 | + """Return the logrotate unit we've deployed.""" |
553 | return deploy_app.units.pop() |
554 | |
555 | ######### |
556 | @@ -51,4 +53,5 @@ async def unit(deploy_app): |
557 | |
558 | |
559 | async def test_deploy(deploy_app): |
560 | + """Tst the deployment.""" |
561 | assert deploy_app.status == 'active' |
562 | diff --git a/tests/unit/conftest.py b/tests/unit/conftest.py |
563 | index 534e654..8520709 100644 |
564 | --- a/tests/unit/conftest.py |
565 | +++ b/tests/unit/conftest.py |
566 | @@ -1,11 +1,15 @@ |
567 | #!/usr/bin/python3 |
568 | +"""Configurations for tests.""" |
569 | + |
570 | import mock |
571 | + |
572 | import pytest |
573 | |
574 | # If layer options are used, add this to ${fixture} |
575 | # and import layer in logrotate |
576 | @pytest.fixture |
577 | def mock_layers(monkeypatch): |
578 | + """Layers mock.""" |
579 | import sys |
580 | sys.modules['charms.layer'] = mock.Mock() |
581 | sys.modules['reactive'] = mock.Mock() |
582 | @@ -21,8 +25,10 @@ def mock_layers(monkeypatch): |
583 | |
584 | monkeypatch.setattr('lib_logrotate.layer.options', options) |
585 | |
586 | + |
587 | @pytest.fixture |
588 | def mock_hookenv_config(monkeypatch): |
589 | + """Hookenv mock.""" |
590 | import yaml |
591 | |
592 | def mock_config(): |
593 | @@ -39,17 +45,22 @@ def mock_hookenv_config(monkeypatch): |
594 | |
595 | monkeypatch.setattr('lib_logrotate.hookenv.config', mock_config) |
596 | |
597 | + |
598 | @pytest.fixture |
599 | def mock_remote_unit(monkeypatch): |
600 | + """Remote unit mock.""" |
601 | monkeypatch.setattr('lib_logrotate.hookenv.remote_unit', lambda: 'unit-mock/0') |
602 | |
603 | |
604 | @pytest.fixture |
605 | def mock_charm_dir(monkeypatch): |
606 | + """Charm dir mock.""" |
607 | monkeypatch.setattr('lib_logrotate.hookenv.charm_dir', lambda: '/mock/charm/dir') |
608 | |
609 | + |
610 | @pytest.fixture |
611 | def logrotate(tmpdir, mock_hookenv_config, mock_charm_dir, monkeypatch): |
612 | + """Logrotate fixture.""" |
613 | from lib_logrotate import LogrotateHelper |
614 | helper = LogrotateHelper |
615 | |
616 | diff --git a/tests/unit/test_logrotate.py b/tests/unit/test_logrotate.py |
617 | index 1f0ed9b..b01c7b5 100644 |
618 | --- a/tests/unit/test_logrotate.py |
619 | +++ b/tests/unit/test_logrotate.py |
620 | @@ -1,37 +1,45 @@ |
621 | -from unittest.mock import patch |
622 | +"""Main unit test module.""" |
623 | + |
624 | |
625 | class TestLogrotateHelper(): |
626 | + """Main test class.""" |
627 | + |
628 | def test_pytest(self): |
629 | + """Simple pytest.""" |
630 | assert True |
631 | |
632 | - |
633 | def test_daily_retention_count(self, logrotate): |
634 | + """Test daily retention count.""" |
635 | logrotate.retention = 90 |
636 | contents = '/var/log/some.log {\n rotate 123\n daily\n}' |
637 | - count = logrotate.calculate_count(contents) |
638 | + count = logrotate.calculate_count(contents, logrotate.retention) |
639 | assert count == 90 |
640 | |
641 | def test_weekly_retention_count(self, logrotate): |
642 | + """Test weekly retention count.""" |
643 | logrotate.retention = 21 |
644 | contents = '/var/log/some.log {\n rotate 123\n weekly\n}' |
645 | - count = logrotate.calculate_count(contents) |
646 | + count = logrotate.calculate_count(contents, logrotate.retention) |
647 | assert count == 3 |
648 | |
649 | def test_monthly_retention_count(self, logrotate): |
650 | + """Test monthly retention count.""" |
651 | logrotate.retention = 60 |
652 | contents = '/var/log/some.log {\n rotate 123\n monthly\n}' |
653 | - count = logrotate.calculate_count(contents) |
654 | + count = logrotate.calculate_count(contents, logrotate.retention) |
655 | assert count == 2 |
656 | |
657 | def test_yearly_retention_count(self, logrotate): |
658 | + """Test yearly retention count.""" |
659 | logrotate.retention = 180 |
660 | contents = '/var/log/some.log {\n rotate 123\n yearly\n}' |
661 | - count = logrotate.calculate_count(contents) |
662 | + count = logrotate.calculate_count(contents, logrotate.retention) |
663 | assert count == 1 |
664 | |
665 | def test_modify_content(self, logrotate): |
666 | + """Test the modify_content method.""" |
667 | logrotate.retention = 42 |
668 | - contents = '/var/log/some.log {\n rotate 123\n daily\n}\n/var/log/other.log {\n rotate 456\n weekly\n}' |
669 | - mod_contents = logrotate.modify_content(contents) |
670 | - expected_contents = '/var/log/some.log {\n rotate 42\n daily\n}\n\n/var/log/other.log {\n rotate 6\n weekly\n}\n' |
671 | + contents = '/log/some.log {\n rotate 123\n daily\n}\n/log/other.log {\n rotate 456\n weekly\n}' |
672 | + mod_contents = logrotate.modify_content(logrotate, contents) |
673 | + expected_contents = '/log/some.log {\n rotate 42\n daily\n}\n\n/log/other.log {\n rotate 6\n weekly\n}\n' |
674 | assert mod_contents == expected_contents |
This merge proposal is being monitored by mergebot. Change the status to Approved to merge.