220 lines
7.5 KiB
Python
220 lines
7.5 KiB
Python
from __future__ import annotations
|
|
|
|
from types import SimpleNamespace
|
|
import unittest
|
|
|
|
from govoplan_core.core.configuration_packages import (
|
|
ConfigurationPackageFragment,
|
|
ConfigurationPreflightContext,
|
|
)
|
|
from govoplan_core.core.infrastructure_capabilities import (
|
|
infrastructure_capability_receipt_from_mapping,
|
|
)
|
|
from govoplan_files.backend.configuration_provider import (
|
|
FILES_CONFIGURATION_CAPABILITY,
|
|
FilesConfigurationProvider,
|
|
)
|
|
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)
|
|
|
|
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()
|