Files
homelab/tests/test_netbird_runtime.py
T
forust 8729cb5062
ci / validate (push) Skipped
ci / lint-prettier (push) Skipped
ci / lint-ruff (push) Skipped
ci / lint-yaml (push) Skipped
ci / lint-dockerfiles (push) Skipped
renovate-ci / validate-renovate (push) Skipped
renovate-ci / validate-renovate (pull_request) Skipped
ci / lint-compose (pull_request) Successful in 12s
ci / lint-actionlint (pull_request) Successful in 8s
ci / lint-shellcheck (pull_request) Successful in 21s
ci / lint-prettier (pull_request) Successful in 17s
ci / lint-ruff (pull_request) Successful in 6s
ci / lint-yaml (pull_request) Successful in 9s
ci / lint-dockerfiles (pull_request) Successful in 5s
ci / validate (pull_request) Successful in 6s
ci / build (pull_request) Skipped
fix(netbird): restore Compose setup and server entrypoint
2026-10-06 15:08:46 +00:00

88 lines
3.7 KiB
Python

"""Exercise local setup and config rendering without a Docker daemon."""
import os
import shutil
import subprocess
import tempfile
import unittest
from pathlib import Path
ROOT = Path(__file__).resolve().parents[1]
class NetbirdRuntimeTests(unittest.TestCase):
def setUp(self):
self.temp = tempfile.TemporaryDirectory()
self.addCleanup(self.temp.cleanup)
self.root = Path(self.temp.name)
self.stack = self.root / 'netbird'
self.stack.mkdir()
for name in ('setup.sh', '.env.example', 'config.template.yaml'):
shutil.copy(ROOT / 'netbird' / name, self.stack / name)
binary = self.root / 'bin'
binary.mkdir()
docker = binary / 'docker'
docker.write_text('#!/bin/sh\nprintf "%s\\n" 172.20.0.0/16\n')
docker.chmod(0o755)
self.env = dict(os.environ, PATH=f'{binary}:{os.environ["PATH"]}')
def setup(self):
return subprocess.run( # noqa: S603 - executes the repository script copied into this test's temp dir
['/bin/bash', str(self.stack / 'setup.sh')], env=self.env, capture_output=True, check=False
)
def test_setup_preserves_existing_secrets_and_env(self):
self.assertEqual(self.setup().returncode, 0)
paths = [self.stack / '.env', *sorted((self.stack / 'secrets').iterdir())]
before = [p.read_bytes() for p in paths]
self.assertIn(b'NETBIRD_PROXY_SUBNET=172.20.0.0/16', before[0])
self.assertEqual(self.setup().returncode, 0)
self.assertEqual(before, [p.read_bytes() for p in paths])
for p in paths[1:]:
self.assertEqual(p.stat().st_mode & 0o777, 0o600)
def test_setup_rejects_empty_existing_secret(self):
(self.stack / 'secrets').mkdir()
secret = self.stack / 'secrets/datastore-encryption-key'
secret.touch()
self.assertNotEqual(self.setup().returncode, 0)
self.assertEqual(secret.read_bytes(), b'')
def render(self, subnet):
self.assertEqual(self.setup().returncode, 0)
rendered = self.root / 'run/config.yaml'
script = (ROOT / 'netbird/entrypoint.sh').read_text()
replacements = {
'/opt/netbird/config.template.yaml': str(self.stack / 'config.template.yaml'),
'/run/netbird/config.yaml': str(rendered),
'/run/secrets/relay_auth_secret': str(self.stack / 'secrets/relay-auth-secret'),
'/run/secrets/datastore_encryption_key': str(self.stack / 'secrets/datastore-encryption-key'),
'/go/bin/netbird-server': '/bin/true',
}
for original, local in replacements.items():
script = script.replace(original, local)
result = subprocess.run( # noqa: S603 - repository renderer, with test-local paths
['/bin/sh', '-c', script, 'entrypoint', '--config', str(rendered)],
env=dict(self.env, NETBIRD_DOMAIN='nb.example.com', NETBIRD_PROXY_SUBNET=subnet),
capture_output=True,
check=False,
)
return result, rendered
def test_renderer_replaces_placeholders_and_restricts_file_permissions(self):
result, rendered = self.render('172.20.0.0/16')
self.assertEqual(result.returncode, 0, result.stderr)
self.assertNotIn('__NETBIRD_', rendered.read_text())
self.assertIn('nb.example.com', rendered.read_text())
self.assertEqual(rendered.stat().st_mode & 0o777, 0o600)
def test_renderer_rejects_auto_and_default_route(self):
for subnet in ('auto', '0.0.0.0/0', '999.1.1.1/24'):
with self.subTest(subnet=subnet):
result, _ = self.render(subnet)
self.assertNotEqual(result.returncode, 0)
if __name__ == '__main__':
unittest.main()