This commit is contained in:
@@ -22,6 +22,7 @@ from cloud.auth import (
|
||||
NullAuthProvider,
|
||||
Principal,
|
||||
)
|
||||
from cloud.governance import TaskSubmissionPolicyError, enforce_user_submission_policy
|
||||
from cloud.sdk.models import (
|
||||
DeviceResponse,
|
||||
ErrorResponse,
|
||||
@@ -94,8 +95,21 @@ def create_cloud_router(
|
||||
payload: TaskSubmissionRequest,
|
||||
request: Request,
|
||||
) -> TaskSubmissionResponse:
|
||||
_authorize(request, TASKS_SUBMIT_SCOPE)
|
||||
task_constraints = _build_constraints(payload.constraints)
|
||||
principal = _authorize(request, TASKS_SUBMIT_SCOPE)
|
||||
try:
|
||||
task_constraints = _build_constraints(payload.constraints)
|
||||
_validate_task_target(pool, task_constraints)
|
||||
_enforce_user_policy(principal, scheduler.store, task_constraints)
|
||||
except TaskSubmissionPolicyError as exc:
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_403_FORBIDDEN,
|
||||
detail=str(exc),
|
||||
) from exc
|
||||
except ValueError as exc:
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_400_BAD_REQUEST,
|
||||
detail=str(exc),
|
||||
) from exc
|
||||
try:
|
||||
task_id = scheduler.submit(
|
||||
goal=payload.goal,
|
||||
@@ -128,6 +142,8 @@ def create_cloud_router(
|
||||
attempt_count=task.attempt_count,
|
||||
lease_expires_at=task.lease_expires_at,
|
||||
failure_reason=task.failure_reason,
|
||||
target_host_id=task.constraints.target_host_id,
|
||||
target_device_id=task.constraints.target_device_id,
|
||||
)
|
||||
|
||||
@router.get("/tasks", response_model=TaskListResponse)
|
||||
@@ -158,6 +174,8 @@ def create_cloud_router(
|
||||
assigned_host_id=task.assigned_host_id,
|
||||
attempt_count=task.attempt_count,
|
||||
failure_reason=task.failure_reason,
|
||||
target_host_id=task.constraints.target_host_id,
|
||||
target_device_id=task.constraints.target_device_id,
|
||||
created_at=task.created_at,
|
||||
)
|
||||
for task in tasks
|
||||
@@ -303,4 +321,35 @@ def _build_constraints(model):
|
||||
return TaskConstraints(
|
||||
driver_type=model.driver_type,
|
||||
capability_tags=list(model.capability_tags),
|
||||
target_host_id=model.target_host_id,
|
||||
target_device_id=model.target_device_id,
|
||||
)
|
||||
|
||||
|
||||
def _validate_task_target(pool, constraints) -> None:
|
||||
if constraints.target_device_id and not constraints.target_host_id:
|
||||
raise ValueError("target_device_id requires target_host_id")
|
||||
if constraints.target_host_id is None:
|
||||
return
|
||||
if not any(host.host_id == constraints.target_host_id for host in pool.list_hosts()):
|
||||
raise ValueError(f"target host {constraints.target_host_id!r} is not known")
|
||||
if constraints.target_device_id is not None and not any(
|
||||
device.host_id == constraints.target_host_id
|
||||
and device.device_id == constraints.target_device_id
|
||||
for device in pool.list_devices()
|
||||
):
|
||||
raise ValueError(
|
||||
f"target device {constraints.target_device_id!r} is not owned by "
|
||||
f"host {constraints.target_host_id!r}"
|
||||
)
|
||||
|
||||
|
||||
def _enforce_user_policy(principal, store, constraints) -> None:
|
||||
if not principal.id.startswith("user:"):
|
||||
return
|
||||
policy = store.get_user_submission_policy(principal.id.removeprefix("user:"))
|
||||
enforce_user_submission_policy(
|
||||
policy,
|
||||
target_host_id=constraints.target_host_id,
|
||||
target_device_id=constraints.target_device_id,
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user