Page MenuHomeDevCentral

No OneTemporary

diff --git a/_tests/Makefile b/_tests/Makefile
index bf7df8e..288c3f2 100644
--- a/_tests/Makefile
+++ b/_tests/Makefile
@@ -1,34 +1,34 @@
CURRENT_DIR != pwd
MODULES_DIR = ${CURRENT_DIR}/../_modules
test: test-python test-roles test-bats
test-python: test-modules test-pillar test-python-scripts
test-modules:
PYTHONPATH="${CURRENT_DIR}:${MODULES_DIR}" python -m unittest discover modules
test-pillar:
- python -m unittest discover pillar
+ PYTHONPATH="${CURRENT_DIR}" python -m unittest discover pillar
test-python-scripts:
PYTHONPATH="${CURRENT_DIR}" python -m unittest discover scripts/python
test-bats:
bats scripts/bats/test_edit_acme_dns_accounts.sh
# -------------------------------------------------------------
# Tests for roles
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
test-roles: test-roles-dns
test-roles-dns:
roles/python/dns/run_test_dns_zones.sh
# -------------------------------------------------------------
# Configuration test specific to the primary server
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
test-config:
cd config/salt-primary && make test
diff --git a/_tests/helpers.py b/_tests/helpers.py
index 1b8fe9a..6681ddd 100644
--- a/_tests/helpers.py
+++ b/_tests/helpers.py
@@ -1,30 +1,66 @@
# -------------------------------------------------------------
# Helper utilities for tests suite
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
# Project: Nasqueron
# License: 0BSD for import_from_path
+# BSD-2-Clause for load_pillar*
# Reference: http://docs.python.org/3/library/importlib.html
# -------------------------------------------------------------
import importlib.util
+import os
import sys
+from typing import Dict, List
+
+import yaml
# -------------------------------------------------------------
# Import mechanics
#
# Supersede importlib.machinery.SourceFileLoader load_module use
# to maintain compatibility with Python 3.12+
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
def import_from_path(module_name, file_path):
file_final_path = "../" + file_path
spec = importlib.util.spec_from_file_location(module_name, file_final_path)
module = importlib.util.module_from_spec(spec)
sys.modules[module_name] = module
spec.loader.exec_module(module)
return module
+
+
+# -------------------------------------------------------------
+# Pillar helpers
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+
+def load_pillar_files(pillar_directory: str) -> List:
+ pillar_files = []
+
+ for dir_path, dir_names, file_names in os.walk(pillar_directory):
+ files = [
+ os.path.join(dir_path, file_name)
+ for file_name in file_names
+ if file_name.endswith(".sls")
+ ]
+
+ pillar_files.extend(files)
+
+ return pillar_files
+
+
+def load_pillar(file_path: str) -> Dict:
+ with open(file_path) as fd:
+ return yaml.safe_load(fd)
+
+
+def load_pillars(directory_path) -> Dict:
+ pillar_files = load_pillar_files(directory_path)
+
+ return {file_path: load_pillar(file_path) for file_path in pillar_files}
diff --git a/_tests/pillar/dbserver/__init__.py b/_tests/pillar/dbserver/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/_tests/pillar/dbserver/test_postgresql.py b/_tests/pillar/dbserver/test_postgresql.py
new file mode 100644
index 0000000..2ea2415
--- /dev/null
+++ b/_tests/pillar/dbserver/test_postgresql.py
@@ -0,0 +1,72 @@
+#!/usr/bin/env python3
+
+# -------------------------------------------------------------
+# Tests for dbserver pillar, PostgreSQL flavour
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Project: Nasqueron
+# Description: Checks for PostgreSQL pillar coherence
+# License: BSD-2-Clause
+# -------------------------------------------------------------
+
+
+import unittest
+from unittest_data_provider import data_provider
+
+from helpers import load_pillars
+
+
+# -------------------------------------------------------------
+# Connection keys
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+
+MANDATORY_CONNECTION_KEYS = [
+ "db",
+ "user",
+ "ips",
+]
+
+OPTIONAL_CONNECTION_KEYS = [
+ "method",
+]
+
+ALL_CONNECTION_KEYS = MANDATORY_CONNECTION_KEYS + OPTIONAL_CONNECTION_KEYS
+
+
+# -------------------------------------------------------------
+# Tests
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+
+pillars = load_pillars("../pillar/dbserver/")
+
+
+class Testinstance(unittest.TestCase):
+ @staticmethod
+ def provide_pillars():
+ for file_path, pillar in pillars.items():
+ if "dbserver_postgresql" not in pillar:
+ continue
+
+ yield file_path, pillar["dbserver_postgresql"]
+
+ @data_provider(provide_pillars)
+ def test_connections(self, pillar_file_path, pillar):
+ for connection in pillar["connections"]:
+ for key in MANDATORY_CONNECTION_KEYS:
+ self.assertIn(
+ key, connection, f"Mandatory key missing in {pillar_file_path}"
+ )
+
+ for key in connection:
+ self.assertIn(
+ key,
+ ALL_CONNECTION_KEYS,
+ f"Unknown connection parameter in {pillar_file_path}",
+ )
+
+ self.assertIn(
+ "/",
+ connection["ips"],
+ f"Connection IP range should be in CIDR notation in {pillar_file_path}.",
+ )
diff --git a/_tests/roles/python/dns/run_test_dns_zones.sh b/_tests/roles/python/dns/run_test_dns_zones.sh
index c088b0f..b70a4f3 100755
--- a/_tests/roles/python/dns/run_test_dns_zones.sh
+++ b/_tests/roles/python/dns/run_test_dns_zones.sh
@@ -1,27 +1,30 @@
#!/bin/sh
# -------------------------------------------------------------
# Run roles/python/dns/test_dns_zones.py if kzonecheck exists
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
# Project: Nasqueron
# Description: Avoid to maintain both BSD and GNU Makefile
# for conditional logic .ifdef vs .if defined
# License: BSD-2-Clause
# -------------------------------------------------------------
KZONECHECK=kzonecheck
# -------------------------------------------------------------
# Program check
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
if ! command -v $KZONECHECK > /dev/null; then
echo "[WARNING] [SKIP] Skip testing roles/dns: kzonecheck missing" >&2
exit 0
fi
# -------------------------------------------------------------
# Run test
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+PYTHONPATH="$(pwd)"
+export PYTHONPATH
+
python roles/python/dns/test_dns_zones.py
diff --git a/_tests/roles/python/dns/test_dns_zones.py b/_tests/roles/python/dns/test_dns_zones.py
index c376303..8ef4511 100755
--- a/_tests/roles/python/dns/test_dns_zones.py
+++ b/_tests/roles/python/dns/test_dns_zones.py
@@ -1,169 +1,136 @@
#!/usr/bin/env python3
# -------------------------------------------------------------
# Tests for roles/dns files
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
# Project: Nasqueron
# Description: Checks for DNS zones
# License: BSD-2-Clause
# -------------------------------------------------------------
import os
import subprocess
import sys
import tempfile
-from typing import Dict, List
+from typing import Dict
from jinja2 import Environment, FileSystemLoader
import unittest
from unittest_data_provider import data_provider
-import yaml
-
-# -------------------------------------------------------------
-# Pillars helpers
-# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-
-
-PILLARS_DIRECTORY = "../pillar/dns/"
-
-
-def load_pillar_files(pillar_directory: str) -> List:
- pillar_files = []
-
- for dir_path, dir_names, file_names in os.walk(pillar_directory):
- files = [
- os.path.join(dir_path, file_name)
- for file_name in file_names
- if file_name.endswith(".sls")
- ]
-
- pillar_files.extend(files)
-
- return pillar_files
-
-
-def load_pillar(file_path: str) -> Dict:
- with open(file_path) as fd:
- return yaml.safe_load(fd)
-
-
-def load_pillars() -> Dict:
- pillar_files = load_pillar_files(PILLARS_DIRECTORY)
-
- return {file_path: load_pillar(file_path) for file_path in pillar_files}
+from helpers import load_pillars
# -------------------------------------------------------------
# Does zone file exist?
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
ZONE_FILES_DIR = "../roles/dns/knot/files/zones/"
def get_zone_file_path(zone_name: str) -> str:
return ZONE_FILES_DIR + zone_name + ".zone"
def is_existing_zone_file(zone_name: str) -> bool:
zone_file_path = get_zone_file_path(zone_name)
return os.path.exists(zone_file_path)
# -------------------------------------------------------------
# Jinja template
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
def build_context(pillar: str) -> Dict:
return {
# To sync with context from knotdns_file_... from roles/dns/knot/config.sls
"identity": pillar["dns_identity"],
"vars": pillar.get("dns_zone_variables", {}),
}
def resolve_zone_template(pillar: Dict, zone_name: str) -> str:
zone_path = get_zone_file_path(zone_name).replace("../", "")
engine = Environment(loader=FileSystemLoader(".."))
template = engine.get_template(zone_path)
context = build_context(pillar)
return template.render(context)
# -------------------------------------------------------------
# Call Knot utilities
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
def check_zone(file_content: str) -> bool:
"""Validate zone content with kzonecheck"""
with tempfile.NamedTemporaryFile(mode="w", delete=False) as tmp_fd:
tmp_fd.write(file_content)
try:
result = subprocess.run(
["kzonecheck", tmp_fd.name], capture_output=True, text=True
)
if result.returncode == 0:
return True
print(result.stdout, file=sys.stderr)
print(result.stderr, file=sys.stderr)
return False
finally:
os.remove(tmp_fd.name)
# -------------------------------------------------------------
# Tests
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-pillars = load_pillars()
+pillars = load_pillars("../pillar/dns/")
class Testinstance(unittest.TestCase):
@staticmethod
def provide_pillars():
for file_path, pillar in pillars.items():
yield (file_path, pillar)
@data_provider(provide_pillars)
def test_existing_zone_files(self, pillar_file_path, pillar):
for zone in pillar.get("dns_zones", []):
self.assertTrue(
is_existing_zone_file(zone), f"Missing zone file for {zone}"
)
@data_provider(provide_pillars)
def test_mandatory_fields(self, pillar_file_path, pillar):
self.assertIn(
"dns_identity", pillar, "Mandatory key, it should match the DNS server name"
)
@data_provider(provide_pillars)
def test_zone_content(self, pillar_file_path, pillar):
for zone in pillar.get("dns_zones", []):
zone_content = resolve_zone_template(pillar, zone)
zone_path = get_zone_file_path(zone)
result = check_zone(zone_content)
self.assertTrue(
result, f"Zone for {zone} doesn't pass Knot checks. Edit {zone_path}"
)
# -------------------------------------------------------------
# Application entry point
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
if __name__ == "__main__":
unittest.main()

File Metadata

Mime Type
text/x-diff
Expires
Fri, Nov 21, 16:26 (1 d, 7 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
3188513
Default Alt Text
(12 KB)

Event Timeline