Files
govoplan-files/tests/test_configuration_provider.py
zemion 6176e9f40e
Module Package Release / publish-packages (push) Successful in 12s
feat: inventory storage infrastructure dependencies
2026-08-24 14:56:33 +02:00

289 lines
10 KiB
Python

from __future__ import annotations
from pathlib import Path
from types import SimpleNamespace
import tempfile
import unittest
from sqlalchemy import create_engine
from govoplan_core.core.configuration_packages import (
ConfigurationPackageFragment,
ConfigurationPreflightContext,
)
from govoplan_core.core.infrastructure_capabilities import (
infrastructure_capability_receipt_from_mapping,
)
from govoplan_core.db.base import Base
from govoplan_core.db.session import configure_database, reset_database
from govoplan_files.backend.configuration_provider import (
FILES_CONFIGURATION_CAPABILITY,
FILES_INFRASTRUCTURE_DEPENDENCY_CAPABILITY,
FilesConfigurationProvider,
)
from govoplan_files.backend.db.models import FileBlob
from govoplan_files.backend.manifest import manifest
def _receipt(*, source: str = "host-local", state: str = "configured"):
endpoint = (
{"kind": "filesystem", "reference": "volume:files-data"}
if source == "host-local"
else {"scheme": "http", "host": "garage", "port": 3900}
)
secret_refs = (
[]
if source == "host-local"
else [
"env:FILE_STORAGE_S3_ACCESS_KEY_ID",
"env:FILE_STORAGE_S3_SECRET_ACCESS_KEY",
"env:GARAGE_RPC_SECRET",
]
)
return infrastructure_capability_receipt_from_mapping(
{
"schema_version": 1,
"installation_id": "files-provider-test",
"profile": "evaluation",
"capabilities": [
{
"id": "files.storage",
"label": "Managed file content storage",
"state": state,
"source": source,
"detail": "Deployment-owned storage binding.",
"endpoint": endpoint,
"secret_refs": secret_refs,
"dependent_modules": ["files"],
}
],
"post_install_tasks": [],
}
)
def _local_settings(**overrides):
values = {
"file_storage_backend": "local",
"file_storage_local_root": "/var/lib/govoplan/files",
}
values.update(overrides)
return SimpleNamespace(**values)
def _s3_settings(**overrides):
values = {
"file_storage_backend": "s3",
"file_storage_s3_endpoint_url": "http://garage:3900",
"file_storage_s3_bucket": "files",
"file_storage_s3_deployment_managed": True,
"file_storage_s3_endpoint_trusted": False,
}
values.update(overrides)
return SimpleNamespace(**values)
class FilesConfigurationProviderTests(unittest.TestCase):
def test_provider_is_registered(self) -> None:
self.assertIn(FILES_CONFIGURATION_CAPABILITY, manifest.capability_factories)
self.assertIn(
FILES_INFRASTRUCTURE_DEPENDENCY_CAPABILITY,
manifest.capability_factories,
)
def test_inventory_reports_runtime_binding_and_persisted_blob_aggregate(self) -> None:
with tempfile.TemporaryDirectory(prefix="govoplan-files-inventory-") as root:
database_path = Path(root) / "files.sqlite3"
engine = create_engine(f"sqlite:///{database_path}")
Base.metadata.create_all(engine, tables=(FileBlob.__table__,))
configure_database(
f"sqlite:///{database_path}",
engine=engine,
dispose_previous=True,
)
try:
with engine.begin() as connection:
connection.execute(
FileBlob.__table__.insert(),
[
{
"id": "blob-1",
"tenant_id": "tenant-1",
"storage_backend": "local",
"storage_key": "tenant-1/a",
"checksum_sha256": "a" * 64,
"size_bytes": 7,
"protection_discriminator": "plaintext",
"ref_count": 1,
"integrity_status": "unchecked",
},
{
"id": "blob-2",
"tenant_id": "tenant-1",
"storage_backend": "local",
"storage_key": "tenant-1/b",
"checksum_sha256": "b" * 64,
"size_bytes": 11,
"protection_discriminator": "plaintext",
"ref_count": 1,
"integrity_status": "unchecked",
},
],
)
provider = FilesConfigurationProvider(
settings=_local_settings(),
environment={},
)
dependencies = provider.infrastructure_dependencies()
finally:
reset_database()
engine.dispose()
self.assertEqual(
["runtime_storage_binding", "stored_blob_set"],
[item.dependency_type for item in dependencies],
)
blob_set = dependencies[1]
self.assertEqual(2, blob_set.metrics["blob_count"])
self.assertEqual(18, blob_set.metrics["content_bytes"])
def test_matching_local_storage_is_an_idempotent_noop(self) -> None:
provider = FilesConfigurationProvider(
settings=_local_settings(),
environment={},
)
context = ConfigurationPreflightContext(
infrastructure_receipt=_receipt(),
)
fragment = ConfigurationPackageFragment(
module_id="files",
fragment_type="managed_storage",
fragment_id="files-storage",
payload={
"expected_backend": "local",
"expected_source": "host-local",
},
)
first = provider.preflight(fragment, context)
applied = provider.apply(fragment, {}, context)
second = provider.preflight(fragment, context)
self.assertEqual("skip", first.plan[0].action)
self.assertEqual("skip", second.plan[0].action)
self.assertEqual((), applied.diagnostics)
self.assertEqual({}, applied.created_refs)
self.assertEqual({}, applied.updated_refs)
def test_runtime_backend_mismatch_blocks_without_rewriting_settings(self) -> None:
settings = _local_settings()
provider = FilesConfigurationProvider(settings=settings, environment={})
context = ConfigurationPreflightContext(
infrastructure_receipt=_receipt(source="installer-managed-garage"),
)
fragment = ConfigurationPackageFragment(
module_id="files",
fragment_type="managed_storage",
payload={},
)
result = provider.preflight(fragment, context)
self.assertEqual("blocked", result.plan[0].action)
self.assertIn(
"files_storage_runtime_mismatch",
{item.code for item in result.diagnostics},
)
self.assertEqual("local", settings.file_storage_backend)
def test_garage_binding_requires_only_files_secret_references(self) -> None:
fragment = ConfigurationPackageFragment(
module_id="files",
fragment_type="managed_storage",
payload={},
)
context = ConfigurationPreflightContext(
infrastructure_receipt=_receipt(source="installer-managed-garage"),
)
missing = FilesConfigurationProvider(
settings=_s3_settings(),
environment={},
).preflight(fragment, context)
available = FilesConfigurationProvider(
settings=_s3_settings(),
environment={
"FILE_STORAGE_S3_ACCESS_KEY_ID": "reference-resolved",
"FILE_STORAGE_S3_SECRET_ACCESS_KEY": "reference-resolved",
},
).preflight(fragment, context)
self.assertEqual("blocked", missing.plan[0].action)
self.assertEqual(
2,
sum(
item.code == "files_storage_secret_reference_unresolved"
for item in missing.diagnostics
),
)
self.assertEqual("skip", available.plan[0].action)
def test_operator_supplied_s3_requires_explicit_endpoint_trust(self) -> None:
receipt = _receipt(source="operator-supplied-s3", state="externally_supplied")
fragment = ConfigurationPackageFragment(
module_id="files",
fragment_type="managed_storage",
payload={},
)
context = ConfigurationPreflightContext(infrastructure_receipt=receipt)
environment = {
"FILE_STORAGE_S3_ACCESS_KEY_ID": "reference-resolved",
"FILE_STORAGE_S3_SECRET_ACCESS_KEY": "reference-resolved",
}
blocked = FilesConfigurationProvider(
settings=_s3_settings(
file_storage_s3_deployment_managed=False,
file_storage_s3_endpoint_trusted=False,
),
environment=environment,
).preflight(fragment, context)
ready = FilesConfigurationProvider(
settings=_s3_settings(
file_storage_s3_deployment_managed=False,
file_storage_s3_endpoint_trusted=True,
),
environment=environment,
).preflight(fragment, context)
self.assertEqual("blocked", blocked.plan[0].action)
self.assertIn(
"files_storage_trust_boundary_missing",
{item.code for item in blocked.diagnostics},
)
self.assertEqual("skip", ready.plan[0].action)
def test_inline_storage_secret_is_rejected(self) -> None:
provider = FilesConfigurationProvider(
settings=_local_settings(),
environment={},
)
result = provider.preflight(
ConfigurationPackageFragment(
module_id="files",
fragment_type="managed_storage",
payload={"secret_access_key": "inline"},
),
ConfigurationPreflightContext(infrastructure_receipt=_receipt()),
)
self.assertEqual("blocked", result.plan[0].action)
self.assertIn(
"files_configuration_secret_forbidden",
{item.code for item in result.diagnostics},
)
if __name__ == "__main__":
unittest.main()