87 lines
3.2 KiB
Python
87 lines
3.2 KiB
Python
from __future__ import annotations
|
|
|
|
from typing import Any
|
|
|
|
from django.db import transaction
|
|
from django.utils import timezone
|
|
|
|
from .client import CatalogPlugin
|
|
from .lifecycle import LifecycleRequest
|
|
from .models import LifecycleAudit, ManagedPlugin
|
|
from .redaction import redact_data, redact_text
|
|
|
|
|
|
class DjangoLifecycleRepository:
|
|
def has_other_pending_mutation(self, slug: str, audit_id: int) -> bool:
|
|
return LifecycleAudit.objects.filter(
|
|
slug=slug,
|
|
dry_run=False,
|
|
status=LifecycleAudit.Status.HANDED_OFF,
|
|
).exclude(pk=audit_id).exists()
|
|
|
|
def create_audit(self, request: LifecycleRequest, actor_id: int | None) -> int:
|
|
audit = LifecycleAudit.objects.create(
|
|
actor_id=actor_id,
|
|
slug=request.slug,
|
|
action=request.action,
|
|
requested_version=request.version,
|
|
dry_run=request.dry_run,
|
|
request_data={
|
|
"slug": request.slug,
|
|
"action": request.action,
|
|
"version": request.version,
|
|
"dry_run": request.dry_run,
|
|
},
|
|
)
|
|
return audit.pk
|
|
|
|
def mark_running(self, audit_id: int) -> None:
|
|
LifecycleAudit.objects.filter(pk=audit_id).update(
|
|
status=LifecycleAudit.Status.RUNNING,
|
|
started=timezone.now(),
|
|
error="",
|
|
)
|
|
|
|
def mark_success(self, audit_id: int, result: dict[str, Any]) -> None:
|
|
LifecycleAudit.objects.filter(pk=audit_id).update(
|
|
status=LifecycleAudit.Status.SUCCEEDED,
|
|
result_data=redact_data(result),
|
|
completed=timezone.now(),
|
|
)
|
|
|
|
def mark_handed_off(self, audit_id: int, operation_id: str, result: dict[str, Any]) -> None:
|
|
LifecycleAudit.objects.filter(pk=audit_id).update(
|
|
status=LifecycleAudit.Status.HANDED_OFF,
|
|
external_operation_id=operation_id,
|
|
result_data=redact_data(result),
|
|
)
|
|
|
|
def mark_failed(self, audit_id: int, error: str, result: dict[str, Any]) -> None:
|
|
LifecycleAudit.objects.filter(pk=audit_id).update(
|
|
status=LifecycleAudit.Status.FAILED,
|
|
error=redact_text(error, limit=8_000),
|
|
result_data=redact_data(result),
|
|
completed=timezone.now(),
|
|
)
|
|
|
|
@transaction.atomic
|
|
def update_status(self, plugin: CatalogPlugin, **values: Any) -> None:
|
|
safe_values = {
|
|
"name": plugin.name,
|
|
"package_name": plugin.package_name,
|
|
"import_name": plugin.import_name,
|
|
"repository_url": plugin.repository_url,
|
|
"available_version": plugin.latest_version,
|
|
"last_checked": timezone.now(),
|
|
**values,
|
|
}
|
|
if "last_error" in safe_values:
|
|
safe_values["last_error"] = redact_text(safe_values["last_error"], limit=4_000)
|
|
obj = ManagedPlugin.objects.select_for_update().filter(slug=plugin.slug).first()
|
|
if obj is None:
|
|
ManagedPlugin.objects.create(slug=plugin.slug, **safe_values)
|
|
else:
|
|
for key, value in safe_values.items():
|
|
setattr(obj, key, value)
|
|
obj.save(update_fields=tuple(safe_values) + ("updated",))
|