test_bootstrap.py 2.7 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788
  1. import pytest
  2. from flask import Flask
  3. from app.runner.bootstrap import (
  4. register_artifact_cleanup_cli,
  5. runner_settings_from_env,
  6. )
  7. def test_runner_settings_require_signing_secret_and_explicit_dependencies(
  8. monkeypatch,
  9. ):
  10. required = {
  11. "DATABASE_URL": "postgresql://platform",
  12. "NEO4J_URI": "bolt://neo4j:7687",
  13. "NEO4J_USER": "neo4j",
  14. "NEO4J_PASSWORD": "test",
  15. "DATASOURCE_CREDENTIAL_MASTER_KEY": (
  16. "MDEyMzQ1Njc4OWFiY2RlZjAxMjM0NTY3ODlhYmNkZWY="
  17. ),
  18. "DATASOURCE_CREDENTIAL_KEY_VERSION": "v1",
  19. "RUNNER_TASK_TOKEN_SECRET": "x" * 32,
  20. "RUNNER_HTTP_ALLOWED_HOSTS": "events.internal, audit.internal",
  21. "RUNNER_MINIO_HOST": "minio:9000",
  22. "RUNNER_MINIO_USER": "runner-test",
  23. "RUNNER_MINIO_PASSWORD": "runner-test-password",
  24. "RUNNER_MINIO_BUCKET": "dataops-rules",
  25. }
  26. for key, value in required.items():
  27. monkeypatch.setenv(key, value)
  28. settings = runner_settings_from_env()
  29. assert settings.runtime.pool_size == 1
  30. assert settings.runtime.max_overflow == 1
  31. assert settings.runtime.max_idle_pools == 4
  32. assert settings.allowed_http_hosts == {
  33. "events.internal",
  34. "audit.internal",
  35. }
  36. assert settings.artifact_bucket == "dataops-rules"
  37. assert "postgresql://platform" not in repr(settings)
  38. assert required["RUNNER_TASK_TOKEN_SECRET"] not in repr(settings)
  39. assert required["RUNNER_MINIO_PASSWORD"] not in repr(settings)
  40. def test_runner_refuses_to_start_without_a_task_token_secret(monkeypatch):
  41. monkeypatch.delenv("RUNNER_TASK_TOKEN_SECRET", raising=False)
  42. with pytest.raises(ValueError, match="RUNNER_TASK_TOKEN_SECRET"):
  43. runner_settings_from_env()
  44. def test_runner_registers_bounded_artifact_reconciliation_cli():
  45. class Resolver:
  46. def __init__(self):
  47. self.limit = None
  48. self.grace_seconds = None
  49. def reconcile(self, *, limit, grace_seconds):
  50. self.limit = limit
  51. self.grace_seconds = grace_seconds
  52. return {
  53. "pending_finalized": 1,
  54. "pending_deleted": 1,
  55. "ready_failed": 1,
  56. "orphans_deleted": 1,
  57. }
  58. resolver = Resolver()
  59. app = Flask("runner-cleanup-test")
  60. register_artifact_cleanup_cli(app, resolver)
  61. result = app.test_cli_runner().invoke(
  62. args=[
  63. "reconcile-rule-artifacts",
  64. "--limit",
  65. "25",
  66. "--grace-seconds",
  67. "600",
  68. ]
  69. )
  70. assert result.exit_code == 0
  71. assert "pending_finalized=1" in result.output
  72. assert "orphans_deleted=1" in result.output
  73. assert resolver.limit == 25
  74. assert resolver.grace_seconds == 600