Add test suite for confgen
This commit is contained in:
139
app/tests/test_secrets.py
Normal file
139
app/tests/test_secrets.py
Normal file
@@ -0,0 +1,139 @@
|
|||||||
|
"""Tests for secrets interpolation."""
|
||||||
|
|
||||||
|
import os
|
||||||
|
import pytest
|
||||||
|
from unittest.mock import patch
|
||||||
|
|
||||||
|
from src.confgen.secrets import SecretsResolver
|
||||||
|
|
||||||
|
|
||||||
|
class TestSecretsResolver:
|
||||||
|
"""Tests for SecretsResolver."""
|
||||||
|
|
||||||
|
def setup_method(self):
|
||||||
|
"""Set up test fixtures."""
|
||||||
|
self.resolver = SecretsResolver()
|
||||||
|
|
||||||
|
def test_resolve_env_var(self):
|
||||||
|
"""Test resolving environment variable placeholders."""
|
||||||
|
os.environ["TEST_SECRET"] = "my_secret_value"
|
||||||
|
content = "password: {{env.TEST_SECRET}}"
|
||||||
|
|
||||||
|
result = self.resolver.resolve(content)
|
||||||
|
|
||||||
|
assert "password: my_secret_value" in result
|
||||||
|
del os.environ["TEST_SECRET"]
|
||||||
|
|
||||||
|
def test_resolve_multiple_env_vars(self):
|
||||||
|
"""Test resolving multiple environment variables."""
|
||||||
|
os.environ["DB_HOST"] = "localhost"
|
||||||
|
os.environ["DB_PORT"] = "5432"
|
||||||
|
content = "host: {{env.DB_HOST}}\nport: {{env.DB_PORT}}"
|
||||||
|
|
||||||
|
result = self.resolver.resolve(content)
|
||||||
|
|
||||||
|
assert "host: localhost" in result
|
||||||
|
assert "port: 5432" in result
|
||||||
|
del os.environ["DB_HOST"]
|
||||||
|
del os.environ["DB_PORT"]
|
||||||
|
|
||||||
|
def test_resolve_missing_env_var_raises_error(self):
|
||||||
|
"""Test that missing environment variable raises an error."""
|
||||||
|
content = "password: {{env.NONEXISTENT_SECRET}}"
|
||||||
|
|
||||||
|
with pytest.raises(ValueError, match="Environment variable 'NONEXISTENT_SECRET' not found"):
|
||||||
|
self.resolver.resolve(content)
|
||||||
|
|
||||||
|
def test_resolve_with_prefixed_env_var(self):
|
||||||
|
"""Test resolving environment variables with CONFGEN_ prefix."""
|
||||||
|
os.environ["CONFGEN_MY_SECRET"] = "prefixed_secret"
|
||||||
|
content = "password: {{env.MY_SECRET}}"
|
||||||
|
|
||||||
|
result = self.resolver.resolve(content)
|
||||||
|
|
||||||
|
assert "password: prefixed_secret" in result
|
||||||
|
del os.environ["CONFGEN_MY_SECRET"]
|
||||||
|
|
||||||
|
def test_get_secret_names(self):
|
||||||
|
"""Test extracting secret names from content."""
|
||||||
|
content = """
|
||||||
|
password: {{env.DB_PASSWORD}}
|
||||||
|
api_key: {{env.API_KEY}}
|
||||||
|
token: {{vault.SECRET_TOKEN}}
|
||||||
|
"""
|
||||||
|
names = self.resolver.get_secret_names(content)
|
||||||
|
|
||||||
|
assert "DB_PASSWORD" in names
|
||||||
|
assert "API_KEY" in names
|
||||||
|
assert "SECRET_TOKEN" in names
|
||||||
|
|
||||||
|
def test_is_secret_placeholder(self):
|
||||||
|
"""Test detecting secret placeholders."""
|
||||||
|
assert self.resolver.is_secret_placeholder("{{env.SECRET_KEY}}") is True
|
||||||
|
assert self.resolver.is_secret_placeholder("{{vault.SECRET_KEY}}") is True
|
||||||
|
assert self.resolver.is_secret_placeholder("{{APP_NAME}}") is False
|
||||||
|
|
||||||
|
def test_check_secret_availability(self):
|
||||||
|
"""Test checking which secrets are available."""
|
||||||
|
os.environ["AVAILABLE_SECRET"] = "value"
|
||||||
|
content = "p1: {{env.AVAILABLE_SECRET}}\np2: {{env.UNAVAILABLE_SECRET}}"
|
||||||
|
|
||||||
|
availability = self.resolver.check_secret_availability(content)
|
||||||
|
|
||||||
|
assert availability["AVAILABLE_SECRET"] is True
|
||||||
|
assert availability["UNAVAILABLE_SECRET"] is False
|
||||||
|
del os.environ["AVAILABLE_SECRET"]
|
||||||
|
|
||||||
|
def test_resolve_with_no_secrets(self):
|
||||||
|
"""Test resolving content without secrets."""
|
||||||
|
content = "app_name: {{APP_NAME}}\nport: {{PORT}}"
|
||||||
|
variables = {"APP_NAME": "myapp", "PORT": "8080"}
|
||||||
|
|
||||||
|
from src.confgen.template import TemplateEngine
|
||||||
|
|
||||||
|
engine = TemplateEngine()
|
||||||
|
result = engine.render(content, variables)
|
||||||
|
|
||||||
|
assert result == "app_name: myapp\nport: 8080"
|
||||||
|
|
||||||
|
def test_resolve_vault_secret_without_config(self):
|
||||||
|
"""Test that vault secrets without config raise an error."""
|
||||||
|
content = "api_key: {{vault.SECRET_API_KEY}}"
|
||||||
|
|
||||||
|
with pytest.raises(ValueError, match="Vault not configured"):
|
||||||
|
self.resolver.resolve(content)
|
||||||
|
|
||||||
|
@patch("src.confgen.secrets.SecretsResolver._get_from_vault")
|
||||||
|
def test_resolve_vault_secret_with_config(self, mock_get):
|
||||||
|
"""Test resolving vault secrets when configured."""
|
||||||
|
os.environ["CONFGEN_VAULT_URL"] = "http://localhost:8200"
|
||||||
|
os.environ["CONFGEN_VAULT_TOKEN"] = "test-token"
|
||||||
|
mock_get.return_value = "vault_secret_value"
|
||||||
|
content = "api_key: {{vault.SECRET_API_KEY}}"
|
||||||
|
|
||||||
|
result = self.resolver.resolve(content)
|
||||||
|
|
||||||
|
assert "api_key: vault_secret_value" in result
|
||||||
|
del os.environ["CONFGEN_VAULT_URL"]
|
||||||
|
del os.environ["CONFGEN_VAULT_TOKEN"]
|
||||||
|
|
||||||
|
def test_resolve_mixed_placeholders(self):
|
||||||
|
"""Test resolving mixed variable and secret placeholders."""
|
||||||
|
os.environ["DB_PASSWORD"] = "secret123"
|
||||||
|
content = """
|
||||||
|
app_name: {{APP_NAME}}
|
||||||
|
database:
|
||||||
|
host: {{DB_HOST}}
|
||||||
|
password: {{env.DB_PASSWORD}}
|
||||||
|
"""
|
||||||
|
|
||||||
|
from src.confgen.template import TemplateEngine
|
||||||
|
|
||||||
|
engine = TemplateEngine()
|
||||||
|
resolved = self.resolver.resolve(content)
|
||||||
|
rendered = engine.render(resolved, {"APP_NAME": "myapp", "DB_HOST": "localhost"})
|
||||||
|
|
||||||
|
assert "app_name: myapp" in rendered
|
||||||
|
assert "host: localhost" in rendered
|
||||||
|
assert "password: secret123" in rendered
|
||||||
|
del os.environ["DB_PASSWORD"]
|
||||||
Reference in New Issue
Block a user