From 0af272a8bc1bffcc3eda73c35b52eb9a8366877a Mon Sep 17 00:00:00 2001 From: Pascal Zimmermann Date: Fri, 16 Sep 2022 00:26:00 +0200 Subject: [PATCH] Add new tests and refactor the code --- .../__init__.py | 0 .../dashboard.py | 68 ++++++++++++++----- .../model.py | 0 setup.py | 5 +- tests/test_dashboard.py | 35 +++++++--- tests/test_model.py | 10 +-- 6 files changed, 82 insertions(+), 36 deletions(-) rename {src/grafana_dashboard => grafana_dashboard}/__init__.py (100%) rename {src/grafana_dashboard => grafana_dashboard}/dashboard.py (51%) rename {src/grafana_dashboard => grafana_dashboard}/model.py (100%) diff --git a/src/grafana_dashboard/__init__.py b/grafana_dashboard/__init__.py similarity index 100% rename from src/grafana_dashboard/__init__.py rename to grafana_dashboard/__init__.py diff --git a/src/grafana_dashboard/dashboard.py b/grafana_dashboard/dashboard.py similarity index 51% rename from src/grafana_dashboard/dashboard.py rename to grafana_dashboard/dashboard.py index 3bfcf04..03addfb 100644 --- a/src/grafana_dashboard/dashboard.py +++ b/grafana_dashboard/dashboard.py @@ -2,10 +2,12 @@ import sys import json import logging +from typing import Dict +import tempfile import jinja2 -from src.grafana_dashboard.model import Model +from .model import Model class Dashboard: @@ -23,18 +25,17 @@ def __init__(self, dashboard_model: Model): self.dashboard_model = dashboard_model self.logging = logging.Logger - def get_dashboard_json(self, template_values: dict) -> dict: - """The method includes a functionality to template the selected dashboard and return the corresponding dashboard - as dictionary + def get_dashboard_json(self, template_values: Dict) -> Dict: + """The method includes a functionality to template the selected dashboard and return the corresponding dashboard as dictionary Args: - template_values (dict): Specify the inserted templating values as dict + template_values (Dict): Specify the inserted templating values as dict Raises: - Exception: Unspecified error by executing the functionality + jinja2.TemplateNotFound: Jinja2 template not found Returns: - json_dashboard (dict): Returns the dashboard as dict + json_dashboard (Dict): Returns the dashboard as dict """ env = jinja2.Environment(loader=jinja2.FileSystemLoader("/")) @@ -52,26 +53,59 @@ def get_dashboard_json(self, template_values: dict) -> dict: logging.error("Please define templating values.") sys.exit(1) - temp_path: str = "/tmp/dashboard.json" + with tempfile.NamedTemporaryFile() as tmp_file: + self.__write_tmp_dashboard_json( + tmp_file.name, template_dashboard, template_values + ) + return self.__get_dashboard_json(tmp_file.name) + + @staticmethod + def __write_tmp_dashboard_json( + temp_path: str, template_dashboard: jinja2.Template, template_values: Dict + ): + """The method includes a functionality to write a templated json of the selected dashboard to a temporary file + + Args: + temp_path (str): Specify the temporary path as string + template_dashboard (jinja2.Template): Specify the Jinja2 templated dashboard + template_values (Dict): Specify the template values + + Raises: + FileNotFoundError: The corresponding temporary file is not available + ValueError: There is an error inside the values + AttributeError: You missed to add a specific attribute + + Returns: + None + """ try: fw = open(temp_path, "w") fw.write(template_dashboard.render(template_values)) fw.close() - except Exception as e: + except (FileNotFoundError, ValueError, AttributeError) as e: logging.error(f"Please, check the error: {e} .") raise e - try: - with open(temp_path) as file: - json_dashboard = json.load(file) - except Exception as e: - logging.error(f"Please, check the error: {e} .") - raise e + @staticmethod + def __get_dashboard_json(temp_path: str) -> Dict: + """The method includes a functionality to get the corresponding templated dashboard JSON as Dict + + Args: + temp_path (str): Specify the temporary path as string + + Raises: + FileNotFoundError: The corresponding temporary file is not available + ValueError: There is an error inside the values + + Returns: + json_dashboard (Dict): Returns the dashboard JSON as dict + """ try: - os.remove(temp_path) - except Exception as e: + with open(temp_path) as file: + json_dashboard: Dict = json.load(file) + except (FileNotFoundError, ValueError) as e: logging.error(f"Please, check the error: {e} .") raise e diff --git a/src/grafana_dashboard/model.py b/grafana_dashboard/model.py similarity index 100% rename from src/grafana_dashboard/model.py rename to grafana_dashboard/model.py diff --git a/setup.py b/setup.py index 5990fcf..163ae3a 100644 --- a/setup.py +++ b/setup.py @@ -5,7 +5,7 @@ setuptools.setup( name="grafana-dashboard-templater", - version="1.0.1", + version="1.0.2", author="Pascal Zimmermann", author_email="info@theiotstudio.com", description="A Grafana dashboard templater", @@ -20,8 +20,7 @@ "License :: OSI Approved", "Operating System :: OS Independent", ], - package_dir={"": "src"}, - packages=setuptools.find_packages(where="src"), + packages=["grafana_dashboard"], install_requires=["jinja2"], python_requires=">=3.6", ) diff --git a/tests/test_dashboard.py b/tests/test_dashboard.py index af37b41..3337ec1 100644 --- a/tests/test_dashboard.py +++ b/tests/test_dashboard.py @@ -1,13 +1,15 @@ import logging import os -import unittest +import tempfile +from unittest import TestCase +from unittest.mock import MagicMock import jinja2 -from src.grafana_dashboard.model import Model -from src.grafana_dashboard.dashboard import Dashboard +from grafana_dashboard.model import Model +from grafana_dashboard.dashboard import Dashboard -class DashboardTestCase(unittest.TestCase): +class DashboardTestCase(TestCase): @staticmethod def __get_path_name() -> str: if os.path.basename(os.getcwd()) == "tests": @@ -55,9 +57,7 @@ def test_get_dashboard_json_successful(self): self.assertEqual("test", dashboard["templating"]["list"][1]["current"]["text"]) def test_get_dashboard_json_no_config_template_error(self): - template_path: str = ( - f"{os.path.dirname(os.getcwd())}{os.sep}dashboard" - ) + template_path: str = f"{os.path.dirname(os.getcwd())}{os.sep}dashboard" test_model: Model = Model(template_path, "database", "postgresql", "v13") test_dashboard: Dashboard = Dashboard(test_model) with self.assertRaises(jinja2.TemplateNotFound): @@ -73,6 +73,23 @@ def test_get_dashboard_json_no_template_values_error(self): with self.assertRaises(SystemExit): test_dashboard.get_dashboard_json({}) + def test__write_tmp_dashboard_json_write_not_possible(self): + template_path: str = DashboardTestCase.__get_path_name() + test_model: Model = Model(template_path, "database", "postgresql", "v13") + test_dashboard: Dashboard = Dashboard(test_model) + + with self.assertRaises(AttributeError): + with tempfile.NamedTemporaryFile() as tmp_file: + test_dashboard._Dashboard__write_tmp_dashboard_json( + tmp_file.name, + MagicMock, + {"app_name": "test", "prometheus_name": "test_name"}, + ) + + def test__get_dashboard_json_json_not_available(self): + template_path: str = DashboardTestCase.__get_path_name() + test_model: Model = Model(template_path, "database", "postgresql", "v13") + test_dashboard: Dashboard = Dashboard(test_model) -if __name__ == "__main__": - unittest.main() + with self.assertRaises(FileNotFoundError): + test_dashboard._Dashboard__get_dashboard_json("/tmp/dashboard1.json") diff --git a/tests/test_model.py b/tests/test_model.py index a757897..2d18993 100644 --- a/tests/test_model.py +++ b/tests/test_model.py @@ -1,9 +1,9 @@ -import unittest +from unittest import TestCase -from src.grafana_dashboard.model import Model +from grafana_dashboard.model import Model -class ModelTestCase(unittest.TestCase): +class ModelTestCase(TestCase): def test_model_successful(self): test_model: Model = Model("test1", "test2", "test3", "test4") self.assertEqual("test1", test_model.dashboard_templates_path) @@ -17,7 +17,3 @@ def test_model_error(self): self.assertNotEqual("test2", test_model.dashboard_type) self.assertNotEqual("test3", test_model.dashboard_version) self.assertNotEqual("test4", test_model.dashboard_templates_path) - - -if __name__ == "__main__": - unittest.main()