Page Menu
Home
DevCentral
Search
Configure Global Search
Log In
Files
F13143154
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Flag For Later
Size
12 KB
Referenced Files
None
Subscribers
None
View Options
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
Details
Attached
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)
Attached To
Mode
rOPS Nasqueron Operations
Attached
Detach File
Event Timeline
Log In to Comment